On-device and open source Whisper dictation A macOS menu bar app called Local Flow runs OpenAI's Whisper speech-to-text model locally via whisper.cpp with Metal, keeping all dictation on the user's Mac by default. Local Flow offers three built-in models (Best, Classic, Tiny) downloaded in-app from Hugging Face, accepts any ggml Whisper model by Hugging Face link or local file, and can optionally route clips to OpenAI, ElevenLabs Scribe or Gemini using the user's own API key with automatic fallback to the local model. The app requires macOS 14 or later, is distributed as Local-Flow.dmg through GitHub Releases, and deletes each voice recording 5 minutes after transcription while wiping transcripts when the app quits or after 12 hours. You speak faster than you type. Local Flow keeps all voice dictation private. Nobody will train on your data, and all transcription runs locally. - Hold to talk. Fn by default; pick any key in Settings. Double-tap it to keep listening hands-free, tap again to stop. A small Liquid Glass bar shows a live waveform while you speak it adapts to your mic level, so a quiet input still moves ; the text goes straight to your cursor. Pick which microphone to use in Settings. - Local by default. Whisper whisper.cpp with Metal runs on your Mac. Three models to pick from — Best recommended , Classic, Tiny — downloaded in-app from Hugging Face; or add any ggml Whisper model by Hugging Face link or local file Settings → Transcription → Custom model . - Or bring your own key. Cloud mode sends the clip to OpenAI, ElevenLabs Scribe or Gemini with your key, with retries and automatic fallback to the local model. Optional Mixture of experts : every service you have a key for transcribes, then an OpenAI model merges the results — slower, but more accurate. Setup looks for keys in your shell files ~/.zshrc , ~/.zprofile , … and the files they source and shows what it found; nothing is saved until you click Import from shell . - Opens at login once setup is done Settings → General to turn it off . - Files too. Drop an audio or video file on any Local Flow window or click Choose File… , right-click it in Finder → Services → Transcribe with Local Flow , or use Transcribe File… in the menu bar: the transcript lands in History and on your clipboard. Long recordings are cut at pauses into parts of up to 5 minutes cloud services cap uploads at 20–25 MB , transcribed one after another with progress on the bar, and joined; Cancel File Transcription in the menu bar stops it. - One dictionary. A plain list of names, products and jargon. Sent to the model as a hint and used to fix spelling on-device. Setup lets you add word packs for your field engineering, product, sales, legal… . - Cleanup that never leaves your Mac. Ums and uhs, capitalization, punctuation and "new paragraph" are handled with rules, not a model. It also knows where you are typing: terminals, code editors and browser address bars get lowercase with no sentence punctuation git status , example.com ; chat apps skip the final period. On by default, one toggle to turn off. - Short-lived history. Transcripts stay on your Mac only while the app is running — wiped when you quit and on launch , and never kept longer than 12 hours. The voice recording behind each one is deleted after 5 minutes long enough for a Retry and can't be played back in the app. - Self-updating. Checks GitHub Releases once a day also while it stays open and installs the new DMG in place. Download the latest Local-Flow.dmg from Releases https://github.com/jzone3/local-flow/releases/latest , drag Local Flow to Applications and open it. Grant Microphone and Accessibility access when asked Accessibility is what lets it see the hotkey in other apps and paste the text . Requires macOS 14 or later. Liquid Glass needs macOS 26; older systems get a frosted bar. brew install xcodegen scripts/fetch-whisper.sh downloads the pinned whisper.cpp xcframework into Vendor/ checksum verified xcodegen generate xcodebuild -project LocalFlow.xcodeproj -scheme LocalFlow -configuration Debug -derivedDataPath build CODE SIGNING ALLOWED=NO build open "build/Build/Products/Debug/Local Flow.app" Tests for the pure-Swift core cleanup rules, dictionary spelling fixes, env-key scan, version compare run with scripts/test-core.sh . LocalFlow/ App.swift menu bar app, windows Core/ TextCleanup, CleanupProfile, Vocabulary +Packs , EnvironmentKeys, Hotkey, MixtureOfExperts, AudioChunker, Version — no AppKit, covered by Tests/ Capture/ HotkeyMonitor, AudioRecorder 16 kHz mono , AudioInputDevice, TextInserter paste , DictationController Transcription/ TranscriptionProvider protocol, LocalWhisper + model downloader , CloudProviders, TranscriptionService Model/ AppSettings, Keychain, HistoryStore wiped on quit, 12 h purge , UpdateChecker, Welcome UI/ DictationBar Liquid Glass , Settings, Onboarding, History, PackPicker, Glass styles , Icon 1. Add a case to CloudProviderID in LocalFlow/Transcription/CloudProviders.swift with its models, key URL and env var names. 2. Write a TranscriptionProvider that turns a TranscriptionRequest 16 kHz samples + WAV + dictionary into text. Throw TranscriptionError.http / .network so retries and fallback work. 3. Return it from makeProvider model: . Settings and onboarding pick it up automatically. Local engines work the same way: LocalWhisper is just another TranscriptionProvider . - Local mode: audio and text never leave the Mac. - Cloud mode: only the audio clip and the dictionary hint go to the provider you chose, using your key stored in the Keychain . Mixture of experts sends the same clip to every service you have a key for, and their transcripts text only to OpenAI for merging. Local Flow has no server and keeps no logs; the providers may keep what you send under their own terms. - Cleanup and spelling fixes are deterministic and on-device. There is no LLM cleanup pass. - History ~/Library/Application Support/Local Flow/History is one history.json plus one .wav per dictation, nothing else. The whole folder is emptied when the app quits and again at launch so a crash leaves nothing behind ; Delete removes files right away; while running, the purge runs every minute recordings go after 5 minutes, text after 12 hours , on wake and whenever the app comes to the front, and also removes orphaned audio. The folder is excluded from Time Machine so backups never keep a copy. - Transcripts are pasted through the pasteboard, which is restored 0.6 s later; a third-party clipboard manager could still record them, as with any dictation app. Drag Local Flow from Applications to the Trash. That leaves behind: - ~/Library/Application Support/Local Flow/ — the downloaded Whisper models 0.5–1.6 GB each and the session history. - Settings: defaults delete com.jzone3.LocalFlow - Any API keys you saved, in the login keychain under service com.jzone3.LocalFlow.keys accounts openai.apiKey , elevenlabs.apiKey , gemini.apiKey ; builds before 0.0.7 used com.jzone3.LocalFlow : remove them in Keychain Access, or security delete-generic-password -s com.jzone3.LocalFlow.keys -a openai.apiKey same for the other two . Settings → About → Remove All Data… does all three and quits, so only the drag to the Trash is left. Same pipeline as New Media Writer https://github.com/jzone3/new-media-writer : release.yml builds, signs, notarizes and publishes Local-Flow-