Skip to content

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.

The collision
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:

The collision zone
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:

Git worktree basics
# Main repository
cd /projects/myapp
git worktree add ../myapp-feature-login feature/login
git 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 .git storage
  • Can checkout different branches
  • Operates independently
Worktree structure
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-worktree binding
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:

  1. Check if task has a worktree
  2. If not, create one with git worktree add
  3. Switch the agent’s working directory to that worktree
  4. Agent works in isolation
Conceptual worktree management
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:

Isolated lanes
┌─────────────────────────────────────────────────────────────┐
│ 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:

Shared 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:

Branch isolation
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.

The binding contract
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 work

Skip 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 branches

Integration: The Final Step

After agents complete their work in isolated worktrees, you integrate:

Merging isolated work
# Back in main repository
git worktree list
# /projects/myapp abc123 [main]
# /projects/myapp/.worktrees/task_001 def456 [task/001]
# /projects/myapp/.worktrees/task_002 ghi789 [task/002]
# Review and merge
git log task/001 --oneline
git merge task/001 --no-ff -m "Merge task/001: OAuth login"
git merge task/002 --no-ff -m "Merge task/002: Rate limiting"
# Cleanup
git worktree remove .worktrees/task_001
git worktree remove .worktrees/task_002
git branch -d task/001 task/002

The Full Lifecycle

Worktree lifecycle for a task
1. Agent claims task 001
2. Check: Does .worktrees/task_001 exist?
- No: Create worktree + branch
3. Switch working directory to .worktrees/task_001
4. Agent does work, makes commits
5. Agent marks task as completed
6. Human or orchestrator reviews and merges
7. Cleanup: Remove worktree + delete branch

Error Handling

Worktrees can fail. Handle these cases:

Common worktree errors
# Error: Branch already exists
$ git worktree add ../task_001 -b task/001
fatal: 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_001
fatal: '../task_001' already exists
Solution: Remove directory or use different path
# Error: Uncommitted changes in main
$ git worktree add ../task_001 -b task/001
fatal: cannot create a new worktree with uncommitted changes
Solution: Commit or stash changes first

What Changed From s11

ComponentBefore (s11)After (s12)
ExecutionSingle workspaceIsolated worktrees
ParallelismSequential or riskySafe concurrent
BranchesAd-hocPer-task branches
ConflictsRuntime collisionsMerge-time resolution
CleanupManualAutomated 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

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