Build Superscribe
KINDAreplaces $38/mosaves $456/yrback to the verdict
A dictation tool whose hard problems are capturing only while a key is held without becoming a keyboard observer, keeping an honest record of audio that leaves the machine for a transcription service, and inserting text into another application without stealing or losing the clipboard.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- have readyfree
Why The permission prompts and secure input behaviour are the interesting part of this build and they only test properly on an account that has not already granted everything.
Get it Create a fresh user account you can reset.
Verify
A first run on the clean account prompts for microphone access and nothing else until insertion is used - installfree
Why Builds the menu bar application without an Xcode project to maintain.
Get it Install the command line developer tools.
Verify
swift build produces a runnable binary - API keypay per minute of audio; the monthly ceiling in this build is what keeps it bounded
Why Remote mode is the fast path, and this is the only component that costs money or sends audio anywhere.
Get it Create a key with a provider whose retention policy you have read, and record what it says.
Verify
A held key produces a transcript and a transmissions row - installfree
Why It is a selectable mode rather than a fallback, and a local path nobody tested is the same as not having one.
Get it Download a small model and a runtime that can transcribe a wav file offline.
Verify
Local mode produces a transcript with the network disconnected - decidefree
Why Audio, transcripts and retention windows are much easier to decide now than after a month of dictations exists on the disk.
Get it Write down whether audio is kept at all, for how long, and what the redaction patterns are.
Verify
The settings match the written policy and the README states it
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- dictations(id, started_at, ended_at, duration_ms, mode, provider, model_id, transcript_path, cleanup_applied, target_bundle_id, cost_minor) - transmissions(id, dictation_id, provider, endpoint_host, bytes_sent, seconds_sent, retention_note, at) · one row per time audio left the machine, written before the socket opens - audio_files(dictation_id, path, bytes, delete_after) · optional, off by default, and deleted on a timer when on - redactions(pattern, label, added_on) · applied to the transcript before it is stored or shown in history - apps(bundle_id, first_seen_at, insertion_mode, blocked) · per-application behaviour is explicit rather than guessed - settings(hotkey, provider, retain_audio, transcript_retention_days, monthly_ceiling_minor) - There is no keystroke table, no window content and no audio outside the retention setting. A dictations row records that something happened; the transcript itself is optional.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
STT_API_KEYsecret | optional | sk-...redacted | Remote transcription only. Unset means the application runs entirely locally. |
STT_ENDPOINT_HOST | optional | api.example.com | Recorded on every transmission row so history can say where audio went. |
LOCAL_MODEL_PATH | required | ~/Models/speech-small.bin | The local transcription mode. Required, because it is a mode rather than a fallback. |
RETAIN_AUDIO | required | false | Off by default. When on, files are deleted at their deadline even across restarts. |
TRANSCRIPT_RETENTION_DAYS | required | 30 | Transcripts and their rows are removed together at this age. |
MONTHLY_CEILING | required | 4.00 | Remote transcription stops at this figure and local mode takes over. |
HISTORY_DIR | required | ~/Library/Application Support/Dictation | Transcripts and the database. Redacted before anything is written here. |
The build, in order
A microphone that is shut unless you are holding the key
Capture begins on key down and ends on key up, the application never observes other keystrokes, and the visible state always matches the hardware.
The permission you are not asking for is the point.
Files
Sources/Hotkey/Register.swiftTests/NoEventTapTests.swiftA flag and a microphone can disagree, and the flag is the one that lies.
Files
Sources/Capture/Engine.swiftEvery one of these has left a microphone open in some shipped app.
Files
Sources/Capture/Lifecycle.swift
done when · tick each as it passeswatch out- Implementing the hotkey with an event tap that watches all keyboard input gives your app the ability to read passwords, requires the permission the operating system grants most reluctantly, and stops working the moment any application enables secure keyboard entry, which you will then be tempted to work around. Register the hotkey through the supported interface, accept that it does not fire inside a secure input window, and say so in the interface rather than retrying.
What left the machine, and when
Every transmission to a remote service is recorded before it happens, and the local path works as well as the remote one.
Afterwards is too late for the only case that matters.
Files
Sources/Transcribe/Remote.swiftTests/TransmissionRecordTests.swiftA path nobody tests is a path that does not work.
Files
Sources/Transcribe/Local.swiftThe honest answer to where did that go is in the list.
Files
Sources/UI/HistoryView.swift
done when · tick each as it passeswatch out- Recording the transmission after the call returns means a crash, a cancellation or a network failure leaves audio that went to a third party with no local record of it having gone, which is precisely the case somebody will ask about. Write the row first, mark it complete afterwards, and treat a row without a completion as audio that probably left rather than audio that did not.
Getting the text into the other application
The transcript arrives in the focused application without stealing the clipboard or corrupting a field.
A timer-based restore eats the dictation on a busy machine.
Files
Sources/Insert/Paste.swiftTests/ClipboardRestoreTests.swiftTerminals, editors and browser fields all behave differently.
Files
Sources/Insert/AppPolicy.swiftLive insertion into someone else's document is how text gets mangled.
Files
Sources/Insert/Gate.swift
done when · tick each as it passeswatch out- Restoring the clipboard on a fixed timer after issuing the paste means that on a slow or busy application the restore lands first and the user pastes whatever was there before, losing the dictation and looking like the tool dropped it. Confirm the paste landed before restoring, cap the wait, and if confirmation never arrives leave the transcript on the clipboard and say so rather than restoring over it.
History is a liability, so treat it like one
Transcripts and audio expire, redaction happens before storage, and deleting really deletes.
The file is what other software reads.
Files
Sources/Store/Redact.swiftTests/RedactionOnDiskTests.swiftA deadline that passes while the app is closed still passed.
Files
Sources/Store/Retention.swiftA silent delete is indistinguishable from a broken one.
Files
Sources/UI/PrivacyPane.swift
done when · tick each as it passeswatch out- Redacting at display time leaves the unredacted transcript sitting in a plain file that any backup, any search index and any other application can read, so the redaction protects the interface rather than the user. Redact before the write, keep no shadow copy of the original, and test by grepping the transcript directory for the pattern after a dictation containing it.
Permissions, cost and a way outproduct builder
The permission story is honest, spending has a ceiling, and the history exports in a form something else can read.
With one sentence saying why, and a working refusal path.
Files
Sources/Permissions/Request.swiftDictation should get slower, not stop.
Files
Sources/Transcribe/Budget.swiftTests/CeilingTests.swiftThe record of what left is part of the history.
Files
Sources/Export/Dump.swift
done when · tick each as it passeswatch out- Requesting every permission at launch so the flow is smooth later trains people to grant microphone and automation access without reading, and it is exactly the pattern a tool that types into other applications should not be teaching. Ask at the moment each capability is first used, explain what it is for in one sentence, and keep the application usable when one is refused.
That is the whole plan for Superscribe. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Always-listening and wake-word modes.
- Telephone call capture on an existing number.
- Live word-by-word insertion while speaking.
- Reading the focused window's contents.
- call capture on your existing number (carrier forwarding into a CallKit softphone)
- glitch-free live word-by-word insertion tuned per app: terminals, Electron editors, browser contenteditables
- auto-filing: dictations and calls alike are matched to the right project via embeddings (enriched with GitHub repo context) plus live commit activity during the work block, so billable time lands on the right client without tagging
- the workspace around the transcripts: semantic search, invoice-ready PDF reports, CRM note drafts, a public API, and an MCP server
- Windows parity and signed, notarized auto-updating installers
- Per-application dictionaries for names and jargon, which is the largest accuracy win available without touching the model
- A vocabulary hint sent with each remote request, built from your own corrections rather than from your documents
- An offline-only build that removes the remote path entirely, which is a smaller application and a shorter privacy section
Need the files? The project pack on the verdict page hands your agent the whole brief · more dictation.