Skip to content

Cross-session coordination for independently-launched Claude Code sessions #76727

Description

@wshallwshall

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.

  1. 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. (Subagent tool calls: PreToolUse denials don't surface to the parent, and hook payload carries the parent's session_id #76726)
  2. A subagent's hook payload carries the PARENT's session_id — session-keyed locks/claim registries are silently broken for subagents. (Subagent tool calls: PreToolUse denials don't surface to the parent, and hook payload carries the parent's session_id #76726)
  3. Malformed hook output silently no-ops. A bare {"permissionDecision":"deny"} without the hookSpecificOutput wrapper does nothing — the tool runs, no warning. (Filed as [BUG] permissionDecision: "deny" in PreToolUse hooks is ignored - tools execute anyway #4669 / PreToolUse hook permissionDecision: "deny" ignored for Edit tool — tool executes despite deny #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.
  4. Docs gap, load-bearing: the docs don't state whether hooks fire for subagent tool calls, or what session_id they 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

  1. Fix the silent failures above (esp. Create SECURITY.md #1 and Claude is either blank or non-interactive #3). Enforcement that can be off without saying so is worse than none.
  2. Document the subagent hook semantics (do hooks fire for subagent tool calls? what session_id do they carry?).
  3. 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.
  4. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions