#!/usr/bin/env bash
# Worktree setup: 3 parallel lanes off 'main'
# Run from the repo root (inside my-app/).
set -euo pipefail
# Sync with the remote first so every lane branches off fresh 'main'.
# (If your local main is behind, run: git pull --ff-only origin main)
git fetch origin
# ── Lane 1: auth-flow ───────────────────────────────────
git worktree add -b feature/auth-flow ../my-app-worktrees/auth-flow main
# ── Lane 2: billing-page ────────────────────────────────
git worktree add -b feature/billing-page ../my-app-worktrees/billing-page main
# ── Lane 3: fix-navbar ──────────────────────────────────
git worktree add -b feature/fix-navbar ../my-app-worktrees/fix-navbar main
# Verify: every lane should be listed on its own branch.
git worktree list
# ── Launch one agent per lane ──────────────────────────────────
# Interactive CLIs block the shell: run each line in its OWN
# terminal tab, starting from the repo root.
cd ../my-app-worktrees/auth-flow && claude # terminal 1: auth-flow
cd ../my-app-worktrees/billing-page && claude # terminal 2: billing-page
cd ../my-app-worktrees/fix-navbar && claude # terminal 3: fix-navbar
# ════════════════ CLEANUP — run after each lane's PR is merged ════════════════
# WARNING: deletes branches. 'git branch -d' refuses branches with unmerged
# commits — only swap in -D once you are certain the work has landed.
# 'git worktree remove' refuses dirty worktrees; add --force to discard
# uncommitted changes on purpose.
git worktree remove ../my-app-worktrees/auth-flow
git branch -d feature/auth-flow
git worktree remove ../my-app-worktrees/billing-page
git branch -d feature/billing-page
git worktree remove ../my-app-worktrees/fix-navbar
git branch -d feature/fix-navbar
# Clear stale worktree bookkeeping under .git/worktrees:
git worktree pruneOne .git, many checkouts
A git worktree is a second (or fifth, or eighth) working directory attached to the same repository. Every worktree has its own checked-out branch, its own index, and its own uncommitted changes — but they all share one .git object store, one set of remotes, and one commit history. The feature has shipped with git since 2.5, released in 2015; it is plumbing you already have, not an add-on.
That sharing is what makes worktrees cheap. Adding one doesn't re-download anything or duplicate history — git just writes a new directory tree and a small pointer file. Creation takes about a second on most repos, and git worktree list always shows you every checkout and the branch it holds.
git worktree add -b feature/auth-flow ../my-app-worktrees/auth-flow main
# new folder, new branch, same repo — ready in ~1 second
git worktree list
# /home/you/my-app abc1234 [main]
# /home/you/my-app-worktrees/auth-flow def5678 [feature/auth-flow]Why parallel agents need isolation
A single checkout works fine for one human. Point two or more coding agents at the same directory and it fails in three distinct ways — none of them subtle, all of them time-wasting.
Interleaved edits
Checkout races
Mixed test state
Worktrees remove the shared surface entirely: each agent gets its own directory, branch, and index, so the only thing lanes share is committed history. That isolation is the foundation of any multi-agent coding workflow, and it's covered in depth in our guide to parallel agents with git worktrees.
Sibling folder vs in-repo worktrees
The generator offers two layouts, and the difference matters more than it looks. Sibling folders (../my-app-worktrees/<task>) keep worktrees completely outside the repo, so nothing can accidentally see them. In-repo worktrees (.worktrees/<task>) keep everything under one root — convenient for editors and terminals — but they must be gitignored, or each lane appears as thousands of untracked files inside every other lane. The generated script adds that entry for you.
| Sibling folder | In-repo (.worktrees/) | |
|---|---|---|
| Needs .gitignore entry | No | Yes — script adds it |
| Risk of tools scanning other lanes | None | Possible (search, file watchers) |
| Everything under one project root | No — two top-level folders | Yes |
| Safe with rm -rf of the repo folder | Worktrees survive | Worktrees deleted too |
| Good default for | Most teams, CI-like isolation | Single-folder editor setups |
Lifecycle hygiene: remove, prune, repeat
Worktrees are disposable by design — the mistake is treating them as permanent. The healthy rhythm is: create a lane, do the work, merge the PR, then immediately run git worktree remove and delete the branch. git worktree remove refuses to delete a dirty worktree, which is exactly the safety check you want; plain rm -rf skips that check and leaves stale metadata behind (fix it with git worktree prune).
Branch deletion deserves the same care. git branch -d refuses branches with unmerged commits; reach for -D only when you are certain the work landed or was deliberately abandoned. The cleanup block this tool generates follows that order — remove, delete, prune — with the warnings inline, so future-you doesn't nuke an unmerged lane at 6pm on a Friday.
How many lanes should you run?
Honest answer: fewer than your machine can handle. Git scales to hundreds of worktrees and a modern laptop runs several CLI agents fine — the bottleneck is your review attention. Every lane produces a diff a human must actually read, and skimming five PRs is worse than reviewing two properly. Rate limits on your model plan bite before RAM does, too.
Start with two or three lanes on tasks that touch different parts of the codebase, and grow only when review stops being the constraint. Good task boundaries and shared context help more than extra lanes: a solid context file (try the AGENTS.md generator) and a deliberate routing strategy (see Claude Code orchestration) raise the quality of every lane you run.