克劳德语音多路复用器
Claude Code MCP插件和中继服务器,用于与多个Claude Code会话进行远程语音交互。从任何地方与正在运行的Claude会话交谈——在它们之间切换,查看它们的输出,并通过手机或任何浏览器的语音控制它们。
v3.0:技术支持 vmuxd,一个持久的守护进程,管理所有服务,并根据web应用程序的需求生成Claude会话。现在有了会话间消息传递、交互式终端和改进的按键可靠性。
建筑
Phone / Browser Mac (all local)
┌──────────────────────┐ ┌──────────────────────────────────────────┐
│ │ │ │
│ React Web App │◄─LiveKit─► Relay Server (:3100) │
│ (mic/speaker/UI) │ WebRTC │ ├── LiveKit Agent (embedded) │
│ │ │ │ ├── VAD + audio buffering │
│ Features: │ │ │ ├── Whisper STT │
│ - Voice I/O │ │ │ └── Kokoro TTS │
│ - Session list │ │ ├── WebSocket hub │
│ - New session spawn │ │ ├── Session registry │
│ - Session controls │ │ └── LiveKit token server │
│ - Text transcript │ │ │
│ - Agent status │ │ vmuxd daemon (launchd) │
│ │ │ ├── Service manager │
└──────────────────────┘ │ │ ├── vmux-whisper (auto-restart) │
│ │ ├── vmux-kokoro (auto-restart) │
│ │ ├── vmux-livekit (auto-restart) │
│ │ └── vmux-relay (auto-restart) │
│ ├── Session manager │
│ │ ├── vmux-session- (tmux) │
│ │ └── ... │
│ └── Unix socket IPC (/tmp/vmuxd.sock) │
└──────────────────────────────────────────┘
For remote access: expose relay server via tunnel (Cloudflare/ngrok/Tailscale)运作原理
守护进程(vmuxd)
vmuxd 是一个持久的macOS launchd代理,拥有所有服务的整个生命周期:
- 服务经理:启动Whisper、Kokoro、LiveKit和中继服务器。通过健康检查和指数回退在崩溃时自动重启来监控每个。
- 会话管理器:在命名的tmux窗口中生成Claude Code会话。每个会话运行
claude --permission-mode auto并立即向中继服务器注册。 - Unix套接字IPC:暴露
/tmp/vmuxd.sock(模式0600)vmuxCLI和中继服务器发送命令。 - 自动更新:每60秒轮询一次插件缓存。如果找到新版本,则复制守护程序文件并通过launchd重新启动。
会话注册(MCP插件)
每个Claude Code会话都安装了MCP插件。当用户调用待机技能(或守护进程生成一个)时,插件:
- 通过WebSocket连接到中继服务器并注册(会话名称、工作目录、元数据)
- 发送周期性心跳以保持会话注册表中的存在
- 监听传入的语音信息(来自中继的转录文本)
- 当语音信息到达时:将文本传递给Claude,Claude对其进行处理,并将对话响应发送回中继
- 中继器将响应与Kokoro进行合成,并将音频流式传输回客户端
会话产卵流
Web app "New Session" → POST /api/sessions/spawn {"cwd": "/path/to/project"}
→ relay server → vmux IPC (Unix socket)
→ vmuxd session manager
→ tmux new-session -s "vmux-project-a3f2" -c /path/to/project
→ send-keys: claude --permission-mode auto
→ poll relay /api/sessions until session appears (up to 60s)
→ session visible in web UI → auto-connect音频流
Phone mic → LiveKit (WebRTC) → Relay Server (LiveKit Agent)
→ VAD detects end-of-speech
→ Whisper (local STT) → transcribed text
→ WebSocket → MCP plugin in Claude session
→ Claude processes, generates response text
→ WebSocket → Relay Server
→ Kokoro (local TTS) → PCM audio
→ LiveKit (WebRTC) → Phone speaker代理状态框架
代理将其状态作为结构化状态对象进行跟踪:
{state: "thinking", activity: "Transcribing speech..."}
{state: "speaking", activity: null}
{state: "idle", activity: null}
{state: "error", activity: "Speech-to-text failed. Is Whisper running?"}会话运行状况
守护进程每30秒监视一次生成的会话:
| 状态 | 含义 |
|---|---|
standby | Claude处于待机模式,准备进行语音输入 |
active | Claude正在处理请求 |
zombie | tmux会话活动,但中继心跳停止>90秒 |
dead | tmux会话已退出 |
无论运行状况如何,每个会话都始终可见“终止”和“重新启动”按钮。
组件
1. vmuxd 守护进程(daemon/)
| 文件 | 描述 |
|---|---|
vmuxd.py | 主守护进程(asyncio、launchd入口点) |
service_manager.py | 基础设施服务生命周期+自动重启 |
session_manager.py | tmux会话生成、跟踪、健康监控 |
ipc_server.py | Unix套接字IPC服务器(换行符分隔的JSON) |
vmux | CLI包装器--通过套接字向守护进程发送命令 |
VERSION | 已安装版本(用于自动更新比较) |
2. vmux 命令行界面
vmux status # show daemon + service + session status
vmux spawn /path/to/project # spawn new Claude session
vmux kill # kill a session
vmux attach # attach to tmux terminal (for debugging)
vmux sessions # list active sessions
vmux restart # kill + respawn a session
vmux restart kokoro # restart an infrastructure service
vmux interrupt # send Ctrl-C to a session
vmux hard-interrupt # Ctrl-C + MCP reconnect + re-enter standby
vmux send # send a text message to a session's voice queue
vmux send-keys # send literal keystrokes to a session's tmux pane
vmux send-key # send a special key (Enter, C-c, Tab, etc.)
vmux auth-code # generate a one-time pairing code
vmux update-if-newer # apply update from plugin cache
vmux shutdown # stop daemon and all services3.MCP工具(relay-server/mcp_tools.py)
FastMCP工具嵌入在中继服务器中,通过SSE提供服务 /mcp/sse.
| 工具 | 说明 |
|---|---|
relay_standby | 注册并进入待机模式。阻止,直到语音消息到达。 |
relay_respond | 将Claude的响应文本发送回中继器进行TTS合成。 |
relay_activity | 用Claude的当前活动更新web客户端。 |
relay_disconnect | 从继电器中注销并退出待机模式。 |
relay_status | 显示当前继电器连接状态。 |
relay_notify | 通过通知唤醒父会话(用于后台代理)。 |
relay_code_block | 将代码片段或差异推送到成绩单上。 |
relay_file | 将文件直接转发到web应用程序(无令牌成本)。 |
relay_image | 将图像直接转发到web应用程序。 |
generate_auth_code | 生成一个6位配对码,用于授权新设备。 |
4.中继服务器(relay-server/)
连接web客户端、Claude会话和本地AI服务的Python服务器(FastAPI+Uvicorn)。
终点:
| 端点 | 类型 | 描述 |
|---|---|---|
POST /api/sessions/spawn | HTTP | 通过守护进程生成Claude会话(需要身份验证) |
DELETE /api/sessions/ | HTTP | 通过守护进程终止会话(需要身份验证) |
POST /api/sessions//interrupt | HTTP | 通过守护进程进行硬中断(需要身份验证) |
POST /api/sessions//restart | HTTP | 通过守护进程杀死+重生(需要身份验证) |
POST /api/sessions//message | HTTP | 向会话的语音队列发送文本消息 |
WebSocket terminal_input 消息 (v3.0):客户端WebSocket现在接受 terminal_input 消息与 {keys, special_key} 字段,通过守护进程转发到会话的tmux窗格。
5.React Web应用程序(web/)
- “+”按钮 在会话列表标题中--打开一个对话框,按目录生成新的Claude会话
- 健康徽章 在会话卡上——琥珀色“僵尸”,红色“死亡”
- 终止/重启/硬中断 会话上下文菜单中的菜单项(用于守护进程管理的会话)
- 交互式终端叠加 (v3.0)——点击成绩单中的终端图标,打开双向终端视图。包括命令输入栏、快捷键(^C、Esc、Tab、,↑, ↓),以及自动刷新终端快照。通过WebSocket直接向Claude Code TUI发送按键→ 守护进程→ tmux.
- 授权:承载头 --auth令牌存储在localStorage中,并作为
Authorization: Bearer在所有REST请求上
6.技能(skills/)
| 技能 | 描述 |
|---|---|
install | 运行完整的安装程序(构建deps,设置launchd守护进程) |
standby | 进入待机模式(检查继电器是否启动,不需要自动启动) |
start-services | 如果未运行,则通过launchctl启动守护程序 |
stop-services | 通过以下方式停止所有服务 vmux shutdown |
service-status | 通过以下方式检查状态 vmux status |
auth-code | 通过以下方式生成设备配对代码 vmux auth-code |
7.基础设施
服务由以下人员启动和监督 vmuxd:
| 服务 | 端口 | 描述 |
|---|---|---|
| Whisper服务器 | :8100 | 本地STT(whisper.cpp,使用Metal GPU从源代码编译) |
| Kokoro服务器 | :8101 | 本地TTS(kokoro fastapi,带MPS加速的PyTorch) |
| LiveKit服务器 | :7880 | 用于音频传输的WebRTC媒体服务器 |
| 中继服务器 | :3100 | 核心集线器(FastAPI+WebSocket) |
| MCP工具 | /mcp | 嵌入中继服务器,通过SSE提供服务 /mcp/sse |
配置
所有设置均通过配置 ~/.claude/voice-multiplexer/voice-multiplexer.env,由安装脚本生成。
关键设置:
| 变量 | 默认值 | 描述 |
|---|---|---|
RELAY_HOST | 0.0.0.0 | 中继服务器绑定地址 |
RELAY_PORT | 3100 | 中继服务器端口 |
WHISPER_URL | http://127.0.0.1:8100/v1 | Whisper STT端点 |
KOKORO_URL | http://127.0.0.1:8101/v1 | Kokoro TTS端点 |
KOKORO_VOICE | af_heart | TTS语音 |
LIVEKIT_URL | ws://localhost:7880 | LiveKit服务器URL |
LIVEKIT_API_KEY | LiveKit API密钥 | |
LIVEKIT_API_SECRET | LiveKit API机密 | |
SESSION_TIMEOUT | 600 | 会话心跳超时(秒) |
AUTH_SECRET | (自动生成) | JWT签名密钥 |
AUTH_TOKEN_TTL_DAYS | 90 | 设备授权令牌持续多长时间 |
VMUX_DAEMON_SECRET | (自动生成) | 守护进程的内部机密→中继通信 |
安装
先决条件
- macOS与Homebrew
- Xcode命令行工具(
xcode-select --install) - Python 3.10+
uv(curl -LsSf https://astral.sh/uv/install.sh | sh) - Node.js 20+与npm
通过技能安装(推荐)
在Claude Code中安装插件后,只需在任何Claude会话中运行安装技能:
/voice-multiplexer:installClaude将与您确认,然后运行安装程序并在完成后报告配对代码。
安装脚本(手动)
# Install with defaults (base Whisper model, ~142 MB)
./scripts/install.sh
# Install with a larger, more accurate Whisper model
./scripts/install.sh --whisper-model small
# Force reinstall
./scripts/install.sh --force这个:
- 安装必备组件(cmake、livekit、tmux,如果缺少)
- 使用Metal GPU加速从源代码编译whisper.cpp
- 在PyTorch MPS支持下建立Kokoro TTS
- 构建web应用程序
- 将守护程序文件复制到
~/.claude/voice-multiplexer/daemon/ - 安装
vmuxCLI到~/.local/bin/vmux - 写入并加载launchd plist(
com.vmux.daemon) - 打印一次性配对代码,以便立即进行首次设置
数据目录
~/.claude/voice-multiplexer/
├── daemon/
│ ├── vmuxd.py # Installed daemon (updated by auto-update)
│ ├── service_manager.py
│ ├── session_manager.py
│ ├── ipc_server.py
│ ├── vmux # CLI wrapper
│ └── VERSION # Installed version
├── whisper/
│ ├── whisper.cpp/ # Compiled binary + source
│ └── models/
│ └── ggml-{model}.bin
├── kokoro/
│ └── kokoro-fastapi/ # Python venv + TTS model
├── logs/
│ ├── daemon.log # vmuxd daemon logs
│ ├── daemon-error.log # vmuxd stderr
│ ├── whisper.log
│ └── kokoro.log
├── daemon.secret # Internal daemon↔relay shared secret (0600)
├── daemon.state # Live PID/session state (updated every 10s)
├── devices.json # Authorized devices
└── voice-multiplexer.env # Service config已启动集成
守护进程作为macOS launchd代理运行:
- 属性列表:
~/Library/LaunchAgents/com.vmux.daemon.plist - 自动启动:从登录时开始(
RunAtLoad: true) - 自动重启:launchd在崩溃时重新启动(
KeepAlive: true) - 节流:重新启动之间至少10秒
# Control daemon lifecycle
launchctl start com.vmux.daemon # start now
launchctl stop com.vmux.daemon # stop (launchd restarts automatically)
launchctl unload ~/Library/LaunchAgents/com.vmux.daemon.plist # disable auto-start
launchctl load ~/Library/LaunchAgents/com.vmux.daemon.plist # re-enable auto-start卸载
# Remove everything
./scripts/uninstall.sh
# Keep downloaded models (faster reinstall)
./scripts/uninstall.sh --keep-models卸载之前,请停止守护进程:
launchctl unload ~/Library/LaunchAgents/com.vmux.daemon.plist入门指南
加载插件
来自n33kos市场:
/plugin install n33kos/voice-multiplexer从本地目录(开发):
alias claude='command claude --plugin-dir /path/to/claude-voice-multiplexer'首次设置
./scripts/install.sh安装脚本设置所有内容,启动守护进程,并打印一次性配对代码。打开 http://localhost:3100 并输入代码以授权您的设备。就这样
日常使用
后台进程在以下情况下自动运行 install.sh。您不需要手动启动或停止服务。
要在任何Claude会话中进入语音待机:
/voice-multiplexer:standby要从web应用程序生成新的Claude会话,请执行以下操作:
- 打开
http://localhost:3100 - 点击
+会话列表中的按钮 - 输入工作目录路径
- 会话自动生成并连接
要连接到会话的终端(用于调试):
vmux sessions # list active sessions
vmux attach # open tmux terminal远程访问(隧道)
要从本地网络外部访问语音多路复用器:
ngrok http 3100LiveKit流量通过位于以下位置的中继服务器进行代理 /livekit/*,因此只需要对一个端口进行隧道传输。令牌端点根据请求主机自动返回正确的WebSocket URL。
安全:
- JWT设备身份验证保护所有端点
- 配对代码只能从本地主机或通过以下方式生成
vmux auth-code - 配对尝试有速率限制(每个IP 5/60s)
- 守护进程↔中继通道使用单独的共享密钥(
X-Daemon-Secret)
Daemon架构详细信息
IPC协议
Unix套接字位于 /tmp/vmuxd.sock (模式0600)接受换行符分隔的JSON:
{"cmd": "spawn", "cwd": "/path/to/project"}
→ {"ok": true, "session_id": "abc123", "tmux_session": "vmux-project-a3f2", "daemon_id": "d4f1a2b3"}
{"cmd": "kill", "session_id": "abc123"}
→ {"ok": true}
{"cmd": "restart-session", "session_id": "abc123"}
→ {"ok": true, "session_id": "def456", "tmux_session": "vmux-project-e5c7"}
{"cmd": "hard-interrupt", "session_id": "abc123"}
→ {"ok": true}
{"cmd": "restart", "service": "kokoro"}
→ {"ok": true}
{"cmd": "status"}
→ {"ok": true, "daemon_pid": 1234, "services": {...}, "sessions": [...]}
{"cmd": "send-keys", "session_id": "abc123", "keys": "hello world"}
→ {"ok": true}
{"cmd": "send-keys", "session_id": "abc123", "special_key": "Enter"}
→ {"ok": true}
{"cmd": "send-message", "session_id": "abc123", "text": "Please summarize..."}
→ {"ok": true}
{"cmd": "shutdown"}
→ {"ok": true}服务重启策略
每个服务在出现故障时都会以指数级回退重新启动:
- 尝试1:2s延迟
- 尝试2:延迟4秒
- 尝试3:8秒延迟
- ...
- 最大延迟:60秒
- 最大尝试次数:5次(然后放弃——日志显示“已达到最大重启次数”)
继电器重启恢复
当中继服务器重新启动(崩溃或自动更新)时,现有的备用会话需要重新连接其MCP传输。守护进程通过轮询检测到这一点 /api/sessions --处于待机状态但不再出现的会话会触发硬中断流:
- 将Ctrl-C发送到tmux窗格
- 等待1秒,运行
/mcp reconnect plugin:voice-multiplexer:voice-multiplexer - 等待2秒,运行
/voice-multiplexer:standby
正在进行活动工作的会话在web应用程序中显示“中继重新启动”警告。
自动更新流程
守护进程每60秒检查一次插件缓存:
~/.claude/plugins/cache/n33kos/voice-multiplexer//plugin.json如果 version > installed VERSION:
- 副本
daemon/从缓存到~/.claude/voice-multiplexer/daemon/ - 将新版本写入
VERSION - 设置关机事件→ launchd通过KeepAlive重新启动
项目结构
claude-voice-multiplexer/
├── .claude-plugin/
│ └── plugin.json # Plugin manifest (v3.0.0)
├── .mcp.json # Bundled MCP server definition
├── README.md
├── daemon/
│ ├── vmuxd.py # Main daemon process
│ ├── service_manager.py # Service lifecycle + auto-restart
│ ├── session_manager.py # tmux session spawning + tracking
│ ├── ipc_server.py # Unix socket IPC server
│ ├── vmux # CLI wrapper (Python, executable)
│ └── VERSION # Installed daemon version
├── skills/
│ ├── install/SKILL.md
│ ├── standby/SKILL.md
│ ├── start-services/SKILL.md
│ ├── stop-services/SKILL.md
│ ├── service-status/SKILL.md
│ └── auth-code/SKILL.md
├── relay-server/
│ ├── server.py # FastAPI server + session control endpoints
│ ├── mcp_tools.py # FastMCP tools over SSE
│ ├── livekit_agent.py # LiveKit agent (VAD, STT, TTS)
│ ├── audio.py # Whisper/Kokoro clients
│ ├── registry.py # Session registry
│ ├── auth.py # JWT auth + device management
│ ├── config.py # Configuration (env vars)
│ └── requirements.txt
├── web/
│ └── src/
│ ├── hooks/
│ │ ├── useRelay.ts # WebSocket + session control
│ │ ├── useAuth.ts # Auth with Bearer header
│ │ └── ...
│ └── components/
│ ├── SessionList/ # Session drawer + New Session button
│ ├── TerminalOverlay/ # Interactive terminal with keystroke input
│ └── ...
└── scripts/
├── install.sh # Full install + daemon setup + launchd
├── start.sh # Compatibility wrapper (delegates to vmux)
├── stop.sh # Compatibility wrapper (delegates to vmux)
├── status.sh # Compatibility wrapper (delegates to vmux)
└── uninstall.sh会话间消息传递(v3.0)
这 vmux send 命令启用会话之间的程序化消息传递,解锁一个编排器模式,其中一个AI协调多个Claude会话。
# Send by session ID
vmux send abc123 "Please summarize the recent changes"
# Send by directory path (auto-computes session ID from path hash)
vmux send ~/projects/my-app "Run the test suite and report back"
# Pipe from stdin
echo "Deploy to staging" | vmux send abc123 -消息被传递到目标会话的语音队列,与web UI文本输入和语音转录的路径相同。接待克劳德的会议在下一次会议上接他们 relay_standby 电话。
流量: vmux send → 守护进程IPC→ POST /api/sessions/{id}/message → 接力→ session.voice_queue → relay_standby 将消息返回给克劳德。
从v1迁移
如果你从v1.x升级:
- 在Claude Code中更新插件
- 守护进程的60秒轮询检测插件缓存中的新版本,并自动进行自我更新
- 守护进程重启后,服务将由launchd管理,无需手动
start.sh
现有的start.sh/stop.sh调用仍然有效(它们委托给 vmux 或回退到传统模式)。
