Field notes

Wrapping Claude Code: a 10-minute tour

By Tetherlab team
Updated 2026-05-29

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 -d provides one.
  • An SSH key in ~/.ssh/ (precedence id_ed25519 then id_rsa then id_ecdsa). The shim authenticates with it, the same trust model as git 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.

bash
cp packages/master/.env.example packages/master/.env
# set DEVELOPER_KEYS and JWT_SECRET in .env
pnpm install
pnpm --filter @tether/master dev

Set 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

bash
cargo build -p tether-shim
./target/debug/tether init --developer "$USER"
./target/debug/tether status

tether 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

bash
tether wrap claude

The 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.

Recursive wrapping is blocked

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

  1. 01Open a second terminal and run tether wrap claude again. Each agent gets its own UUID under your developer identity.
  2. 02Give both agents plans that touch the same concept, for example two takes on the auth session contract.
  3. 03When the second plan lands, the master detects the hard conflict and returns a verdict. A conflict notification arrives in the conversation.
  4. 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 -d provides one, or install Postgres natively and create the tether role and database.

What if I run tether wrap inside an already-wrapped session?

It is a no-op. TETHER_WRAPPED=1 is set inside a wrapped session and blocks recursive wrapping.

/ ready to start

Wrap one agent.
See the difference.