You point Claude Code at a codebase, it spins up four agents, and they all work at the same time without overwriting each other. The obvious question for anyone who knows Git: how? You can only have one branch checked out at a time. Two agents editing the same folder would clobber each other within seconds.
The answer is a Git feature almost nobody teaches: worktrees. I'm a software engineer, and this is the same setup I use to run agents in parallel. If you're new to Git, read Git for Vibe Coders first. This guide picks up where that one's worktree teaser left off and goes all the way to the parallel-agent setup.
A branch is a pointer, not a copy
This is the mental model nobody gives you, and it's the whole reason worktrees exist. When you create a branch, Git does not duplicate your code. A branch is a 41-byte file that holds the ID of one commit. That's it. A pointer.
You have one folder on disk: your working directory. When you run git switch feature-x, Git doesn't copy anything to a new place. It rewrites the files in that one folder to match what feature-x points at. Switch back to main and it rewrites them again. Same folder, different contents.
# proof: a branch is just a file holding one commit id
cat .git/refs/heads/main
# 3f8a1c2e9b... (40 hex chars, one commit)The limit falls straight out of this. One folder, and switching branches swaps what's inside it, means you can only be on one branch at a time. An agent on feature-x and an agent on add-tests pointed at the same folder would be fighting over the same files. The first git switch would yank the ground out from under the other.
A worktree is a second folder on disk
A worktree is the upgrade. One command, and Git gives you a second working folder somewhere else on disk, checked out to a different branch, backed by the same repository and the same commit history. Two checkouts, side by side, both live at once.
git worktree add ../path branch-nameThat single command does three things: creates the folder at ../path, checks out branch-name into it, and registers it with the repo. Concretely:
# add a second folder checked out to an existing branch
git worktree add ../proj-feature feature-x
# or create the branch at the same time with -b
git worktree add ../proj-tests -b add-tests
# list every worktree this repo has
git worktree listNow your main code sits in the original folder and feature-x sits in ../proj-feature, both checked out simultaneously. No stashing, no switching back and forth. There is still only one .git repository underneath. Every worktree shares the same commit history, the same remotes, the same object store. They just have different files on disk at different paths.
How Claude Code uses this to run a fleet
Here is the trick behind the parallel agents. Claude keeps one agent in the main folder, then spawns the others each in their own worktree. Every agent gets an isolated folder on its own branch, so they edit different files at the same time without ever touching each other's directory.
# main folder: agent 0 works here, on main
# spin up a worktree per parallel task
git worktree add ../proj-agent-1 -b agent-1-feature
git worktree add ../proj-agent-2 -b agent-2-refactor
git worktree add ../proj-agent-3 -b agent-3-testsAgent 1 builds a feature in ../proj-agent-1. Agent 2 refactors in ../proj-agent-2. Agent 3 writes tests in ../proj-agent-3. Four agents, four folders, four branches, one repo. That isolation is what lets Claude run a fleet on one codebase without melting it. Plain branches can't do this, because plain branches share one folder.
The exact setup I use
I keep worktrees as siblings of the main repo, one per agent task, with a branch name that matches what the agent is doing. Sibling folders keep paths short and keep the worktrees out of the main checkout so Git tooling and file watchers don't trip over them.
# from inside the main repo
my-project/ # main checkout, on main
git worktree add ../my-project-feature -b feat/payments
git worktree add ../my-project-bugfix -b fix/login-redirect
# open a Claude Code session in each
cd ../my-project-feature # one agent owns the feature
cd ../my-project-bugfix # another owns the bugfixEach agent commits and pushes its own branch independently. When a branch is done and reviewed, I merge it into main from the main folder, then tear the worktree down. The branches never collide on disk because they were never in the same folder.
The honest catch
Worktrees are not magic, and the no-code crowd skips the part that matters. Three things to know before you lean on this:
Shared repo means shared merges. The worktrees isolate the folders, not the history. If two agents edit the same file on two branches, Git still makes you merge that file by hand when you bring the branches together. Parallel buys you speed, not zero conflicts. Split work along file boundaries where you can, so agents rarely touch the same file.
Every worktree is a real folder, so dependencies get reinstalled. A worktree is a full checkout on disk, not a symlink. Things that live in the working directory rather than the repo, like node_modules, .venv, or a build cache, do not come along. Each new worktree needs its own npm install (or equivalent). Three agent worktrees on a Node project means three node_modules trees on your disk.
Clean up when you're done. Worktrees stick around until you remove them, and stale ones clutter git worktree list and your disk. Remove a worktree with one command:
# remove a worktree when its work is merged
git worktree remove ../my-project-feature
# if the folder is already gone, prune the stale reference
git worktree pruneRule of thumb: one worktree per agent task, on a branch named for the task, as a sibling folder. Reinstall deps per tree, merge by hand when files overlap, and run
git worktree removethe moment a branch lands. That's the entire setup.