Claude Code Worktrees: Isolate Parallel Changes and Merge Them
- claude-code
- agent-ops
- git
Two agents can finish their tasks correctly and still leave you with a broken project. One changes a parser. The other writes examples for the interface it saw before the parser changed. Separate Claude Code worktrees protect their working files from each other; somebody still has to decide whether those files belong together.
That is the part I would plan before launching parallel work. Which commit are they starting from? Which files does each task own? What check accepts the combined result? Another directory helps with editing. It does not answer those questions.
- The base: a remote default branch and your local HEAD may contain different code.
- The environment: ignored files and shared dependencies can bring shared state into separate checkouts.
- The assignment: file ownership matters more than how many agents are running.
- The merge: a clean diff can still describe the wrong behavior.
- The cleanup: the result must survive removal of the checkout and, potentially, its branch.
The Claude Code review covers the broader tool. This is a workflow built from the Git and Claude documentation, with a proposed parser/README exercise. I have not run a fresh native claude --worktree fixture or a deliberate conflict test for this article.
What a worktree separates, and what it shares
A Git worktree is another checkout of the same repository. It has separate working files and an index, and can check out its own branch. Repository history, references and remote configuration remain shared. See the Git worktree documentation.
This lets two tasks edit their own copies of the same tracked file without overwriting each other's uncommitted work. When both changes come back, they may still conflict. The collision has moved to integration, where it is easier to inspect, rather than vanished.
Claude Code adds its launch mode and checks that help its editing tools stay inside the selected checkout. Those checks do not replace permissions, network controls or a sandbox. A separate directory is no reason to give an experiment credentials or production access. The product-specific behavior is in Claude Code worktrees.
I would assign the parser and its tests to one task, and README examples to another. "Improve the project" is too loose. It leaves both agents deciding what to own after they have already started changing it.
Choose the base before naming the tasks
From a Git repository, the native launch command is:
claude --worktree parser-empty-input
Claude creates a checkout under .claude/worktrees/ and a branch named worktree-parser-empty-input. Its documented default base is the repository's default remote branch. That may not contain the unpushed commits in the checkout you are looking at. See creation and base selection.
The worktree.baseRef setting accepts fresh or head: default remote branch or local HEAD, including unpushed commits. It is not an arbitrary branch selector. For another base, create the checkout with Git and start Claude inside it. The base setting reference covers those values.
For a manually managed checkout, the command might be:
git worktree add -b task-docs ../task-docs main
Replace main with the reviewed base you actually want. Git permits a branch to be checked out in only one worktree at a time, so each parallel task needs its own branch. The sibling path is only an example. Git worktree usage explains the constraints.
Record the base commit. A branch name alone is a moving reference, and the default branch can change while an agent works.
If the documentation task needs an interface the parser task has not produced yet, the tasks are dependent. Agree on that interface first or finish the parser before writing its examples. Launching both sooner does not make the second task independent.
A new checkout still needs a usable environment
Ignored files are where a supposedly independent checkout can surprise you. Dependencies, environment files and generated assets may not be there. A task that cannot run the project checks has started too early.
Claude supports .worktreeinclude for copying matching ignored files into new worktrees. Patterns follow gitignore syntax, and only files also ignored by Git qualify. The worktree documentation describes the copying behavior. Keep the list narrow: an environment file can contain both real credentials and a real database endpoint.
For the parser exercise, prepare dummy values and local endpoints. The application will not choose a test database merely because it runs under .claude/worktrees/.
Dependencies need their own decision. Install independently when tasks may change versions or generate code. worktree.symlinkDirectories can instead link directories such as node_modules from the main repository; see the symlink setting. Both links reach the same underlying directory. That is shared state even if the paths look different.
I would only share a dependency tree when it is stable for both tasks, and say so in the assignment. A passing test in one checkout tells you what happened in that checkout, with those dependencies. It does not establish the other environment by association.
Make the handoff reviewable
The proposed exercise needs a tiny parser and a README in a disposable repository. Task A owns the parser and unit tests, including the agreed behavior for empty input. Task B owns the README examples, which must use the agreed interface.
Each task returns its branch, changed paths, the check command and any assumption it could not resolve. If it needs to edit the other task's file, it stops there. The operator can transfer ownership or sequence the change. That is less work than untangling two agents' overlapping guesses afterward.
"Tests pass" is an incomplete handoff. Which test, against which behavior? A parser check can pass while a README command no longer works. The combined check has to cover the relationship between them.
Claude Code subagents covers delegation within a session. Worktrees change the filesystem arrangement; they do not supply a missing task brief. On resume, verify the directory and branch before further edits. The Claude resume guide covers choosing the session, but a remembered task name is not a filesystem check.
Merge the deliverables, not the success messages
Inspect each checkout before integration:
git status --short
git diff
git diff --cached
Status includes untracked files, which may be the output the agent says it produced. The two diffs separate unstaged and staged changes. Review the deliverable and commit it on the task branch. The references for status and diff explain what each view includes.
Then merge one branch on the integration branch and check it before merging the next. Use the repository's normal merge policy. The agent does not need a special history policy just because it wrote the patch.
git merge task-parser
git merge task-docs
These are manually named example branches. A native Claude checkout uses its actual worktree-... name.
A conflict means deciding how the changes should work together, staging that resolution and completing the merge. If abandoning the in-progress merge is appropriate, Git provides git merge --abort. See the merge reference.
The more interesting failure is a clean merge with an outdated example. Git cannot tell that the README teaches yesterday's interface. Read both changes together and run the example against the merged parser. Only then do you have one working deliverable rather than two finished tasks.
Cleanup comes after preservation
Before removing anything, confirm the result was merged or its commits remain on a retained branch. Check for needed untracked files too. Then identify the actual path:
git worktree list
git worktree remove ../task-docs
Git normally refuses to remove a dirty worktree without force. Read that refusal as useful information. There may be something worth keeping. Removing the checkout and deleting its branch are separate operations in a manual Git workflow; the removal reference covers them.
Claude's own exit handling can offer to remove both its worktree and branch, including changes or commits. Read the choice rather than treating cleanup as a harmless final click. Scripted sessions should not be assumed to have gone through that interactive flow. See Claude worktree cleanup.
How does this compare with Codex worktrees?
The Codex desktop app also manages Git worktrees, but defaults to a detached HEAD based on a selected branch. Claude's named CLI worktree creates a branch. In Codex, create a branch when the handoff needs one, such as a pull request. The Codex worktree documentation describes that surface.
Neither product's launch controls remove the integration job. Check the base, keep the result and read the combined change. Parallel work is useful when the assignments can proceed independently; the final behavior still has one owner.
FAQ
What does a Claude Code worktree isolate?
Working files, the index and the task's checked-out branch within one Git repository. History and references are shared. Credentials, services and symlinked dependencies are not automatically isolated.
Do worktrees share dependencies and environment files?
Not automatically. .worktreeinclude can copy ignored files; configured symlinks can share directories. Decide which state should be independent, copied or shared before starting.
How do I merge changes from two worktrees?
Review and commit each result, merge one branch and check it, then merge the second and check their combined behavior. Resolve conflicts according to the intended result, not whichever patch arrived first.
How do I remove a worktree without losing changes?
Preserve needed files and confirm the commits remain on a retained branch or are merged. For a manual checkout, use Git's removal command. Read Claude's cleanup choice because it can remove the branch too.