What is Worktree Isolation in AI Agents? Parallel Execution Without Conflicts
I ran two agents in parallel. Both were making great progress. Then they started overwriting each other’s changes.
Agent A: Writing to src/auth.py...Agent B: Writing to src/auth.py...Agent A: Saved successfully!Agent B: Saved successfully! (overwrote Agent A's work)Agent A’s changes were gone. No warning, no merge conflict, just silent data loss. The agents were working on the same repository, in the same working directory, on different tasks. Chaos.
This is the parallel execution problem. Worktree isolation solves it.
The Problem: Shared Workspace Collisions
When you dispatch multiple agents to work simultaneously, they share the same filesystem:
project/ src/ auth.py <-- Agent A is here models.py <-- Agent B is here utils.py <-- Agent C is here auth.py <-- Agent D is ALSO here (collision!)If Agent A and Agent D both modify auth.py, one of them loses. The last write wins. No coordination, no awareness of each other.
I tried file locking. It created deadlocks. I tried mutex coordination between agents. Too slow. I tried having agents check git status before writing. Race conditions.
The real solution? Give each agent its own directory.
Git Worktree: Multiple Checkouts, One Repository
Git worktrees let you have multiple working directories from the same repository:
# Main repositorycd /projects/myappgit worktree add ../myapp-feature-login feature/logingit worktree add ../myapp-feature-api feature/api
# Now you have:# /projects/myapp (main branch)# /projects/myapp-feature-login (feature/login branch)# /projects/myapp-feature-api (feature/api branch)Each worktree:
- Has its own working directory
- Shares the same
.gitstorage - Can checkout different branches
- Operates independently
main_repo/├── .git/ # Shared git data├── .worktrees/│ ├── task_001/ # Agent A's isolated directory│ │ └── (feature/login files)│ ├── task_002/ # Agent B's isolated directory│ │ └── (feature/api files)│ └── task_003/ # Agent C's isolated directory│ └── (feature/docs files)└── (main branch files)
Each worktree sees the same repository history but has independent working changes.How Worktree Isolation Works in AI Agents
The s12 worktree isolation pattern binds each task to its own worktree. Here’s the core concept:
Task ID 001 -> /repo/.worktrees/task_001/Task ID 002 -> /repo/.worktrees/task_002/Task ID 003 -> /repo/.worktrees/task_003/
The binding: One task, one worktree, one agent.When an agent picks up a task:
- Check if task has a worktree
- If not, create one with
git worktree add - Switch the agent’s working directory to that worktree
- Agent works in isolation
class WorktreeManager: def __init__(self, repo_path: Path): self.repo = repo_path self.worktrees_dir = repo_path / ".worktrees" self.worktrees_dir.mkdir(exist_ok=True)
def get_or_create(self, task_id: int) -> Path: worktree_path = self.worktrees_dir / f"task_{task_id}"
if not worktree_path.exists(): # Create a new branch for this task branch_name = f"task/{task_id}" subprocess.run([ "git", "worktree", "add", str(worktree_path), "-b", branch_name ], cwd=self.repo, check=True)
return worktree_path
def cleanup(self, task_id: int): """Remove worktree after task completion.""" worktree_path = self.worktrees_dir / f"task_{task_id}" subprocess.run(["git", "worktree", "remove", str(worktree_path)], cwd=self.repo, check=True)The Isolated Execution Lane
Each worktree creates an isolated execution lane:
┌─────────────────────────────────────────────────────────────┐│ Main Repository ││ .git/ (shared) │└─────────────────────────────────────────────────────────────┘ │ │ │ v v v┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ Worktree 1 │ │ Worktree 2 │ │ Worktree 3 ││ Agent A │ │ Agent B │ │ Agent C ││ Task: auth │ │ Task: api │ │ Task: docs ││ │ │ │ │ ││ src/auth.py │ │ src/api.py │ │ docs/api.md ││ (modified) │ │ (modified) │ │ (modified) │└─────────────────┘ └─────────────────┘ └─────────────────┘
No collisions. Each agent in its own sandbox.Why This Works
1. Same Repository, Different Directories
All worktrees share the same git objects:
main_repo/.git/objects/├── pack/│ └── pack-abc123... (shared pack files)└── info/
No duplicate storage. All worktrees reference the same commit history.This means:
- Commits in one worktree are visible in others
- You can cherry-pick between worktrees
- Branches can be merged normally
2. No Merge Conflicts During Work
Each agent works on its own branch:
main ----*----*----*----* \task/001 *----*----* (Agent A's work) \task/002 *----* (Agent B's work)
Agents work independently. Merge conflicts only happen during integration.3. Task-Worktree Binding
The key insight: tasks manage goals, worktrees manage directories, bound by task ID.
Task 001: subject: "Implement OAuth login" status: "in_progress" worktree: "/repo/.worktrees/task_001/" branch: "task/001"
Task 002: subject: "Add API rate limiting" status: "in_progress" worktree: "/repo/.worktrees/task_002/" branch: "task/002"
When agent picks up Task 001, it works in worktree 001.When agent picks up Task 002, it works in worktree 002.When to Use Isolation
Worktree isolation isn’t always needed. Here’s when it matters:
Use Isolation When:
- Running multiple agents in parallel- Agents work on overlapping files- Tasks are independent and can be merged later- You want clean separation of workSkip Isolation When:
- Only one agent at a time- Agents work on completely separate files- Sequential task execution (one after another)- Quick fixes that don't need branchesIntegration: The Final Step
After agents complete their work in isolated worktrees, you integrate:
# Back in main repositorygit worktree list# /projects/myapp abc123 [main]# /projects/myapp/.worktrees/task_001 def456 [task/001]# /projects/myapp/.worktrees/task_002 ghi789 [task/002]
# Review and mergegit log task/001 --onelinegit merge task/001 --no-ff -m "Merge task/001: OAuth login"
git merge task/002 --no-ff -m "Merge task/002: Rate limiting"
# Cleanupgit worktree remove .worktrees/task_001git worktree remove .worktrees/task_002git branch -d task/001 task/002The Full Lifecycle
1. Agent claims task 0012. Check: Does .worktrees/task_001 exist? - No: Create worktree + branch3. Switch working directory to .worktrees/task_0014. Agent does work, makes commits5. Agent marks task as completed6. Human or orchestrator reviews and merges7. Cleanup: Remove worktree + delete branchError Handling
Worktrees can fail. Handle these cases:
# Error: Branch already exists$ git worktree add ../task_001 -b task/001fatal: a branch named 'task/001' already exists
Solution: Check if branch exists, use existing or create new name
# Error: Path already exists$ git worktree add ../task_001fatal: '../task_001' already exists
Solution: Remove directory or use different path
# Error: Uncommitted changes in main$ git worktree add ../task_001 -b task/001fatal: cannot create a new worktree with uncommitted changes
Solution: Commit or stash changes firstWhat Changed From s11
| Component | Before (s11) | After (s12) |
|---|---|---|
| Execution | Single workspace | Isolated worktrees |
| Parallelism | Sequential or risky | Safe concurrent |
| Branches | Ad-hoc | Per-task branches |
| Conflicts | Runtime collisions | Merge-time resolution |
| Cleanup | Manual | Automated worktree removal |
The s12 session is the final piece in the 12-session progression. It combines:
- Agent loop (s01) - The core execution engine
- Tools (s02) - File operations, now scoped to worktrees
- Planning (s03) - Todo lists for task coordination
- Subagents (s04) - Spawn isolated agents per worktree
- Skills (s05) - Reusable worktree-aware capabilities
- Context management (s06) - Each worktree has isolated context
- Tasks (s07) - Task-worktree binding by ID
- Background tasks (s08) - Parallel execution across worktrees
- Teams (s09) - Agents coordinate via task ownership
- Protocols (s10) - Handshake when passing work between worktrees
- Autonomous agents (s11) - Self-directed task claiming
The Motto
The learn-claude-code project has a motto for s12:
“Each works in its own directory, no interference”
This is the final piece of the harness engineering puzzle. With worktree isolation, you can safely run dozens of agents in parallel, each working on its own task, in its own sandbox, all contributing to the same repository.
Limitations in the Learning Project
The s12 implementation in learn-claude-code is a 0-to-1 learning project. It includes a minimal append-only lifecycle event stream for teaching purposes. Production implementations would need:
- Automatic worktree pruning after merge
- Conflict detection before merge
- Worktree health monitoring
- Resource limits (disk space, open file handles)
- Branch naming conventions
But the core concept is complete: tasks manage goals, worktrees manage directories, bound by ID.
References
- learn-claude-code GitHub Repository - Source code and documentation
- Git Worktree Documentation - Official git worktree docs
- Claude Code Documentation - Agent worktree patterns
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Isolation enables parallelism. Without it, concurrent agents overwrite each other. With it, each agent gets its own sandbox. Same repository, different directories, no conflicts. The task ID binds the goal to the directory, creating isolated execution lanes that make parallel agent work safe and predictable.
Comments