Skip to content

Release v8.12.0

Latest

Choose a tag to compare

@github-actions github-actions released this 21 Jul 12:39

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 next converse() call got no response at all and the MCP
    server then exited on its own, taking voice down until you restarted it.
    CancelledError is 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 to listen_duration_max and
    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 while voicemode 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), and conch status distinguishes
    "free" from "granted but unclaimed".

Added

  • Wall-clock time widget for converse() results (VM-1961) — the opt-in
    time_in_response param / VOICEMODE_TIME_IN_RESPONSE env var (default
    off) appends the local time to every converse() 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)
    with VOICEMODE_SAVE_AUDIO on, stt log entries recorded audio_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 of tools/sound_fonts/
    among them), the legacy cli click group, the expired _env_deprecation.py
    machinery, SecretPathMiddleware, assorted dead helpers and shims, and the
    direct websockets dependency (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-mode

Alternative: Direct Installation

# With UV
uv tool install voice-mode

# With pip
pip install voice-mode==8.12.0

For detailed documentation, visit https://getvoicemode.com