coordination for Claude Code teams
How it works

Facts from hooks, decisions from people

Claude Code's hooks post every edit to a small shared server. The server knows which team owns and imports what, so it routes each change to the leads it concerns. Leads announce plans and record decisions; a change no decision covers goes to the engineer. Nothing depends on an agent remembering to report something.

Who talks to whom

RoleTalks toDoesNever
EngineerTheir own leadSets direction, answers escalations, approves every mergeRelays anything to another team
Lead agentIts engineer, its workers, other leadsBreaks requirements into tasks, delegates, reviews worker output, announces status, filters incoming updates, approves critical changes its engineer's decisions already coverWrites code, blocks another team, approves anything not covered by a decision
Worker agentIts own lead onlyWrites code, adapts to routine changes on its own, reports critical ones to its leadTalks to other teams or the engineer, merges

Leads can inform each other but never block each other. Every merge still needs a human.

Facts come from hooks

The plugin installs Claude Code hooks on every agent in your team. After each Edit, Write or NotebookEdit, the hook posts what changed to the server: the file, the session, your engineer and team, and the file's content before and after. Shell edits are caught too. The hook answers fast and never blocks the session; if the server can't be reached, the edit simply goes ahead.

From that data the server derives the facts leads care about:

Leads add the why: announcement, decision_recorded and escalation come from the lead's own MCP tools.

The dependency graph

The host builds a graph of the repo from origin/main: which file imports which, and which exported names it uses. The host fetches every 30 seconds and rebuilds when main moves, so merges pushed from any machine are seen. TypeScript repos get the graph; in other languages routing falls back to ownership and claims.

Routing

An edit goes to the lead of the team that owns the file, plus every lead whose code imports it. A breaking contract_changed is routed per symbol: only to leads whose files import that symbol, plus the owner and the author's own lead. A team with no importer gets nothing. Messages are coalesced per file and receiving team, so a worker making ten edits to one file produces one message, not ten.

Ownership and claims

Ownership is declared: mai own records the paths your team is responsible for, like a CODEOWNERS file. The longest matching prefix wins and a path another team owns is refused.

Claims are temporary. The first edit to a file in another team's area claims it for your team; an edit to a file another team holds is denied, with the holder named in the reason, so two teams never rewrite the same file at once. A claim expires after a quiet period (default two hours; each edit by the holder restarts it), or earlier when the holding lead gives it up with its release tool. An edit inside your own area, or to a file no team owns, claims nothing.

Critical changes and escalation

Workers adapt to routine changes on their own: additive fields, internal refactors, tests. Critical ones climb worker → lead → engineer and stop at the first level that can decide:

  1. A breaking export change or a new migration reaches the lead, pushed as a fact about its own team or reported by a worker.
  2. If one of the engineer's logged decisions covers it, the lead approves, citing the decision.
  3. If nothing covers it, the lead calls escalate. The engineer answers in the lead chat and the lead logs a decision that resolves the escalation. The next change of the same kind is approved without asking.

Escalations are records. They survive a crash or restart, mai escalations lists the open ones, and a new lead session starts with them in context.

The merge safety net

A breaking change made in a way no hook sees (a script, a rebase, a merge from another machine) is caught when main moves: the server diffs the exports between the last scanned commit and the new one and records what the hooks missed. A change a hook already reported isn't reported twice. The last scanned commit is persisted, so a merge that lands while the host is down is scanned at the next start.

The channel

Each lead session holds a WebSocket to the server. Announcements, claims on your files, ownership changes and critical facts arrive in the lead's session as channel messages within seconds. If the connection drops, the channel reconnects and asks for everything since the last event it saw; delivered critical facts are never replayed twice, even across a server restart. When a lead starts, its session begins with the team's decisions, the ownership map, active claims, open escalations, other leads' recent announcements and the critical changes that concern the team since its previous lead session already in context.

Rules that never break