Two Terminals, One Pot of Tea: Parallel Claude Code with Git Worktrees A developer combined Git worktrees with parallel Claude Code sessions to work on multiple features simultaneously without merge conflicts. By creating separate worktrees for each feature branch, they enabled independent AI-assisted development in isolated directories, avoiding the need for stashing or sequential workflows. The approach was tested on the peektea TUI file browser project, where two unrelated features were developed in parallel. I had a lot of work to get through, and for once I didn't want to crawl through it one ticket at a time. I knew Claude Code could run a few sessions in parallel, so my first thought was just to turn a couple of agents loose on different things at once. But then I hit my actual hangup: I don't merge code I haven't read. I like going through diffs properly, lately with git-lrc https://github.com/HexmosTech/git-lrc . So the question became, how do I let a bunch of sessions work at the same time without all their changes piling up into one unreviewable mess on a single branch? Because in a single checkout, everything is sequential by definition: work → review → commit → push → cut a new branch → start the whole thing over. One task can't start until the last one is done. And if something interrupts you halfway through, you're back to the old muscle memory: stash, checkout main, branch, fix, switch back, pop the stash, and hope nothing re-ran a build while you weren't looking. Then I remembered git worktrees. And it turned out Claude had a genuinely good doc on them. The idea clicked right away. One folder per task, each on its own branch, each with its own Claude session. My one rule was dead simple: branch name = session name = whatever it's for. That way I could jump to any of them, or come back hours later, and not have to squint to remember which was which. So I sat down and actually learned it on my little TUI file browser, peektea https://github.com/lovestaco/peektea . Here's the small write-up. Let me pour you a cup xD A normal clone gives you one working directory tied to one branch. A worktree https://git-scm.com/docs/git-worktree is a Both folders share one .git file same history, same remote, but their files are completely independent. Edit, build, or run in one, and the other never even notices. That isolation is the entire point. Claude can be wiring up one feature in Terminal A while you fix something unrelated in Terminal B, and neither session can clobber the other's files. No stashing. No tea spilled. The one rule that decides everything A worktree belongs toexactly one repository, and a branch can live inexactly one worktreeat a time. So the math is simple:one worktree per parallel feature.Two features in peektea → two worktrees → two terminals → two sessions. I created two issues in peektea that may not touch each other, ideal for steeping in parallel: | Feature | Issue | What it is | |---|---|---| A | | y copies the highlighted path, Y copies the file's contents x cuts the entry, v drops it into the current directoryBoth branch off master . Both add keybindings, but they live in different code paths, exactly the kind of "could be one PR each, done at the same time" work worktrees were made for. My main checkout lives at ~/pers/peektea . The worktrees will sit right next to it. You run git worktree add from any existing checkout of the repo, you don't have to be "inside" a worktree to make one. The command creates the folder and the branch in a single shot and wires them together. Terminal A · the copy-shortcuts feature cd ~/pers/peektea git fetch origin master refresh the base new folder + new branch, off master git worktree add \ -b copy-path-and-contents \ ~/pers/peektea-copy \ master cd ~/pers/peektea-copy claude fresh session, right here Terminal B · the move-file feature cd ~/pers/peektea git worktree add \ -b move-to-dir \ ~/pers/peektea-move \ master cd ~/pers/peektea-move claude second session, fully independent That's it. Two checkouts, two branches, two Claude sessions and your original ~/pers/peektea is sitting there untouched, exactly how you left it. Inside each session, run /rename to match the branch. Costs a second now, saves you squinting at an unlabelled session list later: /rename copy-path-and-contents Because claude --resume only lists sessions for the folder you launch it from, the branch-named one is the obvious cup waiting in each worktree: cd ~/pers/peektea-move claude --resume pick the named session or, fastest: claude --continue reopen the most recent one here Switching is just… switching terminals. The sessions don't share state, so there's nothing to reconcile. status and diff work exactly how you already know them, and you can peek at either tree from anywhere with git -C instead of cd -ing around: inside a worktree git status git diff unstaged git diff --staged staged or peek without leaving your current folder git -C ~/pers/peektea-move status Here's the part I genuinely didn't appreciate until I tried it. Because each worktree is its branch , a commit can only ever land on that branch. The classic "ugh, I committed the bugfix onto the feature branch" mistake isn't something you have to be careful about, it's structurally impossible . Visually, the two features steep in their own cups and only meet when you merge: Committing and pushing is the usual ceremony, the first push just sets the upstream: cd ~/pers/peektea-copy git add -A git commit -m "feat: y/Y to copy path and file contents 2 " git push -u origin copy-path-and-contents first push sets upstream This is where a Go TUI is a delight compared to a web stack. peektea is a single binary, no frontend, no backend, no ports to fight over. You build inside the worktree and run the local binary, because you're testing your edited code, not the main tree's: cd ~/pers/peektea-move make build builds ./peektea right here in the worktree ./peektea run the version with YOUR changes Want live reload while you iterate with Claude? make start rebuilds on every .go save: make start air watches and rebuilds ./peektea And because there's no server, you can happily run make start in both worktrees at once, no port collision, no proxy juggling, nothing to stop and restart. The TUI just reads the terminal it's launched in. Anyways. When a feature's merged, remove its worktree from a different checkout, not from inside the folder you're deleting: cd ~/pers/peektea git worktree list see them all git worktree remove ~/pers/peektea-move refuses if the worktree is dirty; add --force to discard changes git branch -d move-to-dir -D to force-delete if unmerged git worktree prune tidy up stale metadata Note that git worktree remove leaves the branch behind on purpose , so you can't accidentally throw away unmerged work by deleting a folder. Branches get deleted separately, deliberately. Polite to the last drop. --worktree …" It does claude --worktree feature-x spins up a worktree and drops you straight into a session, perfect for a quick spike. For real tickets I still reach for the manual git worktree add , for two reasons: worktree-feature-x , not the exact name I want copy-path-and-contents . origin/HEAD , which here is master anyway, but on repos where your trunk is dev or develop , that's the wrong base.When the branch name and base both need to be exactly right, plain git worktree add wins. For a throwaway experiment, --worktree is the faster pour. | Command | What it does | |---|---| git worktree add -b