Run Claude Code, Codex, and Grok on the same repo without them overwriting each other. One agent
holds the stick at a time, handoffs carry structured context so the next agent doesn't re-derive it,
and tt chat gives you one console to talk to all of them.
No daemon, no server. Multi-process-safe via SQLite WAL, liveness-aware, and it works with Claude
Code, Codex CLI, Antigravity (agy), Grok Build, and OpenCode out of the box.
Node ≥ 22 required.
npm i -g talking-stick
tt install --alltt install adds the coordination skill to every harness it finds and skips the ones you don't have.
Restart any harness that was already running so it picks the skill up.
Split your terminal like the screenshot above: the agents stacked on the left, the console on the
right. Each pane cds into the same repo — that shared directory is what puts them in one room.
| Left column, one pane per agent | Right column |
|---|---|
cd ~/myrepo && claudecd ~/myrepo && codexcd ~/myrepo && grok |
cd ~/myrepo && tt chat |
Two agents is enough to start; add more panes on the left as you want them.
Give every agent pane the same one-line prompt:
Use the /talking-stick $talking-stick skill.
That's the whole prompt — no task yet. Each agent joins the room and goes idle waiting for you. You'll see each one appear in the console as it joins, so they don't announce themselves on top of that.
Prefer a plain prompt over harness goal modes such as /goal: their automatic continuation keeps
restarting an agent, which works against tt standby.
Start in tt chat with the introduction shown in the screenshot:
Hey guys. Introduce yourselves.
Once the agents have joined, give them the task in that same console:
Work together to implement OAuth login.
It reaches every agent in the room, and they coordinate from there. You don't script the turn-taking: the skill teaches each agent to join, wait, hand off, test, and review.
Driving from the console, rather than typing into each harness, is what keeps the agents in sync — each joined agent receives the same room message through its supported delivery path. Agents report their own work rather than forwarding your message to one another. You'll see who holds the stick in the footer and a delivery mark next to each agent you message.
| You type | What happens |
|---|---|
ship it when tests pass |
Goes to the whole room |
@codex rebase onto master |
Goes to Codex; @everyone addresses every agent that has joined the room |
!@claude stop, wrong file |
Steers Claude mid-task, at its next tool step |
/who, /help |
Members and stick holder; all commands |
Each message header marks every recipient: … not delivered yet, ✓ delivered, ! failed. That's a
delivery receipt, not proof the model acted on it.
- Join. Each agent runs
tt joinandtt instructions show. - Listen. With no task yet, each agent enters standby — or keeps one
tt wait --park --jsonrunning when it can't self-wake. During assigned work it keeps onett wait --jsonrunning instead, which returns on anything worth acting on: a turn, a message, a join or leave, a handoff. - Take a turn. When
tt waitreturnsyour_turnwith a liveguardian_pid, that agent may edit, build, and test. A background guardian keeps its lease alive. Everyone else stays read-only and can still investigate, message, and leave notes. - Hand off. The holder tests, then runs
tt release(to the next fair waiter) ortt assign <agent>(to a specific reviewer). The handoff carriesstatus,next_action, andartifacts. - Talk without passing the stick.
tt msg sendcarries questions, review notes, and vetoes between turns. - Go idle. An agent with nothing to do runs
tt standbyand ends its model turn. A directed message, assignment, or pending handoff wakes it again. - Finish. Every participant reviews the result and explicitly agrees. With a console open, agents stay in standby instead of leaving, so you can bring them back with a message.
A directed message, or a room message you send from the console, wakes an idle Claude Code or Codex session natively — no keystrokes typed, no model polling while idle.
| Harness | How it wakes |
|---|---|
| Claude Code | Its inbox socket. A message you send as the operator arrives at the next tool boundary without cancelling the current tool |
| Codex | codex queue, delivered after the current turn ends |
| Grok Build | Active-turn hooks while a session is running; an idle session needs a live tt wait or cmux |
| Antigravity, OpenCode, Gemini | cmux only |
Claude Code and Codex wakes, and Grok's active-turn hooks, carry the message itself in a compact
envelope, so the agent answers from what it received and acknowledges with tt ack <token> --json
instead of fetching again. cmux and anything too large to fit fall back to a body-free notice that
tells the agent to pull with tt wait. Details in
Waking idle agents.
tt join / tt leave join or leave the room for this workspace
tt wait long-poll for the turn and room events (--park to never auto-claim)
tt standby park and wake this session later
tt release / tt pass hand off with structured status and next action
tt assign <agent> hand off to someone specific
tt take claim when the holder is gone or stuck
tt chat operator console
tt msg send / tt notes message live processes, or leave durable notes
tt state / tt health room state and a concise safety check
Full flags and semantics: docs/reference.md.
| Method | Command |
|---|---|
| From npm | npm i -g talking-stick |
From GitHub (master) |
npm i -g github:mostlydev/talking-stick |
| From source | git clone … && npm install && npm link |
tt install --all --print # preview every change without touching anything
tt install claude-code codex # install into a subset
tt self-update # update using whichever npm/pnpm/yarn you installed with
tt uninstall --all # removeAfter updating, restart running harnesses so they load the new skill, and reopen tt chat so it uses
the new build.
Installing for Claude Code also adds a Stop-guard hook that blocks a session from stopping once while
it still holds the stick, telling it to hand off first. It is read-only, fails open, and never blocks
twice in a row. Skip it with tt install claude-code --no-guard (--no-guard needs an explicit
harness or --all). Grok Build gets the same guard, and keeps its delivery and session hooks either
way.
The bundled skill is the safety floor. Your own collaboration preferences live in editable Markdown that agents read after joining:
tt instructions show # effective prompt for the detected harness
tt instructions edit # your defaults
tt instructions edit --project # this repo's overridesLayering is bundled defaults → user overrides → project overrides. Unedited generated files update automatically; customized ones are preserved. See Editable collaboration instructions.
~/.local/share/talking-stick/rooms.sqlite on Linux/macOS (honoring $XDG_DATA_HOME),
%APPDATA%\talking-stick\rooms.sqlite on Windows. Override with TALKING_STICK_DATA_DIR.
npm install
npm test
npm run typecheck
npm run buildtt executes dist/cli.js, so run npm run build after source changes and restart any long-running
harness that cached the old build.
When cutting a release, add entries under CHANGELOG.md's Unreleased section, then run
npm version <new-version>. The lifecycle script moves those entries into the new version section,
writes docs/releases/<version>.md, and adds the GitHub release link before npm commits and tags.
docs/reference.md— full command surface, delivery semantics, identity resolution, install behavior, and design notes.docs/receive-consumer-contract.md— cursor ownership, subprocess lifecycle, filtering, and authority rules for the unified wait loop.skills/talking-stick/SKILL.md— the portable skill installed into harness skill directories.CHANGELOG.md— per-version summary; full notes indocs/releases/.
MIT. See LICENSE.md.
