Git worktrees in Claude Code: keep main clean, run agents in parallel
Research runs for months, most trials fail, and parallel agents on the same working tree step on each other's files. One flag — claude -w <name> — fixes both problems at once.
The problem
An empirical project is not a one-shot game. A single classification task, a single regression, a single data pull can stretch across months, and most attempts along the way fail. Out of seven trials, maybe two survive into the polished paper.
The naive workflow is to keep everything on main and dump every session's log into a single progress.md. That holds up for a week. By session fifteen, progress.md is a graveyard of abandoned ideas — and Claude Code re-reads it on every new session. Old, dead context pollutes the next decision: the model keeps referencing approaches you already discarded, suggests fixes for problems that no longer exist, and drifts back toward work you have already ruled out.
There is a second problem. Claude Code is at its best when you run agents in parallel — one training a classifier while another cleans the panel while a third drafts the appendix. But three agents sharing the same working tree means three agents writing to the same files. Overwritten edits, lost work, and conflicts that only surface after both sides have already drifted.
The fix: one worktree per exploration
A git worktree is exactly what it sounds like: a separate working copy of the same repository, on a separate branch. Same .git under the hood, different files on disk. Claude Code ships first-class support for them behind one flag:
claude -w text-llm
That creates a fresh worktree at .claude/worktrees/text-llm on a new branch, launches Claude inside it, and leaves main untouched. Long form: claude --worktree text-llm. The name is optional — omit it and Claude picks one for you.
Inside the worktree, try things. If the trial wins, merge the branch back to main. If it loses, delete the worktree with git worktree remove text-llm and the failed history is gone — main never saw it, and no future session re-reads it.
A worked example: text classification
I am classifying sentiment toward immigration in parliamentary speeches. I want to compare a modern LLM-based classifier with a traditional keyword/dictionary approach — two separate pipelines, two validation runs — and I want to run both at the same time without them colliding. Two terminals, two Claudes, one command each:
claude -w llm-classify
claude -w keyword-classify
Now each agent has its own working tree. The LLM agent writes prompts, annotates a validation set, and calls the model. The keyword agent builds a dictionary, runs regex, and computes precision/recall. Their files live at different paths on disk — .claude/worktrees/llm-classify/ and .claude/worktrees/keyword-classify/ — so they cannot overwrite each other. No git stash dance is needed to switch between them.
A week later the LLM approach wins on the held-out set. I merge llm-classify into main and remove the keyword worktree. The paper — and every future Claude session on main — sees only the classifier I kept. The dead branch does not hang around in progress.md whispering about keyword thresholds I no longer care about.
When to merge, when to discard
- Merge when the trial settles a question: a feature that sticks, a cleaning step that survives, a model that beats the baseline. Add a short note in
main'sprogress.md— what you decided and why — and drop the detailed exploration log along with the branch history. - Discard when the trial answered "no." Delete the worktree; keep one sentence in
main'sprogress.mdnoting you tried X and it did not work, so you do not re-try it six months later.
Either way, main stays a record of load-bearing decisions rather than a graveyard of every false start. That is what keeps Claude Code sharp over the long months of a real project.
Source
Documented under the --worktree flag in Claude Code's CLI reference. Related: Dispatch #9 on Compound Engineering, for the broader brainstorm → plan → work → review loop this slots into.