Voice input
Speak prompts in the terminal UI, desktop app, phone and CLI. Transcribe on your ChatGPT plan, live with gpt-live-transcribe, or offline with whisper.cpp.
Copy & share
On this page18 sections
Voice input lets you speak a prompt instead of typing it. It works in the terminal UI (TUI), the desktop app, the phone app and the headless CLI. Empryo records a short clip, turns it into text, and either puts the text in your message box for review or sends it right away.
Option 1: your operating system's dictationLink to this section
You do not need Empryo's voice feature at all if your system already has dictation. It types into any text field, including Empryo's message box.
- macOS: turn on System Settings → Keyboard → Dictation. Click into the message box, press the dictation key (🎤 or Fn), and speak.
- Windows: press Win+H.
Use Empryo's own voice input when you want better accuracy on technical words, automatic sending, headless runs, or Linux.
Option 2: offline with whisper.cpp (free, no key)Link to this section
whisper.cpp runs speech-to-text on your own machine. Nothing leaves your computer and you need no API key.
First install it:
brew install whisper-cpp # macOS. Linux/Windows: grab the official
# prebuilt from github.com/ggml-org/whisper.cpp/releases
# (whisper-bin-ubuntu-*.tar.gz / whisper-bin-x64.zip)
# and put whisper-cli on PATH. Linux needs libgomp1.Then download a model. In the TUI, run /voice setup. It downloads the default model and tells you when the mic is ready. To pick a different model, name it:
| Command | Size | Notes |
|---|---|---|
/voice setup tiny.en | ~75 MB | Fastest, English only |
/voice setup base.en | ~142 MB | Fast, English only. The default |
/voice setup small.en | ~466 MB | More accurate, English only |
/voice setup large-v3-turbo-q5_0 | ~547 MB | Best quality, all languages |
You can also download a model yourself:
mkdir -p ~/.local/share/whisper-cpp
curl -L -o ~/.local/share/whisper-cpp/ggml-base.en.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.binOn Windows, use %USERPROFILE%\.local\share\whisper-cpp instead.
Empryo looks for models in ~/.local/share/whisper-cpp, ~/.cache/whisper-cpp, and Homebrew's share/whisper-cpp/models folder. If it finds several, it uses the most accurate one. To choose a model yourself, set voice.localModel to a model name ("base.en") or a full file path.
The desktop app records in a different audio format. It converts the recording with ffmpeg before passing it to whisper.cpp, so install ffmpeg if you use local transcription in the desktop app.
Option 3: cloud transcription with an OpenAI or Groq keyLink to this section
Your ChatGPT plan (the default)Link to this section
If you signed in to ChatGPT with /login codex, voice input works with no key and no extra setup. Empryo sends each clip to the transcription service ChatGPT's own apps use, so it runs on your plan instead of an API bill. It is the default whenever you are signed in, even when you also have an API key. Picking chatgpt/transcribe while signed out uses your OpenAI or Groq key instead; with no key, voice says to run /login codex rather than showing ready. If a clip fails on the plan, it goes to your key at api.openai.com (or Groq), never to ChatGPT.
- The text arrives when you stop talking, in about a second. Words while you speak need an OpenAI API key: turn live dictation on to use it.
- It takes no keywords, so product names can come out misspelled ("Empryo" became "MPRIO" in our tests). Pick
openai/gpt-transcribeand setvoice.keywordswhen names matter. - ChatGPT keeps each clip in your account for 30 days. Empryo cannot shorten that: the service ignores retention options and refuses to delete the file (tested September 30, 2026).
- It is not a public API, so OpenAI can change or block it. When a clip fails there, Empryo transcribes it with your OpenAI or Groq key, or local Whisper, instead.
An API keyLink to this section
If you already have an OpenAI or Groq key, voice input works with no extra setup.
empryo --set-key groq <key>
# or
empryo --set-key openai <key>| Key | Model Empryo uses | Price (September 2026 list) |
|---|---|---|
| ChatGPT plan (signed in) | ChatGPT's transcription service | part of your plan |
| OpenAI | gpt-transcribe, OpenAI's most accurate speech-to-text model | $0.0045 per minute |
| Groq only | whisper-large-v3-turbo | free tier, then per hour |
A ChatGPT sign-in wins over keys, and OpenAI wins over Groq. Pick another model with /voice model in the TUI, the Voice page in desktop Settings, or the config.
Live dictation: words appear as you speakLink to this section
With an OpenAI API key and no ChatGPT sign-in, live dictation is on by default. When you are signed in to ChatGPT it is off by default, so your plan does the work; turn it on to spend your key on live words. Your words show up in the draft while you talk, the way ChatGPT's dictation does, without a voice conversation. Stop talking and it stops by itself; the draft already holds the final text.
Empryo keeps a connection to OpenAI ready before you press the mic, so the first words appear about a second after you start and the last ones about half a second after you stop (measured on September 30, 2026).
- TUI:
/voice live offor/voice live on, or/voice settingsand pick Live dictation. - Desktop:
/voice live offor/voice live onin the composer, or Settings → Voice → Live dictation./voice settingsopens that page, and searching Settings for "dictation" jumps there. - Anywhere: ask Empryo to set
voice.livetofalseto turn it off.
Stops when you go quietLink to this section
After you speak, about 2.5 seconds of quiet ends the recording and the text lands in the draft, or is sent if voice.insertMode is "send". Holding the shortcut to talk ignores quiet and stops when you let go. Change the wait with /voice auto-stop 4, the Stop after silence row in desktop Settings, or voice.autoStop. 0 or off keeps listening until you stop it. The phone app reads the same wait from your computer's config.
Hands-free: talk, pause, it sends, it listens againLink to this section
Turn on hands-free and you only press the mic once. Each time you go quiet, what you said is sent, and the mic opens again for the next thing you say. Stretches with no speech are thrown away instead of sent. Press the mic again to end the session; what you said up to then is still sent. Esc ends it too, but throws away what you said since the last pause.
- TUI:
/voice hands-free on, or/voice settingsand pick Hands-free. The recording line shows "hands-free" while it listens. - Desktop:
/voice hands-free onin the composer, or Settings → Voice → Hands-free. The mic's tooltip says it is listening. - Phone: touch and hold any mic and pick Hands-free, or open Settings → Voice. The phone reads and writes the same setting on your computer, so all three always agree. A small repeat badge on the mic means it is listening hands-free.
- Anywhere: ask Empryo to set
voice.handsFreetotrue.
Hands-free always sends; it ignores voice.insertMode. If voice.autoStop is 0, hands-free still stops after 2.5 seconds of quiet, because it needs a pause to know when you are done. On the ChatGPT plan it costs nothing extra; with live dictation on, the open mic streams to OpenAI and is billed per minute while it listens.
Live dictation uses gpt-live-transcribe ($0.017 per minute) and needs an OpenAI API key. Empryo streams your microphone at 24 kHz to OpenAI's Realtime API. A pause of about 0.7 seconds closes a sentence, so the text before it becomes final while you keep talking. Empryo still records the whole clip: if the live stream drops, it transcribes the recording with your normal model instead, so nothing you said is lost.
voice.delay trades speed for accuracy. The default is low, which gave the fastest first words in our tests without losing accuracy.
| Delay | Behaviour |
|---|---|
minimal | Words appear fastest |
low | Fast, good for captions |
medium | Balanced |
high | More accurate, words arrive later |
xhigh | Most accurate, slowest |
Live dictation works in the TUI, the desktop app and the phone app. Headless runs record a clip and transcribe it when you press Enter.
Use voice in the TUILink to this section
- Press
Ctrl+Y, click the mic button in the message box, or run/voice. - Speak. The message box shows
● RECand a small level meter that moves with your voice, so you can see the mic is picking you up. - Press
Ctrl+Yagain to stop. PressEscinstead to cancel and throw the recording away. - Wait while it shows
transcribing…. The text is added to your draft, after anything you already typed. With live dictation on, the words appear while you speak. - Edit the draft if you want, then press
Enterto send.
To send the text automatically instead, set voice.insertMode to "send".
Use voice in the desktop appLink to this section
The desktop app records through your system microphone, so it needs microphone permission. You do not need a separate recording tool.
- Click the mic button in the message box, or press
⌘Yon macOS orCtrl+Yon Windows and Linux. - Speak. The mic icon pulses with your voice.
- Click the mic button again to stop. Press
Escto cancel instead. - Review the text in your draft, then send it.
You can also hold the shortcut to talk. Hold the key, speak, and let go. Recording stops and transcribes when you release. A quick tap (under 400 ms) starts and stops recording as usual.
By default the text stays in your draft (voice.insertMode is "insert"). Set it to "send" to send it automatically.
Use voice in headless modeLink to this section
You need an interactive terminal for this. Run:
empryo --headless --voiceEmpryo records until you press Enter. A status line shows the elapsed time and a level meter. Press Esc or Ctrl+C to cancel. The text becomes your prompt.
If you also type or pipe a prompt, the spoken text is added after it:
empryo --headless --voice "also update the tests"Configure transcriptionLink to this section
Voice settings live under voice in config.json. That is ~/.empryo/config.json for all projects, or .empryo/config.json for one project.
{
"voice": {
"model": "openai/gpt-transcribe",
"language": "en",
"insertMode": "insert",
"live": true,
"delay": "medium",
"prompt": "A coding session in a TypeScript monorepo called Empryo.",
"keywords": ["Empryo", "Genome", "useChat", "Bun"]
}
}| Key | What it does |
|---|---|
model | Speech-to-text model as provider/model: chatgpt/transcribe (your ChatGPT plan), openai/gpt-transcribe, openai/gpt-4o-transcribe, openai/gpt-4o-mini-transcribe or groq/whisper-large-v3-turbo. That provider needs a key. |
language | The language you speak, as one code (en) or a list (en,fr). Leave it out to detect the language. |
insertMode | "insert" puts the text in your draft. "send" sends it right away. |
live | Shows words as you speak. On by default when you have an OpenAI API key and are not signed in to ChatGPT; true or false sets it either way. |
autoStop | Seconds of quiet after you speak before recording stops by itself. Default 2.5; 0 keeps listening. |
handsFree | true sends each time you go quiet and listens again until you stop the mic. Off by default. |
liveModel | The live model. Defaults to gpt-live-transcribe. |
delay | Live speed against accuracy: minimal, low (default), medium, high or xhigh. |
prompt | A sentence about what you usually talk about. It helps with jargon. |
keywords | Exact words to expect, such as names and identifiers. No <, > or line breaks. |
prompt and keywords go to gpt-transcribe and gpt-live-transcribe. Other models get prompt only. A project that is not trusted cannot set prompt or keywords, because they can change what the transcript says.
In the TUI, /voice settings opens all of this in one picker, and /voice model, /voice live, /voice hands-free, /voice auto-stop, /voice delay and /voice language change one thing each. In the desktop app it is Settings → Voice, which also shows which model will run and why live dictation is not ready. On the phone, touch and hold any mic for hands-free, live words, what happens when you finish and the quiet wait, or open Settings → Voice for the same four. The phone saves them on your computer, so the TUI and desktop change with it.
Every text field on the phone has a mic: the chat box, answers to questions, steering a running step, plan notes, new schedules, handoff notes and the reason for stopping a step. Only the field you started from receives the words. Fields that send (chat, answers, steering, plan notes) follow your send and hands-free choices; the others only fill the field.
Change the mic shortcutLink to this section
voice.key changes the mic shortcut in both the TUI and the desktop app:
{
"voice": { "key": "mod+shift+v" }
}Join keys with +. The last part is the key. Everything before it is a modifier.
| Part | Meaning |
|---|---|
ctrl / control | Control |
cmd / meta / command / super | Command on macOS, Windows key on Windows |
mod | Command on macOS, Control everywhere else |
alt / option / opt, shift | Alt or Option, Shift |
| last part | A letter or digit (y), a function key (f5), or a key name (space) |
The defaults are ctrl+y in the TUI and mod+y in the desktop app.
A few rules:
- If Empryo cannot read your shortcut, it uses the default instead of showing an error.
- A single letter with no modifier is not allowed, because it would trigger on every keystroke. Function keys on their own are fine.
Escalways cancels a recording. You cannot change that.- Restart the TUI or the desktop app after changing the shortcut.
Use your own transcription serverLink to this section
Set voice.baseURL to any server that offers an OpenAI-compatible /audio/transcriptions endpoint. This could be a whisper server on your machine or on your local network. Your audio then stays on your network. A custom server needs no provider key, and model can be a plain name:
{
"voice": {
"baseURL": "http://localhost:9000/v1",
"model": "large-v3"
}
}Transcribe with a chat model that understands audioLink to this section
Set voice.llm to send the recording to a chat model that accepts audio, instead of a speech-to-text endpoint. Any provider you have set up works. Use voice.instruction to tell the model how to write the text, for example to remove filler words:
{
"voice": {
"llm": "openai/gpt-4o-audio-preview",
"instruction": "Transcribe faithfully, but drop filler words and add punctuation."
}
}Use your own recording commandLink to this section
voice.command replaces the recording command in the TUI and headless mode. Empryo replaces every {output} with the path of the audio file. The command must keep recording until it is stopped, and write an audio format your transcription service accepts:
{
"voice": { "command": ["sox", "-d", "-c", "1", "{output}"] }
}Requirements and troubleshootingLink to this section
The TUI and headless mode record with a command-line tool. Empryo uses the first one it finds:
- macOS:
rec(part of SoX) orffmpeg. Runbrew install soxif you have neither. - Linux:
arecord(fromalsa-utils),ffmpeg, orrec(SoX). - Windows:
ffmpeg.
If none is installed, the error message tells you what to install for your system.
Each recording can be up to 5 minutes long, and the audio file can be up to 10 MB.
PrivacyLink to this section
Empryo sends your audio only to the transcription service you configured. With whisper.cpp, it never leaves your machine.
In the TUI and headless mode, the recording is saved to a private temporary file and deleted after transcription or when you cancel. The desktop app keeps the recording in memory until transcription finishes.