Skip to content

Repository files navigation

zumo

Mobile mission control for coding agents. Zumo runs on your workstation and gives your phone one inbox for Claude Code, Codex, OpenCode, and Pi without replacing their models, tools, authentication, or native CLI sessions.

Warning

Zumo is currently in BETA. Expect breaking changes and rough edges. Try it on real projects, report problems through GitHub Issues, and open PRs for improvements.

What works

  • Launch any installed supported agent in a scanned git repository.
  • Open local Claude sessions in Anthropic's official web or mobile UI through Remote Control.
  • Use the stable structured Codex view for streamed messages, commands, file changes, diffs, questions, and approval buttons.
  • Use the native PTY view for Claude Code, OpenCode, Pi, or raw Codex.
  • Answer Codex questions, allow or deny commands, stop work, and dismiss completed/failed work from one action inbox.
  • Hand work to another installed harness with the current branch/status/diff, or start a read-only Claude/Codex review.
  • Carry a local, append-only Work Graph of prompts, outcomes, and tool summaries across Codex and Claude sessions.
  • Browse transcript-backed Claude history and resume the exact native conversation.
  • Attach images, use mobile terminal keys, and receive web-push alerts.
  • Keep timestamped terminal recordings for seven days (1 GB cap) and uploaded images for 24 hours (256 MB cap).
  • Use the installable AWS app for encrypted Claude/Codex conversations, tools, diffs, messages, approvals, and status without a VPN app.
  • Optionally use the Direct/Tailscale app for raw PTY access to every harness.

Zumo deliberately does not build another agent loop or proxy model APIs. The harnesses continue to own execution; Zumo owns sessions, attention, handoffs, and intervention.

Claude launches enable Remote Control by default and appear at https://claude.ai/code under their Zumo session name. Disable the launch toggle when using API-key, Bedrock, Vertex, or Foundry authentication; those modes do not support Remote Control. The private PTY terminal remains available as a fallback.

Requirements

  • macOS or Linux with Node.js 22.18+, Bun, tmux 3.1+, curl, and at least one supported agent
  • One connectivity choice: AWS CLI credentials for the no-VPN app, or Tailscale for direct raw-terminal access
  • A modern mobile browser; iOS web push requires installing the PWA to the Home Screen

Windows is supported through WSL2. Native Windows is not supported because the session substrate is tmux.

Install

bun install
bun run setup

Setup creates ~/.zumo/config.json, detects agent binaries, installs fail-silent Claude/Codex lifecycle hooks when available, and starts a user service plus the recording-retention job. Existing ~/.port23 installations remain in place for backward compatibility. Codex asks you to review newly installed hooks once through /hooks before it trusts them.

Then choose one phone connection:

AWS app — recommended, no Tailscale

aws sts get-caller-identity
bun run deploy:aws
systemctl --user restart zumo.service   # Linux

Open the printed CloudFront URL on your phone and install it to the Home Screen. On the laptop, open http://127.0.0.1:7323, select Cloud pair, and enter its five-minute code in the phone app.

The AWS app provides the common Claude/Codex timeline, messages, tools, diffs, approvals, and session controls. Conversation payloads use an ephemeral P-256 key exchange and AES-GCM encryption, so the relay Lambda handles ciphertext rather than readable prompts or diffs.

Direct app — optional raw terminal

tailscale serve --bg 7323

Open the https://…ts.net URL on your phone and install it to the Home Screen. This route adds the native PTY terminal for Claude Code, Codex, OpenCode, and Pi; it requires the Tailscale app to be connected.

On Linux, keep the workstation service alive after logout with:

sudo loginctl enable-linger "$USER"

The daemon runs under Node because node-pty is unreliable under Bun on the tested host. Bun remains the package manager and test runner.

Work Graph and harness switching

Zumo stores shared project history under ~/.zumo/projects/<project-id>/work-graph.jsonl (or the retained ~/.port23 home on legacy installs) with mode-0600 files. It never creates a transcript directory inside the repository. Zumo-launched Codex sessions use the structured app-server event stream; desk-started Codex and Claude sessions use lifecycle hooks. Provider transcript files remain a display/import fallback, not the source of truth.

Use Hand off on a running session to launch another installed harness. The target receives a bounded context containing the previous task, latest result, recent tool outcomes, and the live Git branch/status/diff. A desk-started session in the same repository also receives recent context from a different harness at SessionStart, when that context is less than 24 hours old. Zumo marks this history as untrusted and tells the target to verify it against the working tree.

Inspect the local graph without opening private provider history files:

curl --get --data-urlencode "repo=$PWD" http://127.0.0.1:7323/api/work-graph

Services

  • Linux: zumo.service and zumo-retention.timer under systemd user services
  • macOS: com.zumo.daemon and com.zumo.retention under launchd

AWS app details

The AWS route works over ordinary mobile internet and keeps the raw terminal private:

aws sts get-caller-identity
bun run deploy:aws
systemctl --user restart zumo.service   # Linux

deploy:aws provisions API Gateway WebSocket, two arm64 Lambda functions, three encrypted on-demand DynamoDB tables, a private S3 bucket, CloudFront, 14-day logs, throttling, concurrency caps, and error alarms. It uploads the cloud PWA and writes the generated endpoint and device credential to the mode-0600 local config.

Open Cloud pair on the laptop, then enter the 80-bit one-time code in the CloudFront app. Codes expire after five minutes. Pairing a new browser replaces the previous durable browser credential in this single-workstation release.

The AWS relay can see only:

  • repository basename, harness, purpose, status, and timestamps;
  • actionable approval/question/failure text, capped at 500 characters;
  • allow, deny, answer, dismiss, refresh, and stop commands.

Session messages, paths, diffs, and transcript events cross AWS only as end-to-end encrypted, size-capped chunks. The relay observes ciphertext size and timing but receives no session key. Terminal bytes, harness credentials, and model keys never enter the relay. The raw terminal remains available only through the optional Direct/Tailscale app.

bun run smoke:relay performs a destructive pairing test and replaces the currently paired browser credential; use it only during relay development.

To deploy in another region:

bun run deploy:aws eu-west-1

Development

bun install
bun run dev
bun test
bun run check

The local app is at http://127.0.0.1:7323. Useful operational checks:

systemctl --user status zumo.service
journalctl --user -u zumo.service -n 100
curl -fsS http://127.0.0.1:7323/api/relay
aws cloudformation describe-stacks --stack-name zumo-relay --region us-east-1

Configuration lives at ~/.zumo/config.json:

{
  "port": 7323,
  "repoRoots": ["/home/you/my-work"],
  "activityWindowMs": 3000,
  "agentBins": {
    "claude": "/absolute/path/to/claude",
    "codex": "/absolute/path/to/codex",
    "opencode": "/absolute/path/to/opencode",
    "pi": "/absolute/path/to/pi"
  }
}

ZUMO_HOME, ZUMO_PORT, ZUMO_CLAUDE_BIN, ZUMO_CODEX_BIN, ZUMO_OPENCODE_BIN, and ZUMO_PI_BIN override their defaults.

Security model

The local daemon binds only to 127.0.0.1; Tailscale, when enabled, is its identity and HTTPS boundary. State-changing direct-browser requests and PTY WebSockets must be same-origin. AWS conversation traffic is encrypted end-to-end in the phone and workstation before relay. Prompts and arguments are passed directly to child processes, never through a shell. Pairing codes and durable cloud tokens are stored only as SHA-256 hashes in DynamoDB, and API Gateway access logging is intentionally disabled so query credentials are not recorded.

Do not bind the daemon publicly or put the full terminal behind an unauthenticated reverse proxy.

About

Mobile mission control for Claude Code, Codex, OpenCode, and Pi — one private action inbox, terminal, and cross-agent handoff.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages