Watch the yard from your pocket.
CC Dispatch attaches to the Claude Code, Codex and Grok sessions already running in iTerm2. See who's working, answer the one that's asking, get pinged when one finishes. Nothing restarts.
rm -rf dist/
the problem
You left the desk. The fleet didn't.
A prompt is a full stop.
One agent wants to run a command. Until you say yes, that whole session sits idle. The other five carry on without you knowing which one stalled.
Status is invisible from the sofa.
Working, stuck, or done? From across the room a terminal is just a rectangle. You end up walking back to check.
Reconnecting loses context.
Most remote tools spin up a fresh session. CC Dispatch attaches to the one that's already running, with its history and its trust.
what it does
Everything the yard needs.
Nothing it doesn't.
Attach, never restart
Reads the panes that already exist through the iTerm2 Python API. Kill the server and the fleet is exactly as it was.
Answer prompts from anywhere
See exactly what an agent wants to do. Allow, deny, or pick an option. Numbered menus and checkbox lists both work.
A push when it needs you
Web-push the moment a session finishes or stalls on input. No app open, no polling on your side.
Send the next thing
Type a follow-up, dictate it, or drop a file into the pane. Switch a Claude session's permission mode, effort, or model.
Passkey only
The QR at startup carries a single-use bootstrap token. It registers your first passkey and then it's spent. Nothing else gets in.
Loopback behind Tailscale
The server binds 127.0.0.1. tailscale serve terminates TLS and proxies it to your Tailnet. No listener for a stranger to find.
Secrets on request
An agent runs dispatch-auth request github. Your phone buzzes. You approve. The key is released from an encrypted vault, just in time, and never lands on disk in plaintext.
Claude, Codex, and Grok
Each pane gets its own critter, coloured by what's running in it. Claude-only controls hide themselves on the others.
install
Six commands.
Then scan.
The server runs on the Mac that owns the panes. Your phone reaches it over your Tailnet. Everything below is copy-paste.
Clone and install into a venv.
git clone https://github.com/charlie-818/claude-dispatch.git cd claude-dispatch && make venv
Turn on iTerm2's Python API. Settings → General → Magic → Enable Python API.
Install the fleet-status hooks so every pane shows up.
make hooks # then merge examples/settings.snippet.json into ~/.claude/settings.jsonPublish the port over your Tailnet with TLS.
tailscale serve --bg 8788
Start the server from inside an iTerm2 window, so it inherits ITERM2_COOKIE.
make run
Scan the QR it prints, register a passkey, add the app to your home screen.
After that it's passkeys only. The token in the QR is already spent.
the fence
Four things that are true
by construction.
Loopback only. Tailscale is the only way in, and it terminates TLS before the server ever sees a packet.
Passkeys require a real HTTPS origin, so nobody registers one over a bare IP. The bootstrap token dies after one use.
A pane only receives keystrokes if its foreground job is a known agent. Scratch shells are unreachable, on purpose.
Integration keys sit in a Fernet-encrypted vault. The key lives in the macOS login keychain, not in the repo, not on disk.
What it does not protect against, and every control with the line of code that enforces it: the threat model.
contribute
Small codebase.
Real fleet needed.
One aiohttp server, one PWA, a pytest suite that runs offline. The parsers and gates are unit-tested; the iTerm2 side you check by hand against your own panes.
- Read the sourceApache-2.0
- Contributing guidesetup, style, what to work on
- Open issuesbug forms and feature requests
- Architecture and API docsevery route, every env var
- Report a vulnerabilityprivately, please