If you're running multiple AI coding agents on the same repository, you've probably hit this: Agent A edits src/auth.rs while Agent B is also editing src/auth.rs. One overwrites the other. Nobody notices until the tests fail — or worse, until production breaks.
The fix is surprisingly simple, and it's been in git since 2015: worktrees.
What Git Worktrees Are
A git worktree is a separate working directory linked to the same repository. Each worktree has its own branch, its own staged changes, and its own files on disk — but they all share the same .git history.
Think of it as lightweight cloning without duplicating the entire repo.
# Your main repo
~/project/ # on branch: main
# Create two worktrees for two agents
git worktree add ~/project/.agents/agent-1 -b agent-1/task-auth
git worktree add ~/project/.agents/agent-2 -b agent-2/task-tests
# Now you have three working directories:
~/project/ # main
~/project/.agents/agent-1/ # branch: agent-1/task-auth
~/project/.agents/agent-2/ # branch: agent-2/task-tests
Each agent works in its own directory on its own branch. They can edit the same files simultaneously without conflicts — the conflicts only need to be resolved at merge time, when one agent's branch is integrated into main.
Step-by-Step: Manual Worktree Workflow
1. Create a worktree for each agent
mkdir -p .agents
git worktree add .agents/agent-1 -b agent-1/task-refactor-auth
git worktree add .agents/agent-2 -b agent-2/task-add-api-tests
git worktree add .agents/agent-3 -b agent-3/task-fix-css-bug
Each command creates a new directory with a fresh checkout on a new branch based on your current HEAD.
2. Point each agent at its worktree
Launch each agent in its own directory:
# Terminal 1
cd .agents/agent-1
claude-code # or codex, aider, etc.
# Give it the task: "Refactor the auth module to use JWT"
# Terminal 2
cd .agents/agent-2
codex
# Give it the task: "Add integration tests for the REST API"
# Terminal 3
cd .agents/agent-3
aider
# Give it the task: "Fix the CSS layout bug in the dashboard"
Each agent sees only its own working directory. It can read any file, edit anything, run any command — without affecting the other agents.
3. Run tests before merging
When an agent says it's done, verify:
cd .agents/agent-1
cargo test # or npm test, pytest, etc.
echo $? # 0 = tests pass, merge it
This is the critical step most people skip. Agents will confidently declare a task complete when the code compiles but tests fail. Always run the test suite before accepting an agent's work.
4. Merge back to main
cd ~/project # back to main worktree
git merge agent-1/task-refactor-auth
If there's a conflict (because agent-2 also touched a file agent-1 modified), git will tell you. Resolve it once, cleanly, instead of having agents silently overwrite each other during active work.
Pro tip: merge one branch at a time. If you merge agent-1 first, then merge agent-2, the second merge will see agent-1's changes as part of main. This serialized approach catches conflicts incrementally instead of all at once.
5. Clean up
git worktree remove .agents/agent-1
git branch -d agent-1/task-refactor-auth
Or reuse the worktree for the next task:
cd .agents/agent-1
git checkout main
git pull
git checkout -b agent-1/task-next-thing
Reusing is faster — creating a worktree means checking out the full working tree, which takes a few seconds on large repos.
Why This Works Better Than Branches Alone
You might think "just use branches" — and you're half right. Branches handle the version control. But without separate worktrees, all agents share the same working directory. That means:
-
git stashconflicts between agents - Uncommitted changes from one agent appear in another's environment
- Build artifacts and caches get confused
Worktrees give each agent a physically separate directory. No stash juggling, no dirty working tree from another agent's half-finished work, no shared build cache poisoning.
The Practical Limit
I've run 3-5 agents in parallel this way. Beyond 5, the codebase itself becomes the bottleneck — too many concurrent changes for clean merges. The sweet spot depends on your repo:
- Loosely coupled modules (microservices, independent features): 5+ agents work fine
- Tightly coupled codebase (shared state, lots of cross-file dependencies): 2-3 agents max
- Monorepo with clear boundaries: depends on how well tasks map to boundaries
Automating It
The manual workflow works but gets tedious at scale. You're creating worktrees, launching agents, checking test results, serializing merges, cleaning up — for each agent, for each task.
Batty automates this entire loop. It creates persistent worktrees per agent, dispatches tasks from a Markdown kanban board, runs tests before merging, and serializes concurrent merges with a file lock. The agents run in tmux panes so you can watch them work.
cargo install batty-cli
batty init --template pair # 1 architect + 1 engineer
batty start --attach
But the underlying pattern — worktree isolation, test gating, serialized merges — works with any workflow. Even a shell script that creates worktrees and runs git merge at the end is better than letting agents fight over the same directory.
Quick Reference
# Create worktree
git worktree add <path> -b <branch-name>
# List worktrees
git worktree list
# Remove worktree
git worktree remove <path>
# Prune stale worktree references
git worktree prune
The core insight: isolation at the filesystem level is simpler and more reliable than isolation at the branch level alone. Git worktrees give you both. They've been stable since git 2.5 (2015) and most developers have never used them.
If you're running multiple agents and haven't tried worktrees yet, this is the single highest-impact change you can make.
Top comments (0)