JUL 14, 2026 · In AI & Automation

Parallel Work with Claude Code

How a non-engineer PM came to understand git worktrees while running multiple Claude Code sessions at once. The core rule is "1 session = 1 worktree = 1 working branch = 1 PR."

Yongjin Jin
Vintage engraving-style illustration of a peacock, a swan, and a hummingbird among flowers and foliage

As a PM who is not an engineer, I used AI coding tools for a long time without really understanding git. My pattern was simple: create a branch, work on one thing, open a PR, and ship the code to GitHub. When building web apps, I would run roughly two or three sessions at once, scoping them by gut feeling so they wouldn't overlap, and whenever the source code conflicted, Claude Code resolved it on the spot. When developing an iOS app, I had no feel for it at all, so I worked on a single task, finished it, and only then moved on to the next.

Recently, though, while testing a YouTube video production pipeline, I wanted to run several tasks at the same time. When I fired up many sessions at once (say, five or six), Claude Code raised a series of warnings about code management, and I realized it was time to actually study the concept of worktrees. I had heard before that Boris Cherny, who created Claude Code, works in parallel using git worktrees, but I had never properly understood what that meant.

1. Git state is per-folder, not per-session

Opening multiple Claude Code sessions doesn't mean git distinguishes between them. Claude Code is a separate tool from git, so if sessions are looking at the same folder, they all share the same working space. (More precisely, the working files, the staging area, and the current position (HEAD) belong to each worktree (folder) separately, but branches and commit history live in one shared repository.)

So when one session saves (commits) and sweeps everything in with git add, it also commits code that another session was still working on in the same folder. This actually happened to me: commits made this way ended up mixing in changes from other sessions.

The more fundamental risk actually exists even before the commit stage. If two sessions edit the same file at the same time, they can overwrite each other's changes before anything is committed. Either way, sharing a single folder is itself the risk.

2. Separating workspaces with worktrees

The problem above ultimately comes from multiple sessions looking at one folder. The way to approach it is to give each session its own folder, and this is where git worktrees come in. A worktree is a working space that lays out one more copy of the same project in a separate folder.

One thing worth knowing: worktrees share only the work history (git history), while the actual files are copied per folder, so environment files like .env have to be brought over to each new folder yourself. Claude Code has a feature called .worktreeinclude that copies these automatically. You write patterns in .gitignore syntax, and only files that match a pattern and are gitignored get copied. See the official docs for the details.

Even with that bit of hassle, it's far lighter than cloning the whole repository multiple times, and the real advantage is that each folder can work independently on its own branch.

The core rule I've come to understand for parallel work in Claude Code is "1 session = 1 worktree = 1 working branch = 1 PR." In other words, one Claude Code session produces one deliverable (a PR) on its own dedicated branch in its own dedicated folder. Even with five or six sessions running at once, as long as each works in a different folder, their edits never mix in the same working space.

Claude Code supports a tool called EnterWorktree for this. Calling it creates a separate folder and a new branch. For example, if you ask a session to "work in a worktree," Claude Code calls the EnterWorktree tool and sets up a new folder and branch for you. There are default naming rules here. If you create a worktree named render-fix, Claude Code creates the folder .claude/worktrees/render-fix/ by default, and the branch gets a worktree- prefix: worktree-render-fix. So the folder keeps exactly the name you gave, while the branch name gets the worktree- prefix by default (this behavior is configurable).

If you were running two sessions in parallel, the opening prompts might look like this:

  • Session A (say, rendering performance): "I'll work in a worktree. Name it render-fix. Find out why rendering is slow and improve it."
  • Session B (say, a stock-image reuse pipeline), in another session window: "Create a worktree called stock-lib and get started. Set up a structure for reusing stock images across episodes."

The only thing that matters is giving each session a different name (like render-fix and stock-lib). Strictly speaking, what must not collide is the branch rather than the folder name (two worktrees generally can't check out the same branch at once), but giving different names naturally solves both.

Normally, Claude Code creates the worktree based on the remote repository's default branch (origin/HEAD, usually main or master). In fact, the default behavior itself starts from the remote: it attempts a fetch internally, and if there is no remote or the fetch fails, it falls back to the current local HEAD.

So the request you sometimes see, "fetch first, then create the worktree," isn't wrong, but it may just be double-checking a safety mechanism that's already part of the default behavior. Conversely, if you want to create a worktree based on unfinished work on your current local branch, you can set worktree.baseRef to "head" (this setting accepts only two values, "fresh" or "head"). For typical parallel work, though, starting from the remote default branch, as the default does, seems safer.

Beyond this, I separate worktrees per session, but there are also cases where a single session splits worktrees per subagent to work in parallel within one session.

3. The confusing moments when running sessions in parallel

Running Claude Code sessions A and B at the same time, there are a couple of moments that can get confusing. One is when starting work (creating each worktree), and the other is when finishing (merging each PR). In both cases the worry is whether sessions A and B will interfere with each other, and most of it Claude Code resolves automatically.

(1) Starting work: separate worktrees don't collide

"Session A already created a worktree. If session B calls EnterWorktree too, won't they collide?" → As long as the names are different, they won't.

Session A → EnterWorktree(name="render-fix")  → workspace 1
Session B → EnterWorktree(name="stock-lib")   → workspace 2

Each session works in a physically different folder, so they're safe from collisions. The thing to watch instead is that a session working directly in the main folder without a worktree is the risk. So every working session stays inside its own worktree, and the main folder is kept view-only.

(2) Finishing work: when the code session B was looking at has fallen behind

This is the most common situation. Session A finishes first and merges its PR, which updates the remote repository's default branch (usually main or master). But session B started its work from the default branch as it existed before A's work. What happens when B's PR gets merged in this state confused me the most.

The short answer: B having started from older source code is, by itself, mostly a non-issue. If the PR is mergeable, GitHub combines B's changes on top of the current, latest default branch at the moment of merging. What git actively blocks are the situations that are hard to combine automatically: both sides touched the same part at the same time, or one side deleted a file the other side modified. Broken into cases:

Case 1. A and B changed different files (most of the time)

If the PR screen says "no conflicts," you can usually just merge. GitHub automatically combines A's changes and B's changes on top of the current latest base branch. One caveat: "no conflict" means git found no text-level conflicts. It is not a guarantee that the code is logically correct. So before merging, separately confirm that tests pass and the feature behaves as intended.

Case 2. A and B changed the same part (a conflict)

Here GitHub blocks the automatic merge. If you ask session B to "bring the latest default branch into my working branch and clean up the conflicts," Claude Code pulls the latest code, merges it, pushes again, and refreshes the PR. I never have to resolve the conflicting code by hand.

That said, as a non-engineer, I used to instruct "keep both sides no matter what" early on, and often got broken results back. These days I try a prompt like this:

"Merge the two changes into one naturally, preserving the intent of both. Wherever a judgment call is needed along the way, explain how you merged it (or plan to) in plain language that someone who can't read code can understand. After merging, test that both features actually work, and fix anything that broke."

To sum up: when starting, different worktree names keep you safe; when finishing, "the code being behind" is handled by GitHub on its own; and the moment a human (or an AI tool) steps in is when there's an actual conflict.

4. Cleaning up

Once a PR is merged, it's time to clean up the worktree and branch that are no longer needed. Claude Code can tidy up the worktree a session created via the ExitWorktree tool. You can ask the session like this:

"The PR is merged. Please clean up this worktree and branch."

ExitWorktree ends the worktree session and returns the working location to the original main folder. Note that it only operates on worktrees created by this session's EnterWorktree. It won't touch worktrees created manually or by previous sessions.

How cleanup proceeds depends on the worktree's current state. If there are no uncommitted changes, no untracked files, and no new commits, the worktree and branch are removed automatically. If any of these remain, it always asks keep/remove instead of deleting automatically. Also, if you've given the session a name, it won't auto-delete even with no changes, and instead confirms keep/remove so you can reuse it later.

Choosing remove deletes the local worktree directory together with its local branch. Any remaining changes or commits can be discarded along the way, so it's safest to clean up only after confirming the PR has actually been merged. Choosing keep leaves the worktree and branch as they are.

In plain git you'd run this as two separate steps, "delete the folder (git worktree remove)" and "delete the branch (git branch -d)", but choosing remove in Claude Code handles both together. Note that this cleans up the local folder and local branch on your machine. The remote branch on GitHub is separate: press GitHub's "Delete branch" button when merging the PR, or separately ask the Claude Code session to delete the remote branch too.