Parallel sessions with worktrees
One developer, one repository, two sessions working at once — without either seeing the other’s half-finished edits. Git worktrees are the mechanism, and Claude Code has a flag for them.
01The goal
Run two Claude Code sessions at the same time, each in its own git worktree on its own branch, and land both branches back in your main checkout with git merge.
02The idea
A git worktree is a second working folder, on its own branch, that shares the repository’s history. Claude Code speaks worktrees natively: claude --worktree docs-pass (or the short -w docs-pass) creates .claude/worktrees/docs-pass/ on a new branch called worktree-docs-pass and starts the session inside it.
Isolation is enforced, not requested. Claude Code blocks a worktree session’s file-editing tools from touching your main checkout, blocks commands whose working directory is the main checkout, and blocks git commands that reach into it — a git -C from inside the worktree does not get through. That is the property that makes parallelism safe: neither session can see, edit or corrupt the other’s uncommitted work.
| Shared through the one .git | Fresh in each worktree |
|---|---|
| Commits and branches | Uncommitted edits |
| The repository’s history | Installed dependencies |
| Worktree sessions also read the main checkout’s shared settings | Gitignored files, such as .env |
The work comes back through git: each session commits on its branch, you merge the branches from the main checkout, then remove the worktrees. One base-branch detail decides whether the merges are painless: a new worktree branches from the remote’s default branch, not from your local HEAD. Work you have not pushed is not in it. (The worktree.baseRef setting can change this to head if you work without a remote.)
03The walkthrough
Three terminals at the repository root: two for sessions, one for git. Your repo should be clean, on its default branch, pushed.
- 01Ignore the worktree folder, then commit and push the rule — otherwise worktree contents show up as untracked files in your main checkout: append .claude/worktrees/ to .gitignore, commit, push.
- 02Terminal 1: claude --worktree docs-pass, and give it a small documentation task — "Tidy the wording of the README’s first section, then wait for me before you commit." Asking it to wait keeps the commit step yours.
- 03Terminal 2: claude -w test-pass, and give it a test task — "This worktree is a fresh checkout: install the dependencies, then add one missing test for a small exported function and run the tests. Wait for me before you commit." It installs dependencies in its own folder first — that is the fresh-checkout property in action.
- 04Terminal 3, while both sessions wait: git worktree list shows all three checkouts; git status --short in the main checkout shows neither session’s edits; git -C .claude/worktrees/docs-pass status --short shows only that session’s. Now tell each session to commit.
- 05Merge both branches from the main checkout — git merge worktree-docs-pass, then git merge worktree-test-pass. The first typically fast-forwards; the second makes a merge commit. Run these yourself: Claude Code blocks a worktree session’s git commands that reach into the main checkout. If both tasks touched the same lines, resolve the conflict or start a session in the main checkout and ask it to.
- 06In each session, /exit. Because the worktree’s branch has a new commit, Claude Code asks keep or remove: choose remove — and know that removing deletes the folder, the branch, and any work in them you have not merged. Merge first; keep only what you want to resume later.
04Your turn
Pick two small changes in your repository that touch different files — a fix in one module, a missing test for another. Make each in its own worktree session with both running at the same time, merge both branches, remove both worktrees, and end with your tests passing. If the work the tasks should build on is not pushed to the remote’s default branch yet, push it first — or set worktree.baseRef to head in your personal settings so new worktrees start from local HEAD.
Two traps to respect. A "Yes, and don’t ask again" answer inside a worktree session saves its rule to the main checkout’s .claude/settings.local.json, where it applies to every future session in the repository and outlives the worktree — approve only commands you would allow everywhere. And two sessions working at once multiply token usage; give each one small task and exit it once its branch is merged.
What does worktree isolation not stop?
- AAn edit to a file under .claude/worktrees/<name>/
- BA file edit that targets the main checkout
- CA git -C command pointed at the main checkout
→Check your answer
Isolation is directional: the session owns its own worktree and is blocked from touching the main checkout, not from working in its own folder.
Which of these is fresh in each worktree rather than shared?
- ACommits and branches
- BUncommitted edits and installed dependencies
- CThe repository’s history
→Check your answer
All checkouts share the one .git. Uncommitted edits, installed dependencies and gitignored files exist per worktree — each is a fresh checkout.
At /exit, a worktree whose branch has new commits…
- AIs removed automatically
- BIs kept automatically
- CPrompts keep or remove — and remove deletes the branch and any unmerged work
→Check your answer
Claude Code asks. Removing deletes the folder and the branch together, so merge before you remove; keep is for resuming later.