Vox is a voice first engine for conduct AI Agents in conductor
See the codeA floating voice pill for macOS that lets you talk to your Conductor worktrees instead of alt-tabbing between them.
The loop, sped up: a spoken command launches an agent on findy, and Vox says so when it answers.
The startup recap — full mp4 for higher quality.
Vox sits at the bottom of your screen as a small always-on-top bar. Hit Option+Space and talk.
The loop it closes:
Launch — "lance un agent sur findy pour corriger les tests" — and it goes, on any repo Conductor knows about. Follow — "où en sont mes agents ?" — answered from what is actually running, with elapsed time. Hear back — when an agent answers, Vox tells you out loud, summarized or word for word. Ask — "il a dit quoi ?" — the result stays answerable for half an hour.
On launch it reads Conductor's own database and speaks a recap: which agent is working, which is idle, which errored, and what to look at first. Everything runs on your machine by default — no cloud calls, no API keys.
Everything runs on your machine. No cloud calls, no API keys.
launch_agent command targets a repo name, a worktree codename, or "here" for the active project — every repo Conductor knows about, not just the ones with work in progress. Names are matched exactly first, then fuzzily (so a mangled transcription still lands), and a name that matches two repos equally is a spoken question rather than a coin flip. Up to four agents run at once; ⌥Space within two seconds of a launch cancels it, and "stop" kills them all.openai-whisper) daemon; text-to-speech via Kokoro (English) or Piper (French), with macOS say as a last-resort fallback. The brain — the model that turns your voice into an action — is a picker: any model pulled in Ollama (default qwen2.5:3b, fastest), your Claude or Codex subscription through their CLI with no API key, or the Anthropic / OpenAI APIs. A subscription CLI understands more but takes seconds rather than under one; the trade-off is yours.window-vibrancy + NSVisualEffectView), floats above fullscreen apps and every Space, animated waveform per state, and a per-letter transcript reveal so you can see what Vox heard.~/.vox/pronunciations.json (e.g. {"Conductor": "conedeuctor"}) to fix names the TTS engine mangles.~/.vox/venv; the speech stack installs itself into it, isolated from your system Python).claude) on your PATH if you want Vox to launch agents by voice..dmg from Releases.xattr -dr com.apple.quarantine /Applications/Vox.app
~/.vox/venv — a small panel shows the progress. No separate setup script. You just need Python 3.11+ and an internet connection for that first install (scripts/install.sh still exists as a manual fallback).ollama pull qwen2.5:3b
| Shortcut | Action |
|---|---|
| Option+Space | Start/stop listening. Also interrupts Vox while it's speaking or during the startup recap. |
| Cmd+, | Open/close settings (model, language, version, updates). |
Hover the pill to reveal the settings gear; click it, or use the shortcut, either works.
Example things to say:
English
Français
Vox replies in one short spoken sentence — it's built to be glanceable and interruptible, not a conversation partner.
All config lives under ~/.vox/:
settings.json — model and language. Written whenever you change something in the settings panel.
{
"model": "qwen2.5:3b",
"language": "en",
"agent_reply": "summary",
"agent_reply_max_chars": 420,
"tts_engine": "auto"
}
agent_reply is summary (default), verbatim, or off — off still remembers results and still answers questions about them, it just never speaks unprompted. Verbatim switches to a summary past agent_reply_max_chars of cleaned text (~30 seconds of speech). tts_engine is auto (Kokoro for English, Piper for French) or an explicit kokoro / piper / qwen3 / say.projects.json — project name → filesystem path, used by the "switch project" voice command. Auto-created on first launch with the folder Vox was started from.
{ "vox": "/Users/you/code/vox", "my-app": "/Users/you/code/my-app" }
pronunciations.json — word → phonetic respelling, applied before text hits the TTS engine. Not created automatically; add it yourself.
{ "Conductor": "conedeuctor" }
This doubles as a speech-recognition alias: if you taught the voice to say orivo as oreevo, Vox also accepts hearing "oreevo" and resolves it back.aliases.json — optional, spoken form → real name, for repos whose names Whisper mangles. Not created automatically.
{ "orie vo": "orivo" }
Advanced: environment variables override the persisted settings at launch, mainly useful for development — VOX_MODEL, VOX_LANG, VOX_PROJECT, VOX_TTS, VOX_SAY_VOICE, VOX_AGENT_TIMEOUT, VOX_AGENT_REPLY, plus:
VOX_MAX_AGENTS (default 4) — simultaneous agents. Each one is a full Claude Code process and they share a rate limit; past four a laptop also running Ollama and a speech model starts to crawl. Over the cap Vox refuses out loud rather than queueing silently.VOX_DRAFT_MODEL — a second local model used only to expand a spoken request into a full agent prompt. It runs after the spoken confirmation, so a bigger model's latency is invisible. Defaults to the main model.VOX_DEBUG_SAY="…" — drive one full turn at startup without a microphone. The mic needs a signed bundle, so this is the way to exercise the loop from npm run tauri dev.Two agents in the same worktree is allowed (Vox says "that's two agents on findy now") but they can conflict on files — it's the same situation as two terminals in one directory.
Vox is a Tauri 2 app: a Rust backend (src-tauri/) driving a small always-on-top webview (renderer/index.html) that renders the pill, captures the mic, and plays audio back — keeping playback in the browser is what makes echo-cancelled barge-in possible.
src-tauri/resources/vox_stt.py) that keeps an openai-whisper model resident in memory and talks over a line-based stdin/stdout protocol; it falls back to the whisper CLI if the daemon isn't available.launch_agent, prompt_worktree, switch_project). Models without native tool-calling get a JSON-object prompt fallback.vox_tts.py / vox_tts_piper.py) as the LLM generates them — or macOS say if neither is available. The renderer plays each WAV; synthesis runs one sentence ahead of playback.sqlite3 CLI against Conductor's own database (~/Library/Application Support/com.conductor.app/conductor.db). Vox never writes to it.claude --print --dangerously-skip-permissions "<task>" in the target worktree (the active project, or any worktree resolved by name from Conductor's database), with a 10-minute default timeout (VOX_AGENT_TIMEOUT) and a live agent-count badge on the pill.Prerequisites: Node 20+, a stable Rust toolchain, and Xcode Command Line Tools (for the macOS-only blur and window APIs).
npm install
npm run dev # run locally (file watcher off — see .taurignore)
npm run tauri build # produce a release .app bundle
The GitHub Actions release workflow (.github/workflows/release.yml) additionally builds a .dmg and attaches it to the release on every v* tag push.
Qwen3-TTS ships as an optional third engine, installed from the setup panel into its own virtualenv (~/.vox/venv-qwen) so a failed experiment can't disturb Kokoro or Piper. Once installed, a Voice row appears in settings; changing it restarts the daemon and immediately speaks a sample line.
Measure before replacing anything:
python3 scripts/vox_tts_bench.py --engines piper,kokoro --langs fr --repeat 3 # baseline first
python3 scripts/vox_tts_bench.py --engines piper,kokoro,qwen3 --langs fr,en --repeat 3
It drives the daemons exactly as Rust does and writes report.md (cold start, time to first sentence, RTF, peak RSS), bench.json, the WAVs side by side, and ab.html — a blind listening test with the engine names folded away. report.md carries the pass/fail thresholds; the quality call is made by ear.
Baseline on an M-series Mac, French, 14 sentences × 2:
| engine | cold ms | 1st sentence | synth p95 | RTF p95 | peak RSS |
|---|---|---|---|---|---|
| piper | 600 | 111 ms | 111 ms | 0.025 | 365 MB |
| kokoro | 4901 | 369 ms | 609 ms | 0.105 | 2158 MB |
scripts/vox_tts_selftest.py guards the shared text-normalisation module against regressions.
NSVisualEffectView, which is macOS-only, so this isn't a near-term priority.MIT — see LICENSE.
12 commits
TypeScript
76.6%
Go Template
10.5%
Shell
5.5%
Rust
3.1%
JavaScript
1.7%
HTML
1.1%
Vox is a voice first engine for conduct AI Agents in conductor
See the codeA floating voice pill for macOS that lets you talk to your Conductor worktrees instead of alt-tabbing between them.
The loop, sped up: a spoken command launches an agent on findy, and Vox says so when it answers.
The startup recap — full mp4 for higher quality.
Vox sits at the bottom of your screen as a small always-on-top bar. Hit Option+Space and talk.
The loop it closes:
Launch — "lance un agent sur findy pour corriger les tests" — and it goes, on any repo Conductor knows about. Follow — "où en sont mes agents ?" — answered from what is actually running, with elapsed time. Hear back — when an agent answers, Vox tells you out loud, summarized or word for word. Ask — "il a dit quoi ?" — the result stays answerable for half an hour.
On launch it reads Conductor's own database and speaks a recap: which agent is working, which is idle, which errored, and what to look at first. Everything runs on your machine by default — no cloud calls, no API keys.
Everything runs on your machine. No cloud calls, no API keys.
launch_agent command targets a repo name, a worktree codename, or "here" for the active project — every repo Conductor knows about, not just the ones with work in progress. Names are matched exactly first, then fuzzily (so a mangled transcription still lands), and a name that matches two repos equally is a spoken question rather than a coin flip. Up to four agents run at once; ⌥Space within two seconds of a launch cancels it, and "stop" kills them all.openai-whisper) daemon; text-to-speech via Kokoro (English) or Piper (French), with macOS say as a last-resort fallback. The brain — the model that turns your voice into an action — is a picker: any model pulled in Ollama (default qwen2.5:3b, fastest), your Claude or Codex subscription through their CLI with no API key, or the Anthropic / OpenAI APIs. A subscription CLI understands more but takes seconds rather than under one; the trade-off is yours.window-vibrancy + NSVisualEffectView), floats above fullscreen apps and every Space, animated waveform per state, and a per-letter transcript reveal so you can see what Vox heard.~/.vox/pronunciations.json (e.g. {"Conductor": "conedeuctor"}) to fix names the TTS engine mangles.~/.vox/venv; the speech stack installs itself into it, isolated from your system Python).claude) on your PATH if you want Vox to launch agents by voice..dmg from Releases.xattr -dr com.apple.quarantine /Applications/Vox.app
~/.vox/venv — a small panel shows the progress. No separate setup script. You just need Python 3.11+ and an internet connection for that first install (scripts/install.sh still exists as a manual fallback).ollama pull qwen2.5:3b
| Shortcut | Action |
|---|---|
| Option+Space | Start/stop listening. Also interrupts Vox while it's speaking or during the startup recap. |
| Cmd+, | Open/close settings (model, language, version, updates). |
Hover the pill to reveal the settings gear; click it, or use the shortcut, either works.
Example things to say:
English
Français
Vox replies in one short spoken sentence — it's built to be glanceable and interruptible, not a conversation partner.
All config lives under ~/.vox/:
settings.json — model and language. Written whenever you change something in the settings panel.
{
"model": "qwen2.5:3b",
"language": "en",
"agent_reply": "summary",
"agent_reply_max_chars": 420,
"tts_engine": "auto"
}
agent_reply is summary (default), verbatim, or off — off still remembers results and still answers questions about them, it just never speaks unprompted. Verbatim switches to a summary past agent_reply_max_chars of cleaned text (~30 seconds of speech). tts_engine is auto (Kokoro for English, Piper for French) or an explicit kokoro / piper / qwen3 / say.projects.json — project name → filesystem path, used by the "switch project" voice command. Auto-created on first launch with the folder Vox was started from.
{ "vox": "/Users/you/code/vox", "my-app": "/Users/you/code/my-app" }
pronunciations.json — word → phonetic respelling, applied before text hits the TTS engine. Not created automatically; add it yourself.
{ "Conductor": "conedeuctor" }
This doubles as a speech-recognition alias: if you taught the voice to say orivo as oreevo, Vox also accepts hearing "oreevo" and resolves it back.aliases.json — optional, spoken form → real name, for repos whose names Whisper mangles. Not created automatically.
{ "orie vo": "orivo" }
Advanced: environment variables override the persisted settings at launch, mainly useful for development — VOX_MODEL, VOX_LANG, VOX_PROJECT, VOX_TTS, VOX_SAY_VOICE, VOX_AGENT_TIMEOUT, VOX_AGENT_REPLY, plus:
VOX_MAX_AGENTS (default 4) — simultaneous agents. Each one is a full Claude Code process and they share a rate limit; past four a laptop also running Ollama and a speech model starts to crawl. Over the cap Vox refuses out loud rather than queueing silently.VOX_DRAFT_MODEL — a second local model used only to expand a spoken request into a full agent prompt. It runs after the spoken confirmation, so a bigger model's latency is invisible. Defaults to the main model.VOX_DEBUG_SAY="…" — drive one full turn at startup without a microphone. The mic needs a signed bundle, so this is the way to exercise the loop from npm run tauri dev.Two agents in the same worktree is allowed (Vox says "that's two agents on findy now") but they can conflict on files — it's the same situation as two terminals in one directory.
Vox is a Tauri 2 app: a Rust backend (src-tauri/) driving a small always-on-top webview (renderer/index.html) that renders the pill, captures the mic, and plays audio back — keeping playback in the browser is what makes echo-cancelled barge-in possible.
src-tauri/resources/vox_stt.py) that keeps an openai-whisper model resident in memory and talks over a line-based stdin/stdout protocol; it falls back to the whisper CLI if the daemon isn't available.launch_agent, prompt_worktree, switch_project). Models without native tool-calling get a JSON-object prompt fallback.vox_tts.py / vox_tts_piper.py) as the LLM generates them — or macOS say if neither is available. The renderer plays each WAV; synthesis runs one sentence ahead of playback.sqlite3 CLI against Conductor's own database (~/Library/Application Support/com.conductor.app/conductor.db). Vox never writes to it.claude --print --dangerously-skip-permissions "<task>" in the target worktree (the active project, or any worktree resolved by name from Conductor's database), with a 10-minute default timeout (VOX_AGENT_TIMEOUT) and a live agent-count badge on the pill.Prerequisites: Node 20+, a stable Rust toolchain, and Xcode Command Line Tools (for the macOS-only blur and window APIs).
npm install
npm run dev # run locally (file watcher off — see .taurignore)
npm run tauri build # produce a release .app bundle
The GitHub Actions release workflow (.github/workflows/release.yml) additionally builds a .dmg and attaches it to the release on every v* tag push.
Qwen3-TTS ships as an optional third engine, installed from the setup panel into its own virtualenv (~/.vox/venv-qwen) so a failed experiment can't disturb Kokoro or Piper. Once installed, a Voice row appears in settings; changing it restarts the daemon and immediately speaks a sample line.
Measure before replacing anything:
python3 scripts/vox_tts_bench.py --engines piper,kokoro --langs fr --repeat 3 # baseline first
python3 scripts/vox_tts_bench.py --engines piper,kokoro,qwen3 --langs fr,en --repeat 3
It drives the daemons exactly as Rust does and writes report.md (cold start, time to first sentence, RTF, peak RSS), bench.json, the WAVs side by side, and ab.html — a blind listening test with the engine names folded away. report.md carries the pass/fail thresholds; the quality call is made by ear.
Baseline on an M-series Mac, French, 14 sentences × 2:
| engine | cold ms | 1st sentence | synth p95 | RTF p95 | peak RSS |
|---|---|---|---|---|---|
| piper | 600 | 111 ms | 111 ms | 0.025 | 365 MB |
| kokoro | 4901 | 369 ms | 609 ms | 0.105 | 2158 MB |
scripts/vox_tts_selftest.py guards the shared text-normalisation module against regressions.
NSVisualEffectView, which is macOS-only, so this isn't a near-term priority.MIT — see LICENSE.
12 commits
TypeScript
76.6%
Go Template
10.5%
Shell
5.5%
Rust
3.1%
JavaScript
1.7%
HTML
1.1%