voxtype: Configuration & CLI
Configuration lives at ~/.config/voxtype/config.toml
(voxtype also reads a legacy
~/.config/voice-type/config.toml if it exists and the
voxtype one doesn’t — a carryover from when the tool
shipped as voice-type).
You rarely need CLI flags. Every runtime flag is
just an override of a config key (the exceptions are
--config, which points at a different file, and the
setup/init --force flag), so the intended workflow
is: put your preferences in the config once, then
your daily command is plain voxtype — flags
exist for one-off experiments (e.g. trying another
engine) and always win over the file.
Any config key can be set for one run with
--set KEY=VALUE, exactly as if that line were in
the file. The key may use hyphens or underscores,
and --set can be repeated:
voxtype --set post-process=true --set post-process-provider=s1-minivoxtype --set sounds=false --set submit-phrases="go, send it"voxtype post-process --set post-process-format=minimal "so um hi"Values are read as the key’s type: true/false (also
yes/no, on/off, 1/0), numbers, plain strings, and
lists as comma-separated items or a TOML array such
as ["go", "send it"]. KEY= gives an empty string
or empty list. If a dedicated flag such as --engine
sets the same key, that flag wins.
Two ways to create that file:
voxtype setup # interactive walkthrough — asks, then writesvoxtype init # write a fully commented sample to edit by handvoxtype init --force # overwrite an existing samplevoxtype setup is the quickest start: it asks a
short series of explained questions (engine, mode,
segmentation, hotkey, wake word, and optional extras),
validates your choices, and writes a ready-to-use
config — you can record the hotkey live during the
walkthrough. init instead drops a fully commented
sample (like the reference below) for hand-editing.
The three independent axes
Section titled “The three independent axes”Three settings combine to define how voxtype behaves, and they answer different questions:
mode— when is it listening?toggle: only between two presses of the hotkey.wake: always passively listening for the wake word (hotkey works as an override).vad: dictating from the moment it starts.segmentation— when does text appear? See “When does the text appear?” below — this is the axis people mean when they ask about “streaming” dictation. (Mostly independent, with one tie:holdneeds a parakeet engine in toggle mode; otherwise voxtype usesvad.)engine— what transcribes it? Pure speed/accuracy/platform trade-off; see the engine table below. Any engine works with any mode.
When does the text appear?
Section titled “When does the text appear?”Dictation tools differ in how immediately the transcript shows up. The spectrum, from most to least immediate:
- Word-by-word streaming (Apple-dictation style: words materialize and self-correct as you speak). voxtype deliberately does not do this into your apps: revising already-typed text in another application means blindly sending backspaces into whatever has focus — one desync and your document is mangled. Typed text should be final.
- Per-pause typing —
segmentation = "vad". Speak; roughly half a second after each natural pause, that utterance is typed. This is the closest voxtype comes to a streaming feel: text flows in sentence-sized pieces while you keep talking. Trade-off: the model transcribes each fragment with only that fragment’s context, so accuracy is a notch lower. - Whole-take —
segmentation = "hold". Nothing appears while you speak (the ghost indicator is your feedback); on toggle-off the entire take is transcribed as one segment and typed in one go. Maximum accuracy — the model sees full sentence context — and most apps undo it as a single edit (keystrokes are synthesized, so undo grouping is up to the focused app). Requirestogglemode, since the wake word can only be heard by continuous per-utterance transcription.
Wake and vad modes always use per-pause typing
(2); toggle mode lets you pick between (2) and (3),
and defaults to (3), whole-take, with a parakeet
engine — so out of the box you get maximum-accuracy
push-to-talk. Set segmentation = "vad" if you’d
rather see text appear as you pause.
Common setups
Section titled “Common setups”Push-to-talk dictation (the default, and the
recommended daily driver). No wake word involved at
all; maximum accuracy; text lands in one go (a single
edit to undo, in most apps). This is exactly what you
get out of the box — no config needed — since
mode defaults to toggle, the engine is auto-selected
(a parakeet engine), and segmentation then defaults to
hold. Spelled out, that is:
mode = "toggle"segmentation = "hold"# engine is auto-selected: parakeet-mlx on Apple Silicon,# parakeet on Intel — you normally leave it unsetToggle with live feedback. Same hotkey workflow, but text appears at every pause instead of at the end — useful when you want to see progress while dictating something long, at some cost in accuracy:
mode = "toggle"segmentation = "vad"Hands-free with a wake word. Say “hey claude …” to dictate, “stop listening” (or silence) to re-arm; the hotkey still toggles manually. Per-pause typing is inherent to this mode:
mode = "wake"wake_word_aliases = ["hey cloud"] # add what the model mishearsAlways-on transcription. Types everything it hears while running — for captioning yourself or short bursts of use:
mode = "vad"(These recipes leave engine unset so it auto-selects
for your machine; set it explicitly only to force a
specific engine.)
Engines
Section titled “Engines”Selected with engine / --engine. All run 100%
on-device.
| Engine | Runs on | Speed* | Notes |
|---|---|---|---|
parakeet-mlx | Apple GPU (MLX) | ~40x realtime | Default on Apple Silicon. fp16 Parakeet-TDT v3: best accuracy and speed. Weights from HuggingFace on first run. |
parakeet | CPU (sherpa-onnx) | ~32x realtime | Default on other machines. int8 Parakeet-TDT v3 (or fp16 v2 via parakeet_model); ~490 MB download. |
moonshine | CPU (ONNX) | streaming | Moonshine streaming models; smallest footprint. Opt-in: uv tool install "voxtype[moonshine]" (no Intel-macOS build). |
Both parakeet engines ship with the base install; the
default is chosen for your machine, so most people
never set engine at all.
*measured on an M-series Mac; see parakeet_threads
for CPU tuning.
Config reference
Section titled “Config reference”# ~/.config/voxtype/config.toml — all keys optional; the values shown# are the defaults (except `engine`, which is auto-selected per machine)
# Activation: "toggle" (hotkey), "vad" (hands-free), "wake" (wake word)mode = "toggle"
# Engine: "parakeet-mlx" | "parakeet" | "moonshine". Auto-selected when# unset: parakeet-mlx on Apple Silicon, parakeet on Intel. Set it only to# force a choice; the value below is just the Apple-Silicon case.engine = "parakeet-mlx"
# "vad" types each utterance when you pause; "hold" records everything# between toggle-on/off and transcribes the whole take at once (parakeet# engines + toggle mode only). Default: "hold" with a parakeet engine in# toggle mode (the common case), otherwise "vad".segmentation = "hold"
# parakeet (CPU) build: "v3-int8" | "v2-fp16"; and decode threadsparakeet_model = "v3-int8"parakeet_threads = 4
# parakeet-mlx model (HuggingFace id)mlx_model = "mlx-community/parakeet-tdt-0.6b-v3"
# moonshine model: tiny | base | tiny-streaming | base-streaming |# small-streaming | medium-streamingmodel_arch = "medium-streaming"
language = "en"
# Hotkeys (pynput or bracket-less syntax; `voxtype hotkey` records one)hotkey = "<ctrl>+;" # toggle recording# A second toggle for the laptop keyboard (macOS): tap a modifier key# twice on its own. One of left_alt right_alt left_cmd right_cmd# left_ctrl right_ctrl left_shift right_shift ("alt" = Option). The key# keeps working as a normal modifier. "" disables.double_tap_key = ""double_tap_ms = 400 # max gap between the two taps, press to presscancel_hotkey = "<esc>" # cancel recording (only intercepted WHILE recording)paste_hotkey = "" # re-type last transcript, e.g. "<cmd>+<ctrl>+v"
# Wake modewake_word = "claude"wake_word_aliases = [] # misspellings the model produces, e.g. ["hey cloud"]stop_phrase = "stop listening"idle_timeout = 20.0 # seconds of silence before wake mode re-arms
# Spoken submit: saying one of these as an ENTIRE utterance presses Entersubmit_phrases = ["over", "go", "submit"]
# Transcript cleanup: strip standalone fillers (uh, um, ...) and# collapse 3+ word stutters ("I I I think" -> "I think")strip_fillers = true
# Optional LLM cleanup, off by default — see "Post-processing" belowpost_process = falsepost_process_provider = "s1-mini" # s1-mini (local) | cerebras (external API)post_process_format = "auto" # cerebras: auto | paragraphs | minimalpost_process_newlines = "auto" # line breaks: auto | shift_enter | flattenpost_process_log_text = true # log each take's before/after textpost_process_cerebras_model = "gpt-oss-120b"post_process_style = "semi-formal" # casual | semi-casual | semi-formal | formalpost_process_structure = "prose" # prose | listspost_process_context = "general" # general | emailpost_process_timeout = 0.0 # seconds before raw; 0 = 4 (s1-mini) / 2 (cerebras)post_process_model = "" # local .gguf path; "" = pinned S1-mini downloadpost_process_server = "llama-server" # llama.cpp server binary (name or path)
trailing_space = true # append a space after each typed utterance
# Toggle chimes. sounds = false silences the start/stop chime entirely# (or run with --no-sounds). Names are system sounds# (/System/Library/Sounds) or file paths.sounds = true # false = no chime when recording toggles on/offsound_start = "Glass"sound_stop = "Bottle"
# Keep each session's text on the clipboard toocopy_to_clipboard = false
# Floating ghost indicator while recording (macOS): a little blue# ghost whose mouth opens with your voice.overlay = trueoverlay_flex = 1.0 # how much the face flexes its shape (higher = more)overlay_speed = 1.0 # animation speed (lower = slower/gentler)overlay_opacity = 1.0 # 0.1–1.0; lower it if the ghost hides text under it
# Keep the model's memory warm (parakeet-mlx only). After this many# minutes without a decode, voxtype quietly decodes a short silent# clip so the idle model stays recently-used and macOS is far less# likely to evict it to swap — otherwise, on a memory-pressured# machine, the first take after a long pause can stall for seconds# paging the model back in. Keeps ~1.7 GB in active use. 0 disables;# max 1440 (a day). See the note below on the one trade-off. Also keeps# the post-processing model warm when post_process is on.keepalive_minutes = 0.0About keepalive_minutes
Section titled “About keepalive_minutes”Turn this on if your Mac runs under heavy memory pressure and your first take after a pause is sometimes slow — several seconds for a few seconds of audio, when a normal take is near-instant. That slowness is macOS having evicted the idle model (~1.7 GB) to swap; the periodic silent decode keeps those pages in active use so it is far less likely to happen. A value of 5 (minutes) is a reasonable start. On a machine with memory to spare, leave it off — it is not free, it keeps ~1.7 GB resident.
One trade-off worth knowing:
- The keepalive decode runs on the same thread that reads the microphone, so while it runs, capture pauses. It skips itself during a take, during an utterance, and for 30 seconds after any hotkey press, so it should never collide with you speaking — but if you happen to press the hotkey in the instant it starts, the first fraction of a second of your dictation can be lost.
- In practice that window is ~0.2 s, because a keepalive on a warm model is fast, and keeping the model warm is the whole point. A multi-second keepalive means the model had already been evicted, which is the situation this option prevents.
Post-processing (LLM cleanup)
Section titled “Post-processing (LLM cleanup)”Optionally, voxtype can pass each transcript through a language model
before typing it, to clean it up. Pick one of three setups in
~/.config/voxtype/config.toml:
| You want | Put in your config | Also needed |
|---|---|---|
| No cleanup (the default) | nothing | nothing |
| Local cleanup (on-device, English only) | post_process = true | brew install llama.cpp (details) |
| Cerebras cleanup (also paragraphs and lists; sends transcripts to Cerebras) | post_process = truepost_process_provider = "cerebras" | CEREBRAS_API_KEY in ~/.config/voxtype/.env (details) |
With no cleanup, plain voxtype types Parakeet’s transcript exactly as
it always has, after the regex filler removal. With either kind of
cleanup, any failure or timeout types the raw transcript, so a take is
never lost. To turn cleanup off again, delete post_process = true or
set it to false.
The local model (s1-mini)
Section titled “The local model (s1-mini)”The local model adds punctuation and capitals, drops self-corrections, and removes verbal clutter like “you know”. These are real takes from this Mac:
| Parakeet heard | voxtype typed |
|---|---|
| it does not handle missing keys, I mean optional keys, and then it crashes | It does not handle optional keys, and then it crashes. |
| Let’s meet on Tuesday, no wait Wednesday at three. | Let’s meet on Wednesday at 3. |
| First install Voxtype second run Voxtype setup third grant the permissions | First, install Voxtype. Second, run Voxtype setup. Third, grant the permissions. |
| which is like kind of surprising you know. | which is kind of surprising. |
The model is “S1-mini” by “Superwhisper”, a 0.6B-parameter fine-tune of Qwen3 trained for exactly this job. It is Apache-2.0 licensed, with one added condition: anything that uses it must keep calling it “S1-mini” by “Superwhisper”. It handles English only. Everything runs on your Mac; nothing leaves the machine.
Set up the local model
Section titled “Set up the local model”-
Install llama.cpp, which provides the
llama-serverthat runs the model. voxtype adds no Python dependencies for this, so the base install stays as light as before.Terminal window brew install llama.cpp -
Download the model and try it once. The model is a single 462 MiB file, pinned to a fixed revision and checked against its sha256, and stored in
~/.cache/voxtype/models/.Terminal window voxtype post-process "so um I think we should uh move it to Tuesday no wait Wednesday"This prints the cleaned text and how long it took. Pass
--style formal(or any other style) to compare styles. -
Turn it on in
~/.config/voxtype/config.toml, or answer yes to the question invoxtype setup:post_process = true
Settings
Section titled “Settings”| Key | Default | What it does |
|---|---|---|
post_process | false | Turn LLM cleanup on. |
post_process_style | "semi-formal" | casual (lowercase, little punctuation), semi-casual, semi-formal (sentences, capitals, full stops), or formal (also expands contractions). |
post_process_structure | "prose" | lists numbers “first…, second…” items. |
post_process_context | "general" | email formats the text as an email. |
post_process_provider | "s1-mini" | s1-mini (local) or cerebras (external API; see below). |
post_process_newlines | "auto" | How line breaks in cleaned text are typed: shift_enter, flatten (one line), or auto (Shift+Enter for cerebras, flatten for s1-mini). See below. |
post_process_log_text | true | Log each take’s full before/after text. false logs timings only. |
post_process_timeout | 0.0 | Seconds a take may spend in cleanup before voxtype types it raw (0.5–60). 0 means the provider default: 4 s for s1-mini, 2 s for cerebras. |
post_process_model | "" | Path to your own .gguf file. Empty means the pinned S1-mini download. |
post_process_server | "llama-server" | Name or full path of the llama.cpp server binary. |
The style, structure and context values are the only ones the model was trained on, so voxtype rejects anything else.
Line breaks
Section titled “Line breaks”voxtype never types a bare Enter in the middle of a take, because that
would send a chat prompt or run a shell command partway through. With
post_process_newlines = "shift_enter", each line break in cleaned
text (list items, paragraphs) is typed as Shift+Enter, which inserts a
new line without sending in Claude Code, Codex, Slack, most chat boxes
and editors. The default, "auto", does that for the cerebras provider
and types s1-mini’s output on one line, as s1-mini always has.
What it costs
Section titled “What it costs”Measured on an M1 Max with real Parakeet takes:
- Latency. Cleanup adds about 150 ms at the median and about 550 ms at the 95th percentile, after the server is warm. A short take of 20 words or fewer costs under 300 ms. A 60-word take costs about 0.6 s. A take longer than 250 words is split at sentence boundaries, and each piece is cleaned in turn.
- Memory. The server’s resident size is about 830 MB, but only
about 300 MB of that is its own (dirty) memory. The other ~470 MB is
the model file mapped from disk with no dirty pages: under memory
pressure macOS simply drops those pages and rereads them later,
without writing anything to swap. voxtype never locks the model into
RAM (
--mlock) and keeps the context small (2048 tokens, one request at a time). If memory pressure makes the first take after a pause slow,keepalive_minuteskeeps this model warm too. - Startup. voxtype starts the server in the background at launch, which takes about 5–15 seconds. Takes that arrive before it is ready are typed raw, with a one-line notice.
When it falls back to the raw transcript
Section titled “When it falls back to the raw transcript”Cleanup can only change the text that gets typed. It can never lose a take. voxtype types the raw transcript, exactly as it would with cleanup off, when any of the following happens:
- llama-server is missing, failed to start, or crashed. voxtype retries starting it at most once a minute.
- The take exceeds
post_process_timeout. - The model returns empty output, truncated output, or output that looks like a chat reply rather than a transcript.
- The output is much longer than the input, or lost most of it.
- The transcript looks non-English. Either most of its letters are non-ASCII (Cyrillic, Greek or Chinese, for example), or, in a take of four or more words, at least a quarter are common words of a single one of these languages, and they outnumber the English ones: Spanish, French, German, Italian, Portuguese, Dutch or Indonesian. Other mostly-ASCII languages (Polish or Romanian, for example) are not reliably detected, so use cleanup only for English dictation.
The terminal shows post-processed in N ms, or post-process fell back to raw (reason), for every take. Each take also gets a latency: line;
see Reading the logs.
Spoken commands are matched on the raw transcript, before cleanup. That
covers the submit phrases (“go”), the stop phrase and the wake word, so
cleanup cannot break them. Filler-word removal (strip_fillers) also
still runs first. Esc behaves as it does without cleanup: it
discards the recording in progress, but text already transcribed and
waiting for cleanup is still typed.
The server never outlives voxtype. It runs under a tiny supervisor
process (about 20 MB) that stops it as soon as voxtype exits for any
reason, including a crash, a closed terminal, or kill -9. As a
backstop, each voxtype process records its server in
~/.cache/voxtype/run/, and the next launch stops any server left
behind by a voxtype process that has died. It never touches the server
of a voxtype process that is still running. A server that fails to
start leaves its log in that same directory.
Cerebras provider (external API)
Section titled “Cerebras provider (external API)”post_process_provider = "cerebras" sends each transcript to
Cerebras and runs it through
gpt-oss-120b. Besides cleanup, it splits long, rambling dictations
into paragraphs at topic changes and turns spoken enumerations into
plain-text lists, while keeping technical terms, file names, commands
and URLs as dictated. Short utterances stay short.
Enable it. Put your API key from cloud.cerebras.ai in voxtype’s own
key file, ~/.config/voxtype/.env. Don’t put it in your shell profile
(where every program you run can read it) or in config.toml. The file
holds a single line:
CEREBRAS_API_KEY=your-key-hereCreate it with your editor, then make it readable only by you:
chmod 600 ~/.config/voxtype/.envThen add these lines to ~/.config/voxtype/config.toml:
post_process = truepost_process_provider = "cerebras"Now plain voxtype uses Cerebras. To disable it, set
post_process = false, or switch the provider back to s1-mini.
voxtype looks for the key in this order and never logs it:
- A
CEREBRAS_API_KEYenvironment variable, for example one set by a secrets manager. ~/.config/voxtype/.env.~/.config/voice-type/.env, if your config is still at that legacy location. A config given with--configdoesn’t change where voxtype looks for the key.
If the key file is readable by other users, voxtype warns you to
chmod 600 it. If no key is found, it says so once at launch and types
raw transcripts.
Try it once without starting dictation:
voxtype post-process --provider cerebras "um so lets do it Friday no sorry Thursday"| Key | Default | What it does |
|---|---|---|
post_process_provider | "s1-mini" | cerebras selects this provider. |
post_process_format | "auto" | auto: paragraphs and lists when appropriate. paragraphs: paragraph breaks, but enumerations stay prose. minimal: fix punctuation and disfluencies only, with no added structure; the output is always one line. |
post_process_cerebras_model | "gpt-oss-120b" | The Cerebras model id. |
post_process_timeout | 0.0 | 0 means 2 s for this provider. A take that takes longer is typed raw. |
post_process_newlines | "auto" | auto types Shift+Enter for this provider; paragraphs and lists need it. See Line breaks. |
post_process_log_text | true | Log the before/after text of each take. |
The format is passed to the model through its prompt. The transcript is sent as delimited data, and the prompt tells the model never to follow instructions inside it. A dictated request stays a request: say “write an email to John saying the meeting moved” and that sentence is typed, not an email. voxtype keeps one HTTPS connection open to save the TLS handshake on each take. Every failure (no key, HTTP error, timeout, empty or malformed reply, truncated output, or output that lost most of the input) types the raw transcript, and the reason is logged.
Reading the logs
Section titled “Reading the logs”With post-processing on, every take logs one line with timings only, never transcript text or the key. For example (illustrative numbers):
[voxtype] post-process (cerebras): 412 ms[voxtype] latency: transcribe 966 ms, post-process 412 ms (cerebras, ok), total 1398 ms (speech end to inserted)transcriberuns from your toggle-off to Parakeet’s transcript. It appears in hold mode only; with VAD segmentation the engine’stranscribed N s of audio in M sline covers it.post-processis the cleanup call, including the network round trip. The parenthesis showsok, orfallback: <reason>such asHTTP 402 payment_requiredortimed out.totalruns from the end of your speech to the text being typed. With VAD segmentation it starts when the transcript arrives instead. If you start and stop a new take before the previous one has finished transcribing, that earlier take is timed from the latest toggle-off, so its numbers read low.
The latency and fallback lines never contain your words. The
before/after lines (before: "…", after: "…") contain each take’s
full text; set post_process_log_text = false to turn them off.
voxtype’s usual one-line previews (typed: "…") still show the start of
each take, as they always have.
Measured results
Section titled “Measured results”On an M1 Max, using say-synthesized takes of 64–76 seconds (182–238
words: several requirements, a correction, a topic change, file names,
commands and URLs) through Parakeet, voxtype’s real delivery path and
the live Cerebras API, with gpt-oss-120b in auto format:
| Stage | Median | 95th percentile |
|---|---|---|
| Transcription (Parakeet) | 1.0 s | 1.2 s |
| Cerebras cleanup, including network | 0.39 s | 1.5 s |
| Total, end of speech to text typed | 1.4 s | 2.5 s |
The table is from the final run: 12 takes, spaced 3 s apart, all
cleaned. Across all spaced runs, Cerebras usually answered in
0.2–0.5 s but had a long tail. About 1 take in 10 took more than 2 s:
with the default post_process_timeout it timed out and was typed raw.
The slowest call took 4.2 s. Takes sent back-to-back sometimes got
HTTP 429 queue_exceeded from Cerebras; those were typed raw within
about 70 ms.
Example (one 64-second take), Parakeet’s transcript:
Okay, so um, for the new dashboard, we need a few things first a login page with OAuth second or settings page, where users can change their email address and their notification preferences, and third an export button that dumps everything to CSV, and maybe also JSON if it is easy. Oh, and the deadline for all of this is Friday, no sorry, Thursday. … And then the last thing is the onboarding email. It is way too long, and honestly, nobody reads it, so we should make it shorter and friendlier.
What voxtype typed (line breaks typed as Shift+Enter):
Okay, so for the new dashboard we need a few things:
- A login page with OAuth. I want the login page done first because the other two depend on it.- A settings page where users can change their email address and their notification preferences.- An export button that dumps everything to CSV, and maybe also JSON if it is easy.- The deadline for all of this is Thursday.
…
Finally, the onboarding email is way too long and nobody reads it. We should make it shorter and friendlier, …The live tests (pytest tests/test_voxtype_cerebras.py, with
CEREBRAS_API_KEY set) check filler removal, self-corrections,
paragraphs and lists, short utterances, exact technical terms and URLs,
ignored instructions, dictated requests typed rather than carried
out, and all three formats. All of them pass.
Limitations.
- Transcripts leave your Mac.
- The model mostly restructures faithfully, but it sometimes drops a short aside or an emphasis word (“we really need to move fast”, “honestly”). It also occasionally nests a list or rewords a phrase. It does not fix words Parakeet misheard (“pydesk” for pytest).
- Latency has a long tail, so about 1 long take in 10 exceeds the 2 s
default timeout and is typed raw. Raise
post_process_timeout(for example to 4) if you’d rather wait than lose the cleanup. - Dictating several takes in quick succession can hit Cerebras’s
request-queue limit (
HTTP 429); those takes are typed raw. - Shift+Enter is unsafe in plain shells (see above).
- Corporate HTTP proxies are not used; voxtype connects to
api.cerebras.aidirectly. - Formatting is decided by the model, so it can occasionally add
structure you didn’t intend.
minimalavoids that.
voxtype [flags] run with config + flag overridesvoxtype --set KEY=VALUE ... set any config key for this run (repeatable)voxtype setup [--config PATH] [--force] interactive walkthrough -> writes configvoxtype init [--config PATH] [--force] write the commented sample config to editvoxtype hotkey press a chord; prints the config linevoxtype skill install the voxtype skill into Claude + Codexvoxtype post-process [TEXT] [--provider P] [--format F] [--style S] [--set KEY=VALUE] clean TEXT (or stdin) oncevoxtype --version print the installed versionvoxtype --help full flag reference (per-subcommand: e.g. voxtype setup --help)Flags mirror the config keys: --mode, --engine,
--segmentation, --parakeet-model, --model-arch,
--language, --hotkey, --wake-word,
--stop-phrase, --no-sounds, --no-overlay,
--config PATH. Every other key, and these too,
can be set with --set KEY=VALUE (see the top of
this page).
Double-tap toggle
Section titled “Double-tap toggle”double_tap_key adds a second way to start and stop recording, next
to the hotkey chord: tap one modifier key twice, by itself. It exists
for the laptop keyboard, where a chord like Ctrl+; is awkward without
an external keyboard; right_alt (the right Option key) is a good
choice because nothing else uses it alone.
- Both triggers stay active at once; use whichever is under your hand.
- The taps must be clean: press, release, press, release, with no
other key in between and within
double_tap_msof each other (press to press). Holding the key to type an Option-shortcut or an accented character never triggers it. - The modifier is never swallowed — voxtype only observes it — so Option, Command, and friends keep working everywhere.
- macOS only (it rides on the same event tap as the chord).
Hotkey notation
Section titled “Hotkey notation”Both spellings work everywhere a chord is accepted:
hotkey = "<ctrl>+;" # pynput stylehotkey = "ctrl+;" # bracket-lesshotkey = "cmd+shift+f5" # named keys tooEasiest of all: run voxtype hotkey, press the
combo you want, and paste the printed line into your
config. On macOS matched chords are fully
suppressed — the focused app never sees them — and
context-dependent keys like Esc are only
intercepted while recording.
macOS permissions
Section titled “macOS permissions”Grant these to your terminal app (System Settings → Privacy & Security), once each:
- Microphone — to hear you
- Accessibility — to type into other apps
- Input Monitoring — for the global hotkeys
Troubleshooting
Section titled “Troubleshooting”- Every utterance’s fate is logged to the terminal
(
typed: ...,heard (awaiting wake word): ...,dropped,decoded to empty text) — nothing is discarded silently. Read these lines first. - Wake word not firing? Check the
heardlines for how the model actually spelled it and add that towake_word_aliases; prefer a two-word phrase (“hey claude”) over a bare word. - Quiet dynamic mic (Shure MV7 class)? Automatic gain control is built in; if speech still isn’t detected, move closer to the mic.
take was silent (...): microphone muted, held by another app, or its stream went stale — reopening the microphone? voxtype measured no signal at all during that take (a dead mic reads about a millionth of full scale; even a quiet room reads a thousand times more). Two known causes: a meeting app (Zoom) left the mic muted at the system level — unmute there, or tap the mic’s own mute button — or the audio stream went stale after the device setup changed (opening the lid, plugging in a mic). voxtype reopens the stream on its own, so the stale case fixes itself: just dictate again. Hold mode only; in wake/vad mode a dead mic simply never hears anything.- Dictated into the wrong window? Set
paste_hotkeyand re-type the last session anywhere.