Claude Code · Advanced/Lesson 01 of 07~5 min

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.

The Third Way engineering team||Verified against Claude Code v2.1.285 (stable), October 2026

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.

↳What the two checkouts share
Shared through the one .gitFresh in each worktree
Commits and branchesUncommitted edits
The repository’s historyInstalled dependencies
Worktree sessions also read the main checkout’s shared settingsGitignored files, such as .env
Each worktree is a fresh checkout. A .worktreeinclude file at the repository root copies listed gitignored files into new worktrees — list only what the project needs, since every worktree gets its own copy of each secret.

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.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.

↳Check yourself
Q1

What does worktree isolation not stop?

  1. AAn edit to a file under .claude/worktrees/<name>/
  2. BA file edit that targets the main checkout
  3. CA git -C command pointed at the main checkout
→Check your answer
Answer: A

Isolation is directional: the session owns its own worktree and is blocked from touching the main checkout, not from working in its own folder.

Q2

Which of these is fresh in each worktree rather than shared?

  1. ACommits and branches
  2. BUncommitted edits and installed dependencies
  3. CThe repository’s history
→Check your answer
Answer: B

All checkouts share the one .git. Uncommitted edits, installed dependencies and gitignored files exist per worktree — each is a fresh checkout.

Q3

At /exit, a worktree whose branch has new commits…

  1. AIs removed automatically
  2. BIs kept automatically
  3. CPrompts keep or remove — and remove deletes the branch and any unmerged work
→Check your answer
Answer: C

Claude Code asks. Removing deletes the folder and the branch together, so merge before you remove; keep is for resuming later.

The Third Way engineering team
Delivery engineering
Work with us