Wrapping Claude Code: a 10-minute tour
Overview
Ten minutes from zero to a coordinated Claude Code session: one master running locally, one shim on your $PATH, one command to start Claude Code under coordination. The commands below come straight from the repo quickstart.
Prerequisites
- A Rust toolchain to build the shim, and Node 20+ with pnpm to run the master.
- Postgres reachable locally. The master runs migrations at startup and will not bind its port without a database.
docker compose up -dprovides one. - An SSH key in
~/.ssh/(precedenceid_ed25519thenid_rsathenid_ecdsa). The shim authenticates with it, the same trust model asgit push.
Start the master
Copy the env template, set DEVELOPER_KEYS (a JSON map of developer name to SSH public key) and JWT_SECRET, then start it. Fastify listens on http://0.0.0.0:8080 by default.
cp packages/master/.env.example packages/master/.env
# set DEVELOPER_KEYS and JWT_SECRET in .env
pnpm install
pnpm --filter @tether/master devSet OPENROUTER_API_KEY to switch the master to its LLM concept matcher. Without it, the master falls back to a keyword matcher, which is enough to see coordination work.
Point the shim at your repo
cargo build -p tether-shim
./target/debug/tether init --developer "$USER"
./target/debug/tether statustether init reads your SSH key and writes ~/.tether/config.toml. The default master URL is http://localhost:8080; override it with --master-url. tether status should report master: reachable.
Wrap Claude Code
tether wrap claudeThe shim spawns claude --session-id <UUID>, then tails the session transcript for the plan sentinels. The normal Claude Code TUI appears and you type as usual. Coordination runs out-of-band; the session stays fully interactive throughout.
TETHER_WRAPPED=1 is set inside a wrapped session, so running tether wrap claude from within one is a no-op. Shim logs land in ~/.tether/shim.log.
What happens on the first plan
Claude writes its transcript only after its first persisted turn, so the shim waits for it to appear (up to a 10-minute deadline, set by TETHER_TRANSCRIPT_TIMEOUT_SECS). On the first plan, the shim extracts the {summary, steps} and submits it as an intent. The master matches concepts and returns continue. Only then does Claude execute.
Add a second agent and force a conflict
- 01Open a second terminal and run
tether wrap claudeagain. Each agent gets its own UUID under your developer identity. - 02Give both agents plans that touch the same concept, for example two takes on the auth session contract.
- 03When the second plan lands, the master detects the hard conflict and returns a verdict. A conflict notification arrives in the conversation.
- 04Open the dashboard Workspace view to watch the live intents, and the Conflicts view to resolve.
Next steps
For how the plan extraction works under the hood, read the sentinel pattern. To take this across a team, see cross-machine coordination.
Frequently asked questions
- Does wrapping change how I use Claude Code?
No. The shim runs Claude under a PTY so the normal TUI renders and you type as usual. Coordination happens out-of-band on a separate channel. Until two agents collide, the experience is identical to running Claude directly.
- Why does the master need Postgres?
The master runs database migrations at startup and will not bind its port without a reachable database.
docker compose up -dprovides one, or install Postgres natively and create thetetherrole and database.- What if I run tether wrap inside an already-wrapped session?
It is a no-op.
TETHER_WRAPPED=1is set inside a wrapped session and blocks recursive wrapping.