EXPERIMENTAL · APPLE SILICON macOS · BUILD FROM SOURCE

Hold a key. Speak. Release.

Your words land at the cursor of the app you’re already in. No dictation window, no copy-paste.

How it works

One gesture. One destination. Two routes to get there.

Hold the Talk Key (Right Option) and one Utterance opens. Speak; on release, type-wave commits the Final Transcript — the only text it ever inserts — and places it at your Focused Target, the cursor of the app that already has focus. One hold, one insertion. A silent HUD shows a red waveform while you talk, then green processing dots until the text lands — it never shows the transcript itself.

OpenAI Realtime — the default

Streams your voice to OpenAI's Realtime API over an encrypted WebSocket and returns text as you speak. The default model is gpt-live-transcribe, with live Partial Transcripts and vocabulary biasing. Needs an OpenAI API key with Realtime access. Your audio streams to OpenAI while you dictate.

Local Whisper — offline

Runs Whisper Large v3 Turbo entirely on your Mac. No API key, no network while you dictate — the audio never leaves your machine. A one-time, credential-free model download and you're set.

Backtrack — opt-in

Talk the way you think — corrections and all. Turn on Backtrack and type-wave rewrites your spoken self-corrections into the finished text: “send it to Bob, no, to Alice” lands as “send it to Alice.” It is off by default and, when enabled, runs the rewrite through OpenAI — a cloud step you opt into, never part of the offline local route.

Around the loop

Teach it your words, get a dictation back when it lands somewhere you didn’t mean, and take one back when you didn’t mean to say it.

Custom vocabulary — cloud and local

Names, jargon, product words — type-wave, whisper.cpp, the spelling of your own name. Keep one shared list in the menu bar: it biases the default OpenAI model from your next dictation and local Whisper when you switch to it. Edits reach a warm OpenAI session between Utterances, with no restart. The list starts empty and changes nothing until you add to it; a term nudges the spelling, never guarantees it. Pin an older or unknown OpenAI model without keywords support and the OpenAI side stays inert — the menu says “local only.”

Recent Insertions — offline

Sometimes an insertion lands in the wrong app, or focus moves mid-Utterance and the text is simply gone. The last 20 land in a menu-bar list instead. Entries are masked — the app, the time, a character count, never the text — until you ⌥-click one to reveal it; from there you can copy it or re-insert it at your cursor. It lives in memory only: never written to disk, cleared when type-wave quits, and no network on any path.

Undo the last insertion — ⌃⌘⌫

Press ⌃⌘⌫ and the newest insertion is deleted, trailing space and all. It is single-shot and guarded: it fires only while the app it typed into is still frontmost, and it refuses rather than eat text it did not write. The HUD shows the outcome without showing the text — a green bloom when the characters came out, a red shake when it refused. The undone entry stays in Recent Insertions, dimmed; re-inserting it is your redo.

type-wave demo: hold the Talk Key, speak, release, and the Final Transcript lands at the cursor of a TextEdit window.

Your voice can stay on your Mac

Switch to local Whisper and type-wave goes fully offline.

Point the Backend Router at local Whisper and type-wave stops touching the network. Your voice is captured, transcribed, and inserted without a byte leaving your Mac — no API key, no cloud, no dictation-time network. The only fetch is a one-time, credential-free download of the pinned model; after that, local mode runs with no network at all. (In the default OpenAI mode, your audio does stream to OpenAI while you dictate — privacy is what you get when you choose local.)

What type-wave keeps, it keeps in memory. The last 20 insertions stay in the Recent Insertions ring so you can recover a lost dictation — masked in the menu until you deliberately reveal one, never written to disk, and gone when type-wave quits.

Build it and run it

From source with Nix and Zig on an Apple Silicon Mac. No binary to download — you build it yourself.

Try it (foreground dev run)

export OPENAI_API_KEY=sk-...
nix develop --command zig build run

Install for daily use (LaunchAgent)

nix develop --command zig build install-agent
~/.local/bin/type-wave --set-key

Prefer offline? Choose the local backend and you can skip the API key.

HOW IT WAS BUILT

Charted with wayfinder, part of Matt Pocock's AI Skills for Real Engineers. The plan for this site was mapped as decision tickets and resolved one at a time before a line was built.