DEV Community

Cover image for Scripta 3.4.7: schedule local meeting recordings without sending anything to the cloud
thehwang
thehwang Subscriber

Posted on

Scripta 3.4.7: schedule local meeting recordings without sending anything to the cloud

Follow-up to Building a 100% local meeting transcription app for macOS — Scripta already records dual-channel audio and summarizes with a local LLM. v3.4.7 adds something I kept forgetting to do myself: **hit Record before the meeting starts.

The problem

Scripta works great when I remember to open it and tap Start Recording. I do not always remember.

Recurring standups, interviews, and “just a quick sync” calls all have a start time on the calendar — but my muscle memory does not. Cloud assistants solve this by running in someone else’s datacenter. Scripta’s whole pitch is nothing leaves the Mac, so “schedule a bot in the cloud” was never an option.

What I wanted instead:

  • Name the meeting (“Product sync”, not 2026-09-25_16-50-00)
  • Pick start and end (or start + duration)
  • Let the app start and stop capture while it is running
  • Keep transcripts and metadata local, same as manual recording

That shipped in Scripta v3.4.7.

What it looks like

Open Scheduled Recordings from the toolbar calendar icon (or the menu bar):

Empty Scheduled Recordings panel with Add schedule

Create a meeting — title, window, language, optional notification if the app is not open at start time:

New schedule form

Upcoming items show status (Pending, Recording now, Waiting to start, etc.) with Edit, Cancel, or Stop recording when relevant:

Upcoming schedule with Pending status

When a scheduled session finishes, the export folder’s session.json includes a title and optional scheduledRecordingId, so Meeting History is searchable by name.

Product rules we locked in

These are intentional — not missing features for v3.5:

Rule Why
No overlapping schedules Saves fail validation if windows intersect
No auto-summary after scheduled stop Manual recordings still offer the summary sheet when Ollama is ready; scheduled runs set suppressAutoSummary so you are not interrupted
No takeover without consent If you are already recording at start time, Scripta asks whether to stop the current session and start the scheduled one
App must be running for auto-capture Phase 1 is in-process scheduling only — no launchd daemon silently recording in the background
If the app is closed at start time A local notification nudges you to open Scripta; it does not pretend recording happened

Calendar import, multi-device sync, and “record with zero UI process” are explicitly later phases.

How it works (implementation sketch)

Persistence is a single JSON file:

~/Library/Application Support/Scripta/schedules.json

A ScheduleCoordinator ticks about once per second while the app runs:

  1. Arm 5-minute local notifications for upcoming items
  2. At start → configure the recorder (title, language, no summary popup), then startRecording() if permissions are already granted
  3. At end → stopRecording() for that schedule’s session
  4. Reconcile stale states after quit/reopen (e.g. JSON said “recording” but capture never started)

Before auto-start, ScreenRecordingAccess checks mic, speech, and ScreenCaptureKit — scheduled paths avoid hammering the system permission dialog every second if you forgot to grant Screen Recording.

Recording still uses the same pipeline as manual mode: whisper.cpp on the mic, SFSpeechRecognizer on system audio via ScreenCaptureKit (architecture write-up).

Optional Awake (bottom bar, default on): while recording or finishing transcription, Scripta holds an NSProcessInfo activity to prevent idle system and display sleep — not a guarantee against lid-close or manual sleep, but enough for long calls at your desk.

Permissions: the real UX tax

The scheduler did not create new TCC categories — it surfaced the same ones as manual record:

  • Microphone
  • Screen Recording (required for system audio, even though we only capture audio)
  • Speech Recognition

Run Permissions Setup once before the meeting window. If auto-start fails, the list shows Waiting to start with Retry start after you fix settings and return to the app.

If you develop from source, install to /Applications/Scripta.app (scripts/install-local.sh) so TCC matches what users run in production. swift run binaries are a different story.

What we learned shipping it

  1. Do not flip @Published language on a background thread when auto-starting — SwiftUI will punish you with stack overflows in Release builds.
  2. Do not mark a schedule “recording” until MeetingRecorder actually enters .recording — quitting during a permission prompt left JSON lying.
  3. README type-checker limits are real — splitting ContentView lifecycle modifiers into smaller views fixed macOS 15 CI.

Try it

Install (macOS 14+, Apple Silicon or Intel):

curl -fsSL https://raw.githubusercontent.com/thehwang/Scripta/main/scripts/install.sh | bash
Enter fullscreen mode Exit fullscreen mode

Repo: github.com/thehwang/Scripta

After install: complete Permissions Setup, open Scheduled Recordings, add a meeting a few minutes ahead, leave Scripta open, and watch it start on its own.

If this fits your workflow, a GitHub star helps others find it. Issues and PRs welcome — especially around calendar import and safer wake-from-sleep behavior.


Scripta is MIT-licensed. Scheduled recording is local-only: your schedules live in schedules.json on disk, not on our servers — because there are no servers.

Top comments (0)