Cross-session coordination for independently-launched Claude Code sessions
Summary
Heavy users who run many independently-launched Claude Code sessions against one repo with one shared working tree have no first-party coordination story. The only real primitive is a PreToolUse deny hook — a build-it-yourself kit — and that kit has silent holes (below). I spent a day measuring what actually collides between sessions on my own machine and building guards for it; sharing the findings because one of them would change how a first-party version should be built.
Setup: solo dev, Windows 11, one Python repo, ~20 git worktrees, routinely 15–20 concurrent sessions (VS Code extension + Desktop app).
Caveat, stated up front: this is one machine, one repo, one unusually parallel developer. The measurements are real but n=1. Offered as evidence, not a general claim.
---
The finding I'd most want you to see
If you ship a "don't build in the shared checkout" guard, key it on the write's TARGET PATH, not on the session's cwd. The obvious design is wrong.
Measured over 30 days of my own transcripts: 166 sessions ran with cwd = the shared primary checkout. Of their 13,782 Edit/Write calls:
| Writes | Share | What it is |
|-------:|:-----:|------------|
| 6,075 | 44% | wrote into the primary's tree — the actual problem |
| 4,010 | 29% | wrote into a worktree by absolute path — already correct |
The second row is the trap. Nearly a third of writes come from a session sitting in the primary that correctly writes into a worktree by absolute path. A cwd-keyed gate can't tell those apart and would have denied all 4,010 of them. Where a session sits is irrelevant; only where it writes matters. I got this wrong on my first design — and so did every design I generated before measuring.
Same theme, secondary: a deny that just refuses causes the model to thrash or route around it (e.g. shell redirect). A deny that names the exact command to run causes self-correction — in a live test under bypassPermissions, a blocked session ran the worktree-creation script itself and landed its edit in the new worktree without being told to.
---
Bugs / silent failures (these cost me the most time)
These are why the DIY PreToolUse approach is unsafe today — they share a theme, enforcement that can be off without saying so. The first two are filed as a companion bug report with full repro: #76726.
- A subagent's permission denials don't surface to the parent — parent result comes back with
permission_denials: []while the fan-out wrote nothing. Fails silent, not safe. (#76726) - A subagent's hook payload carries the PARENT's
session_id— session-keyed locks/claim registries are silently broken for subagents. (#76726) - Malformed hook output silently no-ops. A bare
{"permissionDecision":"deny"}without thehookSpecificOutputwrapper does nothing — the tool runs, no warning. (Filed as #4669 / #37210, closed as not planned.) "Your guard is off and nothing tells you" is a bad default. Related: a hook whose script path is missing exits non-zero-but-not-2, which also lets the tool run silently. - Docs gap, load-bearing: the docs don't state whether hooks fire for subagent tool calls, or what
session_idthey carry. That single fact determines whether any hook-based enforcement has a hole in it. I had to determine it empirically.
---
The gap itself
Your docs are the evidence, and they're clear: worktrees isolate file edits; subagents and agent teams coordinate work. But agent teams are one-team-per-session, can't be joined by independently-launched sessions, and give teammates no worktree isolation (they share the lead's cwd — the guidance is "partition the work so each teammate owns a different set of files").
So the case heavy users actually hit — many independently-started sessions, one repo, one shared working tree — has no first-party story. The only real primitive is PreToolUse deny.
Collisions that bit me, none of which any current feature sees:
- Sessions building in the shared primary checkout instead of a worktree (the 44% above).
- A session running
git checkout <its-branch>in the shared primary and detaching HEAD — swapping the entire working tree out from under every other session mid-task. Hooks can't see this at all: it's a shell command, so there are no tool arguments to inspect. Happened to me twice in one day. - Two sessions independently allocating the same "next free" ID in a shared ledger file: different filenames, merges clean, silently corrupt. No lock, no worktree, and no merge-conflict prediction catches this class.
---
What I'd ask for, in priority order
- Fix the silent failures above (esp. #1 and #3). Enforcement that can be off without saying so is worse than none.
- Document the subagent hook semantics (do hooks fire for subagent tool calls? what
session_iddo they carry?). - A first-party notion of "this checkout is shared; sessions should not build here" — keyed on target path, with a deny message that tells the model how to proceed.
- Longer term: let independently-launched sessions see each other. Even a read-only registry ("these 6 sessions are live, here's their cwd and branch") would let users build the rest.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗