Six AI Coding Agents, One Codebase: The Fix That Finally Worked
I run AI coding agents the way most people run browser tabs. On a busy day there are six live Claude Code sessions working across our product portfolio: one shipping a CRM feature, one fixing a marketing site, one debugging a deploy, and a few more picking off smaller tasks. That parallelism is a genuine force multiplier, and it is also how I learned, repeatedly and painfully, that multiple autonomous agents sharing one git repository will eventually destroy each other's work.
The failure modes nobody warns you about
Two agents in the same working directory share everything: the same git HEAD, the same working tree, the same untracked files. Every disaster we hit traces back to that single fact.
- The scattered-commits day. One session ran a
git checkoutwhile five others were mid-task. Their next commits landed on whatever branch HEAD now pointed at. A full day of work ended up sprayed across the wrong branches. - The phantom migration. One session left a half-finished database migration as an untracked file. A different session ran the deploy script, which syncs the working tree, and shipped that unfinished migration straight to production. Every deploy after that failed with "table already exists" until we hunted down a file that no branch in git history had ever contained.
- The vanishing model. During a cleanup, a session deleted an application model file that a sibling session's feature depended on. Neither session had any way to know the other cared.
None of these are exotic. If you run parallel agents on one clone, you are on a countdown to all three.
Why the obvious fixes keep failing
We tried what everyone tries first: instruction files telling agents to check for siblings, persistent memory notes, warnings printed at session start, skills that create isolated workspaces on request. Every one of them failed for the same reason: they are advice, and advice does not survive an agent's context window.
Long agent sessions compact their context to keep going. When that happens, the warning the agent saw three hours ago is gone. The agent is not being careless; the information physically is not there anymore. Any safety mechanism that lives in the agent's memory has a half-life measured in hours.
The lesson took me an embarrassing number of incidents to accept: coordination between autonomous agents cannot be a suggestion. It has to be enforcement, applied at the tool layer, where the agent literally cannot do the wrong thing.
The rule: one writer per clone
The solution that finally stuck is a single deterministic rule, enforced by a small hook that intercepts every file edit and every dangerous shell command before it executes:
- The oldest live session in a repository owns its working tree. It works exactly as it always has, zero friction.
- Every other session is read-only in that tree. File edits, deletions,
git add,git commit, in-place edits, and deploy scripts are hard-blocked with a non-zero exit code. The block message contains the exact next step, so the agent self-corrects in one move. - That next step is a git worktree. Each blocked session isolates into its own worktree: a separate working directory sharing the same repository history. Ours are provisioned automatically (dependencies, environment files, build output), so the agent is productive seconds after isolating. Inside its own worktree, nothing is ever blocked.
- Sessions register themselves in a per-repo lock file at startup, with dead sessions pruned automatically. A session that wanders into a repo it did not start in claims the lock on its first write, so cross-repo work is guarded too.
Reads are never blocked, so shared-clone research stays free. Solo sessions never notice the guard exists. And because the rule is enforced by a hook rather than remembered by a model, it survives context compaction indefinitely. The whole thing adds about six milliseconds to a typical command.
The design principles that mattered
Looking back, four principles separate this attempt from every failed one:
- Enforcement beats instruction. If a safety rule matters, encode it where it cannot be forgotten: hooks, exit codes, file locks. Save the prompt engineering for judgment calls, not guardrails.
- Determinism in the safety layer. The guard is a few hundred lines of shell and Python with no model in the loop. Same input, same verdict, every time, testable with a fixture matrix.
- Make the correct path the easy path. A block that just says "no" trains the agent to look for workarounds. A block that says "run this one command and redo your change over there" gets compliance every time.
- Over-protect, never under-protect, with human escape hatches. Ambiguous cases resolve toward blocking. A human can override with an environment variable; an agent cannot.
Since the guard went in, the failure class is simply gone. Six sessions, one repository, no shared-tree writes, and the isolation cost is one command paid once per session.
The bigger pattern
Multi-agent development is arriving faster than the tooling around it. The instinct is to solve coordination problems with better prompts, but prompts are the wrong tool for invariants. Git already gave us the primitive (worktrees), and every serious agent platform gives you interception points around tool execution. Wire the two together and parallel agents stop being a liability and start being the multiplier they promised to be.
This is the kind of infrastructure thinking we bring to every engagement at Champlin Enterprises: we run AI-native development on our own products daily, hit the sharp edges first, and ship the fixes into client work. If your team is adopting AI coding agents and wants the guardrails before the war stories, we should talk.
See what we build Browse our shipped workLinks mentioned