VoiceMode Documentation

repository·master·Indexed 22 days ago

https://github.com/mbailey/voicemode

VoiceMode is a voice-centric interaction system providing voice interaction capabilities for AI assistants. It includes the voice-mode-install utility for automating system-level dependencies across macOS, Ubuntu/Debian, and Fedora/RHEL, and integrates with Claude Code via a plugin and MCP server. The system supports TTS providers like OpenAI and Kokoro, and offers tools for conducting natural voice conversations through the mcp__voicemode__converse tool.

Tokens
79.7K
Snippets
192
Records
445
Agent score
77%

What's inside VoiceMode

  1. Replay utterances with skip_back and the history buffer

    master

    skip_back acts as 'CD transport', allowing you to jump back through previously spoken utterances using the server's in-memory history buffer.

    The History Buffer

    • Contents: Stores the last N rendered utterances, including decoded PCM audio, text, and metadata (sample_rate, channels, timestamp, voice).
    • Configuration: The buffer size is controlled by VOICEMODE_HISTORY_BUFFER_SIZE (default: 8, min: 1).
    • Lifecycle: The buffer is process-wide and lives for the life of the server; it is not persisted across restarts.
    • Capture Logic: Utterances are captured in full. If pause or skip_back is called mid-playback, the server continues draining the provider to ensure the full utterance is buffered.

    Skip-back Semantics

    • First press: Restarts the current/most-recent utterance from the beginning.
    • Subsequent presses: Steps back one utterance at a time through the buffer.
    • Clamping: Once the oldest record is reached, further presses continue replaying that oldest record.

    Note: skip_back is a playback-layer operation. It does not trigger new STT, model calls, or agent turns.

    {"command": "skip_back"}
  2. How VoiceMode architecture works

    master
    VoiceMode is built as a Model Context Protocol (MCP) server that provides voice capabilities to AI assistants. It uses a modular architecture that separates voice services (STT/TTS), audio processing, and client interfaces. The system follows a hierarchical flow where an MCP Client (like Claude) communicates via the MCP protocol with the VoiceMode MCP Server, which then orchestrates tools, providers, and configuration to interact with underlying voice services like Whisper and Kokoro.
  3. Use the Parallel Operations Pattern for natural flow

    master

    To prevent dead air and create a more natural conversation, use wait_for_response=False when performing actions that do not require user confirmation. This allows the speech to play while your code simultaneously executes other tools or operations.

    When to use:

    • File operations (reading, writing, searching)
    • Data processing (analysis, computation)
    • Status updates during long operations
    • Confirmations that don't need user approval

    When NOT to use:

    • Questions requiring answers
    • Confirmations needing user approval
    • Error messages needing acknowledgment
    • End of conversation farewells
    converse("Searching for that file", wait_for_response=False)
    # Immediately execute:
    Grep(pattern="function_name", output_mode="files_with_matches")
  4. How the VoiceMode control channel works

    master

    The control channel operates as a side channel into the running VoiceMode server using a Unix domain socket (AF_UNIX).

    Key Mechanics:

    • Triggering: An external process writes a newline-delimited JSON command to the socket.
    • Latency: The TTS playback loop polls the control state every audio chunk (~85 ms), ensuring commands like stop land in under ~200 ms.
    • Transport Styles:
      • Cassette transport: Handles pause, resume, stop, and skip_forward. skip_forward acts as a universal advance: it cuts the current utterance and hands control to your next record turn.
      • CD transport: Handles skip_back. This uses a process-wide history buffer (of size defined by VOICEMODE_HISTORY_BUFFER_SIZE) to replay previously spoken audio. Replaying cached audio does not start a new agent turn.
    • Security: The channel is local-only. The server performs a peer-credential check to ensure only processes with the same UID can connect to the socket.
  5. Understand the MFP file structure and playback modes

    master

    All Music For Programming assets are stored in ~/.voicemode/music-for-programming/. The system selects different metadata formats based on whether you are streaming or playing locally:

    ModeConditionMetadata Format
    StreamingAudio not cached locally.ffmeta (FFMETADATA)
    LocalAudio exists in cache.cue (CUE sheet)

    File Types:

    • rss.xml: Cached RSS feed.
    • .mp3: The audio file.
    • .cue: CUE sheet for local playback track navigation.
    • .ffmeta: FFMETADATA chapters for HTTP streaming navigation.
  6. Understand VoiceMode environment variable precedence

    master

    VoiceMode processes environment variables in a specific hierarchy. If a variable is defined in multiple places, the one higher in this list takes precedence:

    1. Command-line environment: e.g., OPENAI_API_KEY=xxx voicemode
    2. MCP host configuration: Variables defined in the MCP server host settings.
    3. Shell environment variables: Variables in your current shell session.
    4. Project .voicemode.env file: Located in your project root.
    5. User ~/.voicemode/voicemode.env file: Global user configuration.
    6. Built-in defaults: The fallback values defined within the application.
  7. Understand and adjust VAD levels

    master

    Voice Activity Detection (VAD) aggressiveness controls how strictly the system identifies speech versus noise. Adjust the vad_aggressiveness parameter based on your environment:

    LevelDescriptionRecommended Environment
    0Least aggressive (captures everything)Silent room, Dictation mode
    1Low (slightly stricter)Silent room, Dictation mode
    2Balanced (default)Home office
    3Most aggressive (strict speech detection)Busy office, Cafe, Outdoors

    Note: For dictation mode, combine low VAD (0-1) with a high listen_duration_min to allow for thinking pauses.

  8. How VoiceMode discovers and loads tools

    master

    VoiceMode uses an automatic discovery mechanism to find tools on the filesystem, applies filters, and dynamically imports them at startup. This allows for zero-configuration registration and selective loading to optimize token usage in LLM contexts (like Claude Code).

    Discovery Logic

    1. Regular Tools: Files located at voice_mode/tools/{tool_name}.py are loaded as {tool_name}.
    2. Service Tools: Files located at voice_mode/tools/services/{service}/{tool}.py are loaded using a flattened namespace: {service}_{tool} (e.g., whisper_install).

    Filtering and Exclusions

    To prevent accidental loading of internal logic, the following patterns are automatically excluded:

    • __init__.py
    • _*.py (private modules)
    • *_helpers.py (utility modules)
    • types.py (type definitions)

    Token Optimization

    Loading all tools can consume ~25,000 tokens. By using selective loading via environment variables, you can reduce this to ~5,000 tokens (e.g., loading only converse), saving 20,000 tokens in the context window.

  9. Add and manage Impression voices

    master

    Voices are managed as directories within your VOICEMODE_VOICES_DIR (defaults to ~/.voicemode/voices/).

    Directory Structure

    To register a voice, create a directory named after the voice and include a default.wav file (5-9 seconds of clean audio).

    ~/.voicemode/voices/
    └── <voice_name>/
        ├── default.wav        # Required: 5-9s clean reference audio
        ├── description.txt    # Optional: one-line human description
        └── persona.md         # Optional: structured character notes for LLM steering

    Using multiple samples

    You can store multiple WAV files in a voice directory to act as a sample bin. To activate a specific sample, create a symlink named default.wav pointing to your preferred file:

    ln -sfn samantha-2024-loud.wav ~/.voicemode/voices/samantha/default.wav

    Warning: A directory containing multiple WAVs but no default.wav symlink will be ignored by VoiceMode.

  10. VoiceMode Tools System

    master

    Tools are the primary interface for voice interactions within the MCP server. They are automatically imported from the tools/ directory and exposed via the MCP protocol.

    Key tools include:

    • converse: The main tool for voice conversations. It handles audio recording (via local microphone), playback, TTS/STT service selection, and implements silence detection and Voice Activity Detection (VAD).
    • Service tools: Used for installation and management, including whisper_install, kokoro_install, and operations for starting, stopping, or checking the status of services, as well as model and configuration management.
  11. How Soundfont lookup works

    master

    When a Claude Code event fires, VoiceMode searches for audio files (.mp3 or .wav) using a specific priority order, moving from most specific to least specific.

    Lookup Priority Table

    PriorityPathWhen
    1{event}/mcp/{server}/{tool}/[01-99|default].mp3MCP tool (e.g. voicemode converse)
    2{event}/mcp/{server}/default.mp3Any tool from that MCP server
    3{event}/mcp/default.mp3Any MCP tool
    4{event}/{tool}/subagent/{subagent}.mp3Specific subagent type
    5{event}/{tool}/[01-99|default].mp3Specific tool
    6{event}/default.mp3Any tool for that event
    7fallback.mp3Nothing else matched

    Numbered Variants

    To add variety to repeated operations, you can place numbered files (e.g., 01.mp3, 02.mp3, ..., 99.mp3) alongside a default.mp3 in any tool directory. The receiver will randomly select one of the numbered files.

  12. How Multi-Agent Voice coordination (Conch) works

    master

    When running multiple voice agents (e.g., in different tmux panes), VoiceMode uses a "conch" mechanism to serialize speech so only one agent talks at a time. This prevents audio overlap.

    Key Concepts

    • The Conch: A synchronization mechanism that manages the "floor" for speaking.
    • Queueing: If the conch is busy, agents can join a queue.
      • wait_for_conch: If set to true (or a duration), the agent joins the queue.
      • VOICEMODE_CONCH_MODE: Determines how queued agents are served. wait blocks until the turn is granted; callback returns immediately with a queue position.
    • Fairness: The floor is handed out in FIFO (First-In-First-Out) order via a grant hint.
    • Operator Overrides: Use the CLI to bypass FIFO: voicemode conch give <session> (jump the line) or voicemode conch bump (drop current holder).

    Remote Agents (MCP conch tool)

    Remote agents on a streamable-HTTP server use the MCP conch tool to interact with the queue.

    • Required: session_id must be provided for registration and heartbeats.
    • Liveness: Remote agents must send a heartbeat (approx. every 30s) to maintain their place. If the VOICEMODE_CONCH_REMOTE_TTL (default 90s) expires, the agent is pruned.
    • Tool Actions:
      • status: View holder and queue.
      • callback: Recommended for joining when busy (returns position immediately).
      • wait: Block until turn (capped by VOICEMODE_CONCH_MCP_WAIT_CAP).
      • heartbeat: Refresh liveness.
      • leave: Give up place.
      • give/bump/release: Operator overrides.
    # Auto-focus tmux pane when an agent starts speaking (default: false)
    VOICEMODE_AUTO_FOCUS_PANE=false
    
    # Override the default focus-hold duration if the sentinel file has no
    # explicit value (default: 30 seconds)
    VOICEMODE_FOCUS_HOLD_SECONDS=30
    
    # Conch coordination (serialises speech across agents)
    VOICEMODE_CONCH_ENABLED=true
    VOICEMODE_CONCH_TIMEOUT=60           # Seconds to wait for the conch
    VOICEMODE_CONCH_CHECK_INTERVAL=0.5   # Polling interval
    VOICEMODE_CONCH_LOCK_EXPIRY=300      # Stale-lock expiry (0 disables)
    VOICEMODE_CONCH_MODE=wait            # Default mode when a busy converse() queues:
                                         #   wait     = block until your turn
                                         #   callback = return now with your position
    VOICEMODE_CONCH_REMOTE_TTL=90        # Heartbeat TTL (s) for a REMOTE MCP waiter
    VOICEMODE_CONCH_MCP_WAIT_CAP=25      # Hard cap (s) on a blocking MCP conch wait