Fixed
Cancelling voice no longer kills your session (VM-2015)
Pressing ESC during a voice call used to leave everything broken behind you.
This one has been with us for months and survived an earlier attempt at a fix
(VM-1026) — it's properly fixed now.
- ESC wedged the connection, then killed the server — the cancel looked
clean, but the nextconverse()call got no response at all and the MCP
server then exited on its own, taking voice down until you restarted it.
CancelledErroris now handled at the boundary the MCP SDK expects, so a
cancel unwinds one request instead of the whole server. - The microphone kept recording after a cancel — recording ran on a thread
that couldn't be interrupted, so it ran on tolisten_duration_maxand
transcribed audio nobody asked for. It's now cooperatively cancellable and
releases the mic in under a second (measured 0.4s vs 17.5s on a 20s limit),
including when the client goes away without cancelling at all — agent
killed, terminal closed, broken pipe.
Other fixes
- A stuck conch grant could block every waiter forever (VM-1967) — a
WAIT-mode call cancelled mid-wait left its queue entry registered, and once
granted it deadlocked everyone behind it whilevoicemode conch status
still reported the conch free. Queue entries are now deregistered on every
exit path, an unclaimed grant self-heals after
VOICEMODE_CONCH_GRANT_TTL(default 30s), andconch statusdistinguishes
"free" from "granted but unclaimed".
Added
-
Wall-clock time widget for
converse()results (VM-1961) — the opt-in
time_in_responseparam /VOICEMODE_TIME_IN_RESPONSEenv var (default
off) appends the local time to everyconverse()return as a trailing
| Widgets: time HH:MM:SS, so the agent has a clock instead of guessing.
Text-only, never spoken. See
converse-parameters.md. -
Saved STT recordings are now linked from the conversation log (VM-4) —
withVOICEMODE_SAVE_AUDIOon,sttlog entries recordedaudio_file: null, so a transcript couldn't be tied back to its recording. The filename
is now logged for both single listens and survey turns, matching what TTS
entries already did. No schema change.
Removed
- ~2,300 lines of confirmed-dead code removed (VM-1811) — code with zero
live callers, verified by AST import-map and caller-grep across the package.
No behaviour change. Includes 7 orphan modules (all oftools/sound_fonts/
among them), the legacycliclick group, the expired_env_deprecation.py
machinery,SecretPathMiddleware, assorted dead helpers and shims, and the
directwebsocketsdependency (still available transitively via fastmcp).
Installation
Quick Start (Recommended)
# Install UV package manager (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install VoiceMode and configure services
uvx voice-mode-install
# Add to Claude Code MCP
claude mcp add --scope user voicemode -- uvx --refresh voice-modeAlternative: Direct Installation
# With UV
uv tool install voice-mode
# With pip
pip install voice-mode==8.12.0For detailed documentation, visit https://getvoicemode.com