March 20, 2026

Git Worktrees for Parallel AI Agents

Isolated workspaces with git worktrees, bare repos, and Worktrunk

Bjorn Krols
Bjorn KrolsFounder

Git worktrees let you work on multiple branches simultaneously without the context switching of git checkout. They provide separate working directories that share a single repository, eliminating the need to stash changes, wait for IDE reindexing, or maintain multiple clones.

This makes them useful for everyday development workflows like code review, hotfixes, and cross-branch debugging. But they really shine when running multiple AI agents in parallel, each handling a discrete task in its own isolated workspace.

Parallel hands


How Worktrees Work

Linked working directories, shared history.

Worktrees create linked working directories that reference the same .git repository. They share commits, branches, and tags while maintaining independent working files and HEAD pointers.

Command Description
git worktree add <path> <branch> Create new worktree at path for existing branch
git worktree add <path> -b <new-branch> <base> Create new worktree with new branch
git worktree list Show all worktrees and their branches
git worktree remove <path> Delete a worktree
git worktree prune Clean up worktree metadata for deleted directories

git checkout rewrites files in your working directory, updates HEAD, and forces your IDE to re-parse thousands of changed files. On large codebases, this "IDE tax" can exceed 30 seconds. Worktrees sidestep this entirely. Context switching becomes simply changing directories. Compared to multiple clones, worktrees use 15% of the disk space and create 4.5x faster.


Why Not Just Clone

Clones duplicate, shared checkouts collide.

The simplest approach is to clone the repo multiple times, one per agent or task. But each clone duplicates the full Git history, eats disk space, and drifts out of sync. Fetching, pruning, and coordinating branches across clones becomes its own maintenance burden.

The other extreme, running multiple agents on the same clone, is worse. Agents overwrite each other's files, compete for the working directory, and can't be on different branches simultaneously. One stash or checkout wipes another agent's context.


Why Bare Repositories

Make the repo coordination-only, with no privileged branch.

With a standard clone, worktrees are created as subdirectories inside the main working tree. This means tooling picks up the wrong files, and the parent worktree's state bleeds into every child. A bare repo eliminates this by containing only Git metadata, with no working directory of its own. All worktrees live as siblings outside it, each a clean checkout of a branch.

project/
├── .bare/                 <- bare repo (no working files)
├── .git                   <- points to .bare
├── main/                  <- worktree: main branch
├── feature/auth/          <- worktree: agent 1
├── feature/payments/      <- worktree: agent 2
└── hotfix/login-crash/    <- worktree: agent 3

Why this matters:

  • No privileged working directory to accidentally pollute - main can be a worktree, but it's opt-in
  • Every branch is a first-class working environment, not an afterthought
  • Agents can't accidentally modify main while working on a feature
  • Cleaner mental model: the repo is the source of truth, worktrees are ephemeral workspaces

Initial setup (once per project):

# Clone as a bare repo
git clone --bare https://github.com/user/project.git project/.bare
 
# Point .git so tooling finds it
echo "gitdir: ./.bare" > project/.git
 
# Fix the remote fetch config
git -C project/.bare config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
 
# Fetch all remote branches
git -C project/.bare fetch origin

Why Worktrunk

Make worktree management a single command.

Raw git worktree commands are verbose and leave everything else to you: no dependency installation, no environment setup, no way to see status across worktrees at a glance. Worktrunk wraps the full worktree lifecycle into simple commands and adds the automation layer that makes worktrees practical at scale.

Key reasons we chose it:

  • Versionable project config - .config/wt.toml is committed to the repo, so every agent and teammate gets identical setup automatically
  • Post-create hooks - dependencies install and config files copy themselves on every new worktree, zero manual steps
  • Bare repo support - works natively with the bare repo pattern

Install and configure:

brew install worktrunk && wt config shell install

Shell integration lets commands like wt switch change your working directory automatically.

Global config - set the worktree layout so worktrees are created as sibling directories (works with the bare repo pattern):

# ~/.config/worktrunk/config.toml
worktree-path = "../{{ branch | sanitize }}"

Project config - committed to the repo so every developer and agent gets the same setup:

# .config/wt.toml
[post-create]
install = "pnpm install"
copy-env = "cp $(git worktree list | head -1 | awk '{print $1}')/.env .env"

The post-create hooks run after every new worktree, ensuring dependencies are installed and environment files are copied automatically.

Claude Code

If you use Worktrunk alongside Claude Code, the Worktrunk plugin adds status indicators to wt list showing which Claude sessions are actively working vs. waiting on user input.


Claude Code's Native Worktree Support

Built-in isolation, no external tooling required.

Claude Code has first-class worktree support via the --worktree flag (or -w). It creates a worktree, starts a session in it, and cleans up on exit:

claude --worktree my-feature
# or shorthand
claude -w my-feature
# omit the name and Claude generates one (e.g., "bright-running-fox")
claude -w

Worktrees are created in .claude/worktrees/ inside the repo by default. This keeps them contained (no sibling folder sprawl), hidden from normal ls output, and easy for Claude to auto-cleanup on exit.

Note that --worktree does not currently support the bare repo pattern. It expects a standard clone with a working directory.

WorktreeCreate hooks

New worktrees are missing .env files (gitignored) and node_modules. Without a hook, the agent wastes tokens debugging missing environment variables before it even starts the real task.

WorktreeCreate hooks solve this. They replace the default git worktree behavior entirely: your hook must create the worktree itself and print the absolute path to stdout.

// .claude/settings.json
{
  "hooks": {
    "WorktreeCreate": [
      {
        "command": ".claude/hooks/setup-worktree.sh"
      }
    ]
  }
}

The hook script can detect the package manager, install dependencies, and copy .env files automatically on every new worktree.


Workflows

Parallel agent development

# Spin up a worktree per task (hooks install deps automatically)
wt switch --create feature/auth
claude "implement OAuth 2.0 login flow per the spec in docs/auth.md"
 
# Meanwhile, in another terminal
wt switch --create hotfix/payment-bug
claude "fix the Stripe webhook signature validation bug in issue #342"
 
# Check status across everything
wt list

Code review

# Check out a PR directly (resolves branch via gh CLI)
wt switch pr:147
# Review the code, then return to your work
wt switch feature/auth
# Clean up after merge
wt remove feature/fix-typo

Your original workspace remains untouched: uncommitted changes, running processes, terminal history intact. Reuse this worktree for all future reviews.

Emergency hotfixes

# Create hotfix worktree (hooks install deps automatically)
wt switch --create hotfix/security
# Fix, commit, and push
gh pr create --fill
# Return to feature work
wt switch feature/auth
# Clean up after merge
wt remove hotfix/security

Cross-branch debugging

# Create worktrees for each version
wt switch main
wt switch feature/auth
# Run them on different ports (3000, 3001)
# Compare behavior side-by-side in your browser

Multiple permanent worktrees

Maintain dedicated worktrees for different purposes:

  • main for read-only reference
  • work for active development
  • review for PRs
  • test for long-running tests

Context switching becomes wt switch work instead of disruptive git operations.

Updating a worktree to latest main

git fetch origin
git rebase origin/main

Practical Considerations

Dependency installs (Node.js)

Both pnpm and Bun use a global content-addressable cache. When you run pnpm install or bun install in a new worktree, packages are linked from the cache rather than downloaded. Installation is near-instant regardless of project size, eliminating the need to symlink node_modules between worktrees.

Dev server port conflicts

When running multiple worktrees simultaneously, each dev server needs its own port. The recommended approach is to set the port as an environment variable in each worktree's .env file (e.g. PORT=3001, PORT=3002). This keeps port assignment explicit and under developer control without requiring any tooling changes.

Database isolation

By default, worktrees share a single local database. Options include template databases (clone a base DB per worktree) and per-worktree database naming conventions.

Bjorn Krols


Construisons votre produit

Dites-nous ce que vous construisez. Nous vous dirons comment nous l'aborderions, ce qu'il faut, et à quelle vitesse nous pouvons avancer.

Nous vous dirons honnêtement si nous sommes le bon choix. Et si ce n'est pas le cas, nous vous orienterons vers quelqu'un qui l'est.