voiceos-tmux-mcp
Provides tools to inspect and interact with tmux panes, enabling the management of Claude Code sessions that run within tmux.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@voiceos-tmux-mcpWhat are my Claude Code sessions doing right now?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
voiceos-tmux-mcp
A VoiceOS integration for steering hand-started Claude Code sessions by voice.
Claude Code sessions started in a terminal register themselves under
~/.claude/sessions/ and record the tmux pane they are running in. This server reads that
registry, matches each entry against the panes tmux reports as alive, and exposes the result
as nine MCP tools. That makes it possible to ask aloud what is running, what a session said,
what it is waiting on, and to answer it — without leaving whatever you were doing.
It runs as a remote-mcp integration whose URL is on this Mac: http://127.0.0.1:7392/mcp.
"Remote" is about the transport, not the location — VoiceOS makes an HTTP call to a server
you start here, rather than spawning it. That is forced by the app: installation goes by URL,
not by folder. The listener is bound to 127.0.0.1, so only processes on this Mac can reach
it. Nothing is sent anywhere, and only local tmux sockets are ever addressed.
The server must be running or the integration is dead — see Start the server below.
Tools
Tool | What it does |
| Reports whether the integration can see tmux at all — the "is this alive" check when something breaks after an OS or app update. |
| Lists the running Claude Code sessions with the folder each is working in. |
| Reports whether a session is working, idle, or waiting, and what it is waiting on. |
| Reads back a session's recent turns from its transcript, for summarizing aloud. |
| Types an instruction into a session and submits it, then confirms the session actually moved. |
| Reads the approval prompt a waiting session is showing, with its numbered options and a fingerprint. |
| Answers that prompt by option number, refusing if the prompt changed since it was read out. |
| Starts a new session in a given folder, optionally with a first instruction. |
| Stops what a session is doing, without closing it. |
Related MCP server: claude-mux.mcp
Safety model
Every write target resolves through the session registry. No tool takes a pane, socket,
or window argument. A tool is given a session name, which is matched against
~/.claude/sessions/ entries that declare a tmux pane, have that pane alive right now,
and whose recorded pid is in the foreground process group of that pane's terminal. Panes
with no Claude Code registry entry — a bare shell, an editor, a tail -f — are not in the
set the lookup searches, so they are unreachable by construction rather than by a filter that
could be bypassed. This matters because text sent to a bare shell is executed.
The foreground-process-group condition is the kernel's own answer to "who receives a keystroke typed into this pane", and it is what closes three holes that a liveness check alone leaves open:
Two entries claiming one pane. A Claude Code started from inside another inherits
$TMUXand registers the same pane under its own pid. Under liveness alone both were steerable, and sending to the nested one typed into the other session's input box. The nested process does not own the pane's terminal, so it no longer resolves.A tmux server restart. Pane ids are monotonic within one server and never recycled, but a restart resets the counter to
%0and reallocates the whole id space — and the pty device numbers come back identical too. A registry entry written before a reboot therefore names a live, unrelated pane on the same/dev/ttysNNN. Its pid is dead, so it is refused.A session that has handed over its terminal to a pager, an editor or a shell. Text typed there lands in the pager, not the agent. Such a session is reported as running but not accepting input, and is never a write target.
It fails closed everywhere: an unreadable tty, a failed ps, or a pid that cannot be
determined all mean the session does not resolve. A session that silently disappears is an
annoyance; a wrong target is a stray keystroke into somebody's terminal. One race remains and
is not closable from here: the foreground group can change between the check and the
keystroke. The window is milliseconds, not eliminated.
Three further guards:
Empty-input check.
send_to_claude_sessionrefuses to type when the session already has text in its input box, rather than merging into a half-written line.Prompt fingerprint.
read_claude_prompthashes the entire prompt block.answer_claude_promptre-reads the screen at the moment of answering and refuses if the hash differs — so an approval spoken for one command cannot land on a different one that appeared meanwhile.Explicit sockets. Every tmux invocation passes
-S <socket>. The server never relies on the ambient default socket.
There is deliberately no general "run a terminal command" tool: ls and rm -rf ~ would be
the same call differing only by a model-written string.
Start the server
./start.sh # leave it running; Ctrl-C stops itIt listens on http://127.0.0.1:7392/mcp. Port 7392 is fixed in server-http.mjs;
7391 belongs to the environment probe on this Mac. Confirm it is up and loopback-only:
curl http://127.0.0.1:7392/health # {"ok":true,...}
lsof -nP -iTCP:7392 -sTCP:LISTEN # must say 127.0.0.1:7392, never *:7392start.sh resolves node absolutely (/opt/homebrew/bin/node, then /usr/local/bin/node,
then PATH) and installs dependencies on first run if node_modules/ is absent, so a
stripped environment fails loudly instead of silently. It execs node, so Ctrl-C reaches
the server rather than a shell wrapper.
Starting it at login instead
com.seanchiu.voiceos-tmux-mcp.plist.sample is a launchd login agent that brings the server
up at login and restarts it if it dies. It is a sample — not installed and not loaded.
Install commands are in the comments at the top of the file. Two details there are
load-bearing: the job runs through zsh -lc because launchd hands a job a minimal PATH
(/usr/bin:/bin:/usr/sbin:/sbin), not the login shell's; and it execs node so KeepAlive
watches the server instead of a zsh parent.
Install into VoiceOS
With the server running, install by URL and give VoiceOS:
http://127.0.0.1:7392/mcpThe install-by-URL option lives under Settings → Agent Mode → Integrations. (The exact menu
wording is not recorded here — the env-probe integration was installed this way at
http://127.0.0.1:7391/mcp on this Mac and answered, but the label was never written down.)
VoiceOS handshakes with the endpoint and discovers the nine tools from the server itself.
voiceos.integration.json declares the same URL under runtime, and its tool list is what
verify.mjs checks the server against.
The stdio path is still here
server.mjs + run.sh still work and still speak stdio, for a local-mcp runtime:
"runtime": { "kind": "local-mcp", "command": "/bin/zsh", "args": ["run.sh"] }Both entrypoints call buildServer() from lib/tools.mjs, so the nine tools are defined
once and the two transports cannot drift apart.
Verify
node verify.mjsPrints the live sessions the state layer can see, then checks that the tools declared in
voiceos.integration.json and those registered in lib/tools.mjs are the same set — which
covers both entrypoints, since both build from that one file. Exit code 1 means drift — the
failure that installs cleanly and then exposes nothing. Run it before installing, and after
any change to the tool list.
verify.mjs is read-only: it issues only list-sessions / list-panes and reads two files.
It never sends keys, launches, or interrupts, so it is safe against live sessions.
Tests
npm testThe glob must stay quoted — node --test test/ (a bare directory) fails on Node 26.
Tests that need a real tmux server create their own on a scratch socket under /tmp and kill
only that one; they never touch the user's socket.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceEnables comprehensive tmux session management through MCP, allowing users to list sessions, send commands, set up automated messaging timers, and control tmux processes directly from Claude Desktop. Provides both real-time session monitoring and automated workflow features like exit/continue cycles.2MIT
- Flicense-qualityCmaintenanceGives Claude Code terminal control and multi-agent coordination through tmux sessions.4
- Alicense-qualityDmaintenanceMCP server for orchestrating multiple Claude Code instances via tmux, enabling spawning, reading, sending, listing, and killing sessions.302MIT
- Alicense-qualityBmaintenanceEnables Claude Code sessions to query fleet status, focus terminals, and manage sessions programmatically via MCP tools.1MIT
Related MCP Connectors
Augments MCP Server - A comprehensive framework documentation provider for Claude Code
Real-time chat hub for AI agents — Claude Code, Cursor, Cline, Codex over MCP or REST.
User-owned memory for AI agents, Copilot, Claude, IDEs, CLIs, and chat apps over remote MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/seanchiuai/voiceos-tmux-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server