Minimal, 100% local push-to-talk dictation for macOS on Apple Silicon.
Hold Left Option + Space, speak, release — your speech is transcribed locally with
NVIDIA Parakeet TDT v3 (mlx-community/parakeet-tdt-0.6b-v3, multilingual with
automatic language detection for German/English and more) and inserted at the current
cursor position via clipboard paste (Cmd+V).
100% local. After the one-time model download (HuggingFace), no audio leaves the device at runtime — it works offline / in airplane mode too.
- Download
ParakeetDictate.dmgfrom the latest release. - Open the DMG and drag Parakeet Dictate into the Applications folder.
- Launch it — on first start it walks you through the three required permissions (Microphone, Input Monitoring, Accessibility) and downloads the speech model (~1–2 GB) once.
- Hold Left Option + Space, speak, release — the text appears at your cursor.
The app is signed and notarized, so it opens without a Gatekeeper warning.
The rest of this file describes running from source (development). To build a release, see
packaging/RELEASE.md.
- Apple Silicon Mac (M-series), macOS 14+
uvor Python 3.11+ffmpeg— only for the optional core-check script (test_transcribe.py). The app itself decodes audio in-process and does not need ffmpeg.
# 1. Create an environment + install dependencies (with uv)
uv venv --python 3.12 .venv
uv pip install -r requirements.txtAlternatively without uv:
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtBefore the hotkey & paste matter, verify the model + transcription run cleanly on your
machine. A short test WAV can be created with the macOS say command:
say -v Daniel -o sample.aiff "Hello, this is a test with a few words."
ffmpeg -y -i sample.aiff -ar 16000 -ac 1 sample.wav # needs ffmpeg
.venv/bin/python test_transcribe.py sample.wavOn the first run the model (~0.6 B parameters) is downloaded from HuggingFace (a few minutes, depending on your connection). After that it is cached locally and the model load takes ~1 s. A ~7-second clip is transcribed in under a second.
source .venv/bin/activate
python app.py- Wait until the log says
ready(the model is loaded and warm). - Place the cursor in any text field (TextEdit, browser, Slack, …).
- Hold Left Option + Space → a short sound, recording is live (🔴).
- Speak.
- Release → transcription (✍️), then the text is inserted at the cursor + a sound.
The menu-bar icon shows the status: 🎙️ idle · 🔴 recording · ✍️ transcribing.
Quit via "Quit" in the menu (or Ctrl+C if headless).
German and English work without switching — the language is detected automatically. Long recordings keep going until you stop (up to the Max recording cap) and are transcribed in overlapping chunks, so a long session is never cut off mid-way.
Live preview (beta): enable Settings → Live preview while dictating to get a small floating panel that shows the recognized text while you speak (stable text in white, in-progress guesses greyed). It's display-only — the final inserted text always comes from the full-quality pass at the end. Costs noticeably more GPU/battery while recording.
The app — i.e. the process that launches it — needs three permissions under System Settings → Privacy & Security:
| Permission | For | Where |
|---|---|---|
| Microphone | recording | Privacy & Security → Microphone |
| Accessibility | simulated Cmd+V |
Privacy & Security → Accessibility |
| Input Monitoring | global hotkey listener | Privacy & Security → Input Monitoring |
The bundled app requests these via native dialogs on first launch (and the menu has "Request permissions…" to re-trigger them). When running from source, grant the permissions to your terminal / IDE instead.
Important: Input Monitoring and Accessibility only take effect after a restart (Microphone is immediate). The menu shows a live ✓/⚠ checklist, and a one-click "Restart now" does the relaunch for you the moment you've granted them.
All options live in a native Settings window (menu → Settings…, or ⌘,; persisted to
~/Library/Application Support/ParakeetDictate/settings.json):
| Setting | Options | Default |
|---|---|---|
| Trigger key | Left Option + Space · Right Option · Right Command · Right Control · F5 · F6 | Left Option + Space |
| Mode | Hold to talk · Tap to start / stop | Hold to talk |
| Max recording | 5 · 15 · 30 · 60 minutes (auto-stop cap) | 30 minutes |
| Recording indicator | floating timer + level pill while recording | on |
| Play sounds | on / off | on |
| Show 'inserted' banner | on / off | off |
| Tidy up text | light cleanup (capitalize, collapse spaces) | off |
| Live preview (beta) | floating panel with live text while dictating | off |
| Open at Login | on / off | off |
The Settings window also has a live Permissions tab (✓ per permission with deep links + one-click restart) and an About tab. The menu keeps the quick actions: status, Copy Last Transcript (paste-failure safety net), Settings…, updates.
Your audio and transcripts stay on your Mac: after the one-time model download the app
sets HF_HUB_OFFLINE (no transcription network), disables HuggingFace telemetry, and
never writes transcript text to disk (the log keeps metadata only). The only routine
outbound call is a daily check to GitHub for app updates — it sends nothing about you,
verifies the download's Apple notarization + Developer-ID signature before installing, and
can be turned off in Settings → General. The app stores the speech model as an
optimized local copy (~1.3 GB instead of the 2.5 GB original download).
- Hotkey does nothing (no sound on press) → Input Monitoring not granted, or the app/terminal wasn't restarted after granting it.
- Text is not inserted (log shows the transcription, but nothing appears) → Accessibility not granted.
- Silence / empty transcription → Microphone not granted, or the wrong input device is selected as the system default.
- App not in the Microphone list → it only appears after it has requested access; use the menu "Request permissions…".
ffmpeg not found(only fortest_transcribe.py) →brew install ffmpeg.
The Parakeet weights are under the NVIDIA Community Model License; the MLX
conversion comes via mlx-community. Unproblematic for local, internal use. Check the
license terms before any redistribution.
For a future, production variant the native route is FluidAudio (Swift SDK,
Parakeet TDT v3 via CoreML on the Apple Neural Engine, more energy-efficient, very high
realtime factor) — the same foundation VoiceInk and Spokenly use for Parakeet. This v1
deliberately stays Python + parakeet-mlx to get something working quickly.