I’ve been running a project with multiple Claude Code sessions in separate Git worktrees: Primary W1 W2 W3 The annoying part wasn’t the parallel work. It was me constantly copying messages between windows: “W1 says this.” “Tell W3 this.” “W3 found a problem, send it back to W1.” So we built a very small inter-agent communication layer inside the repo. The basic idea is: W1 ──→ Primary ←── W2 …│ …↓ …W3 Agents can send messages, acknowledge them, and hand off exact Git SHAs directly. Active Claude Code sessions check their inbox at defined checkpoints, so Primary can send W3 a task and W3 can pick it up and start working without me relaying the message. The part that got interesting is that this project needed blind independent work. W1 and W2 were independently attacking the same research problem and were not allowed to see each other’s results. Once both froze their work at exact SHAs, Primary released only those frozen artifacts to W3 for an independent comparison. So we ended up needing three different concepts:
- transport: who can message whom
- project state: who is authorized to do what
- artifact identity: the exact Git SHA being discussed Keeping those separate turned out to matter a lot. We also had another Claude session hostile-review the coordination system before trusting it, and it found some surprisingly subtle leaks. For example, an early implementation checked whether a file existed in another lane’s commit before checking whether the sender was authorized to inspect that commit. That meant an unauthorized agent could potentially learn information from different error responses. We also had to deal with:
- commits surviving under tags after branches move
- merge ancestry leaking ownership
- sender authorization, not just recipient authorization
- making “released artifact” different from “this lane is no longer blind”
- keeping old private W1→Primary messages private even after a W1 result is released
- making missing-path and existing-path probes against unauthorized work indistinguishable
The resulting system is deliberately boring. It stores messages locally under the shared .git directory, makes no network calls, owns no project state, and doesn’t create a separate coordination branch.
Git owns artifacts.
The project protocol owns state.
The messaging layer owns transport.
Current limitation: it does NOT resurrect a dead Claude Code session. An active session can check its inbox and continue automatically, but if the process has actually exited there is nobody there to receive the message.
Our next experiment is a blocking
coord waitcommand so an agent can sit essentially idle until another authorized agent sends it something, without burning model turns polling. I wrote up the full current SOP here: https://gist.github.com/amarcus10028/0e58cf69a15c9eb7e3f0dd6325e0d59c I’m curious what people who run a lot of parallel Claude Code sessions think. Especially: What failure modes are we missing? Would you trust a shared-.git transport for cooperative same-machine agents? Has anyone found a clean way to do wait/resume without adding a daemon? Is there already a tool that handles this exact combination of worktrees + SHA-pinned handoffs + controlled blindness? submitted by /u/alexmarcus11249
Originally posted by u/alexmarcus11249 on r/ClaudeCode
