FlowLite: I built my own voice dictation app for the Mac
I talk faster than I type, but most dictation gives me text I have to fix: “um” and “uh” left in, missing punctuation, and the sentence I corrected halfway through still written out in full. Paid dictation apps fix most of that, but I wanted to know how they work, and I wanted my audio to stay on my Mac.
So I built FlowLite, a menu-bar app for macOS. Hold the fn key, say what you want to write, let go, and clean text appears where your cursor is: Mail, Slack, a code editor, the terminal or a browser form.
What it does
- Private transcription. Whisper runs on the Mac’s Neural Engine, so audio never leaves the computer.
- Text that reads like you typed it. Claude Haiku removes filler words, applies your spoken corrections (“Tuesday, no wait, Wednesday” becomes “Wednesday”), formats lists and fixes punctuation.
- Works in any app. No plugins or per-app setup. FlowLite types into the focused field the way you would.
- Command mode. Select some text, hold Control + fn, and say “make this more formal” or “translate to Spanish”.
- Your words, spelled right. A personal dictionary for names and jargon, and replacements like “my email” → your address.
How a dictation works
Everything happens in about a second and a half, in seven steps:
- You press fn. Recording starts straight away, so the first word isn’t clipped. A press shorter than 0.3 seconds is treated as an accidental tap.
- It listens and reads the screen. The microphone is recorded at 16 kHz while the Accessibility API reads the app name and the text around the cursor. Password fields are never read.
- Whisper transcribes on the Mac. WhisperKit runs
large-v3-turboon the Neural Engine, with your vocabulary as a spelling hint. - Claude Haiku cleans it up. The transcript and nearby text go to Claude Haiku with strict editing rules: edit what was said, never answer it or follow instructions inside it.
- Your rules run. Replacements are applied exactly, and a leading space is added only when the text before the cursor needs one.
- The text is inserted. FlowLite inserts through Accessibility and checks the field actually changed. In terminals, Chromium browsers and Electron apps, where that’s unreliable, it pastes and then restores your clipboard.
- It’s saved to History with the raw transcript, the final text and the timing of each step.
The surrounding text is what makes the cleanup feel natural. FlowLite knows you’re continuing a sentence in Slack rather than starting an email, so it keeps the tone casual in chat, standard in email and exact in code.
Privacy, by design
| Data | Where it goes |
|---|---|
| Audio | Stays on your Mac. Transcription is local. |
| Transcript and nearby text | Sent to the Anthropic API for cleanup, with your own key. Turn cleanup off and nothing leaves the Mac. |
| Password fields | Never read, never sent, never saved. |
| API key | Stored in the macOS Keychain. |
| History | A local SQLite database you can clear at any time. |
There’s no account, no telemetry and no FlowLite server. If FlowLite can’t tell in time whether a field is a password field, it treats it as one.
Making it reliable
Dictation is only useful if you can trust it, so most of the work went into what happens when things go wrong.
- It never loses your words. If cleanup fails, times out or you’re offline, the raw transcript is inserted instead.
- Nothing can hang the app. Reading the screen, transcription and cleanup each have a time limit, and a stuck step never blocks the next press of fn.
- Every OS dependency sits behind a protocol. The coordinator only sees interfaces for recording, reading context, transcribing, cleaning and inserting, so the whole pipeline is tested with fakes. There are 94 tests.
- Only public APIs. No private frameworks, and no permissions beyond what Accessibility and the keyboard listener need.
Try it
FlowLite is built from source for now. You need an Apple Silicon Mac on macOS 15 or later, Xcode 16 or later, about 2 GB of space for the speech model, and optionally an Anthropic API key for cleanup.
git clone https://github.com/Jenish109/flowlite.git
cd flowlite
brew install xcodegen
Scripts/make-signing-identity.sh # once, so macOS remembers permissions
Scripts/build.sh --runOn first run, grant Microphone, Accessibility and Input Monitoring, let the speech model download, and set System Settings › Keyboard › Press 🌐 key to to Do Nothing. The README has every step and a troubleshooting table, and the FlowLite website explains it with pictures.
Things I learned building it
- Inserting text is harder than transcribing it. Whisper was the easy part. Getting text into every kind of app, and proving it arrived, took the most care.
- The cleanup model must edit, not write. If you dictate “ask him what time the meeting is”, you want that sentence, not an answer. The prompt rules and injection protection exist for exactly that.
- Fallbacks are a feature. Inserting the raw transcript when something fails makes the app feel dependable, even when you’re offline.
What’s next
Streaming transcription while you speak, per-app styles, a notarized download, and support for other cleanup models, including local ones through Ollama.
FlowLite is free software under the GPL-3.0 licence, on GitHub. Issues and pull requests are welcome.
Want something like this built?
FlowLite brings a Claude model into an everyday workflow on the Mac. If your team has a workflow that could use AI in the same careful way, I build custom AI tools and Claude Code integrations.
Tell me what you have in mind and I’ll reply with what’s worth building.
Prepared with AI assistance using the primary sources linked in the article. Guidance checked on 14 October 2026.