Claude Code Worktrees: Parallel Development Without Conflicts
Why Your AI Agent Keeps Stepping On Its Own Feet
If you have spent any real time pairing with Claude Code on a non-trivial codebase, you have probably hit this wall: you ask it to fix a bug on one branch, then realize you need it to also draft a feature on another branch, and now you are stuck. You either wait for the first task to finish, or you git stash, switch branches, let Claude work, stash again, switch back, and pop your original changes. Every context switch costs you time, and every stash carries a small risk of losing track of what you were doing.
The problem is not Claude Code. The problem is that a single git checkout can only be in one state at a time. One working directory, one HEAD, one set of files on disk. If you want two independent lines of work happening simultaneously, checkout-based workflows fight you every step of the way.
Git worktrees solve this at the source. Instead of one working directory tied to one branch, you get multiple working directories, each checked out to a different branch, all sharing the same underlying .git repository and object database. Point one Claude Code session at one worktree and a second session at another, and you have two agents working in parallel with zero risk of clobbering each other's uncommitted changes. No stashing, no switching, no waiting.
This article walks through what worktrees actually are, how to set them up for Claude Code specifically, and a real parallel-agent workflow you can start using today.
What Git Worktrees Actually Are
A worktree is a linked working directory that shares the same .git object store as your main repository, but has its own independent file tree and its own checked-out branch. Git has supported this since version 2.5, but most developers never touch it because normal single-threaded development does not need it.
Here is the mental model. Your main repository lives at, say, ~/projects/my-app. That directory has a .git folder containing every commit, branch, and object in the project's history. Normally you only ever look at that history through one lens: whatever branch is currently checked out in that one folder.
A worktree adds a second (or third, or tenth) lens onto the exact same history, living in a completely separate folder on disk, with its own node_modules, its own build artifacts, its own uncommitted edits. Commit in one worktree and that commit is instantly visible in every other worktree tied to the same repo, because they are all reading from the same object database. You are not cloning the repo three times and burning three times the disk space and three times the npm install time for the shared git history — you are just adding parallel views into it.
This is precisely the property you want when running multiple Claude Code instances. Each agent needs its own untouched file tree so it can edit files, run tests, and leave half-finished work in progress without interfering with a sibling agent doing the same thing somewhere else. Worktrees give you that isolation while keeping everything anchored to one canonical git history, so nothing drifts out of sync the way it can with fully separate clones.
Setting Up Your First Worktree
Let's start with the basic commands. Assume you have a repository checked out at ~/projects/my-app on the main branch.
cd ~/projects/my-app
# Create a new worktree with a new branch, in a sibling directory
git worktree add ../my-app-feature-auth -b feature/auth
# Create a worktree from an existing branch instead
git worktree add ../my-app-hotfix hotfix/payment-bug
# List every worktree currently attached to this repo
git worktree listRunning git worktree list gives you output like this:
/Users/pramod/projects/my-app a1b2c3d [main]
/Users/pramod/projects/my-app-feature-auth d4e5f6a [feature/auth]
/Users/pramod/projects/my-app-hotfix 7g8h9i0 [hotfix/payment-bug]Each row is a fully independent directory. You can cd into my-app-feature-auth, run npm install, edit files, run your test suite, and commit — all without touching a single file inside my-app or my-app-hotfix. When you are done with a worktree, remove it cleanly rather than just deleting the folder:
# Preferred: lets git clean up its internal bookkeeping
git worktree remove ../my-app-feature-auth
# If the worktree has uncommitted changes you're okay discarding
git worktree remove --force ../my-app-feature-auth
# Prune stale worktree metadata after manual folder deletion
git worktree pruneOne detail that trips people up: you cannot check out the same branch in two worktrees simultaneously. Git will refuse, because two working directories pointed at the same branch would create ambiguity about which one's changes are "the" state of that branch. That is a feature, not a bug — it forces you to give every parallel task its own branch, which is exactly the discipline you want when running multiple agents anyway.
It also helps to decide up front where your worktrees live on disk. Some teams keep them as siblings of the main repo, as shown above. Others prefer a dedicated parent folder so the project directory itself does not get cluttered:
mkdir -p ~/worktrees/my-app
git worktree add ~/worktrees/my-app/feature-auth -b feature/auth
git worktree add ~/worktrees/my-app/hotfix-payment hotfix/payment-bugEither layout works fine with Claude Code — what matters is that each worktree has its own absolute path so you can point a terminal, an editor window, or a Claude Code session at it without ambiguity. Pick one convention and stick to it, since inconsistent naming is the single biggest source of confusion once you have more than two or three worktrees open at once.
Why Worktrees Are a Natural Fit for Claude Code
Claude Code sessions are inherently stateful within a working directory. When you start a session, Claude reads your files, tracks edits, runs commands, and builds up context about what it has done so far. If you run two Claude Code sessions against the same checkout, they will race on file writes, confuse each other's test runs, and potentially produce a working tree that is in neither agent's expected state.
Worktrees remove that hazard entirely by giving each Claude Code session its own physical directory. From Claude's perspective, each worktree looks like a completely ordinary, single-branch repository. There is no special worktree-awareness Claude needs — it just operates on the files in front of it, unaware that three other directories exist elsewhere on disk pointing at the same history.
This matters more than it sounds like on paper. Consider the difference between these two workflows:
- Without worktrees: Claude is mid-way through refactoring a module on
feature/auth. You need a hotfix onmainright now. You either interrupt Claude's session, stash its half-done work, switch, fix, switch back, and hope the stash pops cleanly — or you just wait. - With worktrees: You open a second terminal,
cdinto a fresh worktree already onmain, and start a second Claude Code session there. Thefeature/authworktree and its Claude session are completely untouched. Both agents run to completion independently, and you merge each branch back intomainon your own schedule.
The second workflow is not just faster — it changes what kinds of tasks you are willing to hand off to an agent in the first place. If spinning up a parallel, isolated workspace is a ten-second git worktree add, you stop batching tasks sequentially "to be safe" and start treating Claude Code more like a team of contractors who each get their own desk.
A Practical Parallel-Agent Workflow
Here is a concrete setup for running two or three Claude Code agents on unrelated tasks at once, using a real project layout.
# Starting point: your main repo
cd ~/projects/my-app
git status
# On branch main, working tree clean
# Spin up a worktree for a new feature
git worktree add ../my-app-search -b feature/search-improvements
# Spin up a second worktree for an unrelated bug fix
git worktree add ../my-app-fix-cart -b fix/cart-total-rounding
# Spin up a third worktree to try an experimental refactor
git worktree add ../my-app-experiment -b experiment/repo-layer-refactorNow open three terminal tabs (or three panes in tmux, or three windows — whatever your setup is) and launch Claude Code in each directory:
# Terminal 1
cd ~/projects/my-app-search
claude
# Terminal 2
cd ~/projects/my-app-fix-cart
claude
# Terminal 3
cd ~/projects/my-app-experiment
claudeEach session gets a prompt scoped to its own task. In terminal 1 you might say "implement fuzzy search on the product catalog using the existing Postgres full-text index." In terminal 2, "fix the rounding bug in cart totals reported in issue 482." In terminal 3, "try refactoring the repository layer to use the new query builder pattern, and report back on what breaks."
Because each Claude Code instance is confined to its own worktree, none of them can see or accidentally modify the others' in-progress files. You can let the experimental refactor run long and messy in terminal 3 without any risk that it destabilizes the cart bugfix you need to ship today. When one agent finishes, you review its diff, run its tests, and merge:
cd ~/projects/my-app-fix-cart
npm test
git add -A
git commit -m "fix: correct rounding in cart total calculation"
cd ~/projects/my-app
git merge fix/cart-total-rounding
git worktree remove ../my-app-fix-cart
git branch -d fix/cart-total-roundingRepeat for the other two worktrees whenever they are ready, in whatever order makes sense. Nothing about this workflow requires all three tasks to finish at the same time, which is the entire point — you have decoupled task completion from working-directory availability.
Handling Shared Dependencies and Environment Files
A common snag with worktrees is that things like node_modules, .env files, and build caches are not tracked by git, so a fresh worktree starts without them. You will need to handle this deliberately, or every new worktree wastes minutes reinstalling dependencies before Claude Code can even run your test suite.
A few approaches, roughly in order of how much project setup they require:
- Symlink shared, immutable directories. If your
node_modulesis identical across branches (i.e., you are not testing apackage.jsonchange), symlink it instead of reinstalling:
cd ~/projects/my-app-search
ln -s ../my-app/node_modules ./node_modulesThis is fast but dangerous if the two branches actually need different dependency trees — only do this when you know the branches share a lockfile.
- Copy environment files explicitly.
.envfiles are gitignored for good reason, so every new worktree needs its own copy:
cp ~/projects/my-app/.env ~/projects/my-app-search/.env- Use a setup script. The cleanest long-term fix is a small script that every new worktree runs once, so you are not manually repeating these steps:
#!/usr/bin/env bash
# scripts/setup-worktree.sh
set -e
TARGET_DIR="$1"
if [ -z "$TARGET_DIR" ]; then
echo "Usage: ./scripts/setup-worktree.sh <path-to-worktree>"
exit 1
fi
cp .env "$TARGET_DIR/.env"
cp .env.local "$TARGET_DIR/.env.local" 2>/dev/null || true
cd "$TARGET_DIR"
npm install
echo "Worktree at $TARGET_DIR is ready."Run it right after creating each new worktree:
git worktree add ../my-app-search -b feature/search-improvements
./scripts/setup-worktree.sh ../my-app-searchThis one habit — a repeatable setup script — is what separates worktrees as an occasional trick from worktrees as a genuine daily workflow. Once the friction of provisioning a new worktree drops to a single command, you will reach for parallel Claude Code sessions far more often.
Avoiding Merge Conflicts By Design, Not Luck
Worktrees do not make merge conflicts disappear. Two branches that both touch the same lines of the same file will still conflict when you merge them, no matter how isolated their working directories were while the edits happened. What worktrees eliminate is the *accidental* conflict — the kind caused by two processes editing the same files on disk at the same time, or by a stash getting popped onto the wrong branch, or by a half-finished edit surviving a branch switch it should not have survived.
To keep real merge conflicts rare as well, scope each parallel Claude Code task to a distinct area of the codebase whenever you can. If one agent is working on the checkout flow and another is working on the admin dashboard, they are very unlikely to touch the same files, and the worktree isolation guarantees they cannot interfere with each other even during the work itself. If you know two tasks will touch overlapping files — say, both need to modify the same shared utility module — it is often better to run them sequentially rather than in parallel, or to have one agent finish and merge before starting the second.
When conflicts do happen, resolve them the same way you always would, from your main repository, after both branches have been merged in:
cd ~/projects/my-app
git merge feature/search-improvements
git merge experiment/repo-layer-refactor
# CONFLICT (content): Merge conflict in src/lib/repository.tsAt this point, worktrees have already done their job. You are debugging a legitimate conflict between two finished pieces of work, not untangling a mess caused by two processes racing on the same file tree. That distinction is worth a lot when you are running Claude Code agents unattended for stretches of time.
Cleaning Up After Yourself
Worktrees accumulate. If you adopt this workflow seriously, you will end up creating and discarding dozens of them over a few weeks, and stale entries left behind by manual folder deletion will start cluttering git worktree list. Build a habit of cleaning up as you go.
# See everything currently registered
git worktree list
# Remove a worktree you're done with (fails if it has uncommitted changes)
git worktree remove ../my-app-search
# Force removal, discarding any uncommitted changes in that worktree
git worktree remove --force ../my-app-experiment
# If you deleted a worktree folder manually instead of using `remove`,
# clean up the leftover metadata
git worktree prune
# Also delete the branch once it's merged and the worktree is gone
git branch -d feature/search-improvementsIt is worth scripting this cleanup too, especially the combination of removing a worktree and deleting its branch once merged, since doing both together is the common case:
#!/usr/bin/env bash
# scripts/finish-worktree.sh
set -e
BRANCH="$1"
WORKTREE_PATH="$2"
git worktree remove "$WORKTREE_PATH"
git branch -d "$BRANCH"
echo "Cleaned up worktree $WORKTREE_PATH and branch $BRANCH."A clean git worktree list is a good signal that your parallel-agent workflow is under control rather than sprawling. If you notice worktrees piling up for branches that were merged weeks ago, that is a sign to tighten the loop between "Claude finishes a task" and "you review, merge, and clean up."
Scaling to More Than a Handful of Agents
Everything above works well for two or three simultaneous Claude Code sessions, which is the sweet spot for most individual developers — enough to keep a feature, a bugfix, and an experiment moving at once without losing track of what each one is doing. If you are coordinating a larger number of parallel tasks, a few extra habits help.
Name your worktree directories and branches with a consistent convention so git worktree list stays readable at a glance — something like <project>-<ticket-id> rather than free-form names. Keep a lightweight running note (even a plain text file) of which terminal or tmux pane maps to which worktree and which task you gave Claude in it, since after the fourth or fifth parallel session it becomes easy to forget which agent is doing what. And resist the urge to let worktrees live forever "just in case" — a worktree that has been open for two weeks with no commits is almost always either finished-and-forgotten or abandoned, and either way it deserves a decision, not indefinite postponement.
None of this requires special tooling beyond git itself and whatever terminal multiplexer you already prefer. The workflow scales by discipline, not by infrastructure.
It is also worth deciding, per task, whether parallelism actually earns its keep. Not every piece of work benefits from an isolated worktree and a dedicated Claude Code session. A five-line typo fix does not need its own branch, its own terminal, and its own agent — that is pure overhead. Reach for a worktree when the task is substantial enough to run unattended for a while, when you genuinely need to keep working on something else in the meantime, or when the change is risky enough that you want it fully isolated from your main working tree until it proves itself. Used selectively like this, worktrees stay a productivity multiplier instead of becoming their own source of overhead.
Getting Comfortable With the Workflow
The learning curve here is genuinely small. If you already understand branches, worktrees are just "branches you can look at simultaneously from different folders." The commands are few — add, list, remove, prune — and the mental model of "isolated file tree, shared git history" is the only real concept to internalize. Most developers who try this workflow for a week do not go back to single-checkout, stash-and-switch development, because the cost of context-switching between tasks drops to nearly zero.
For Claude Code specifically, worktrees are close to a required tool once you start running more than one agent session regularly. They turn "I have three things to do and one terminal" from a scheduling problem into a non-problem, and they do it using a git feature that has existed for a decade, with no new dependencies, no new services, and no new failure modes beyond the ones git already handles well.
If you want to go deeper on git fundamentals, branching strategies, and how to structure real projects so that Claude Code can work on them effectively — including hands-on modules on exactly this kind of agentic parallel-development workflow — check out the Claude Code Tutorial for Beginners course on teachyou.ai. It walks through the tool from first install to advanced multi-agent workflows like the one covered here, with real repositories and real tasks rather than toy examples.
AI CodingShip full-stack AI apps at conversation speed — specs, agents, deploys, all from the terminal.
Claude CodeGo from zero to confident with Claude Code, the terminal agent that reads, edits, runs, and verifies real code.
Related reading