How do you use git worktrees with Claude Code?
.gitobject database, on its own branch. The Claude Code × worktree workflow is: add a worktree per task, run claude -p inside it, committhe agent’s work, promote the branch to a PR (or land it directly), then remove the worktree. The pre-push hook stays in place the whole time so the agent cannot push on its own.The short answer
git worktree add exists exactly to solve the problem AI agents create at scale: multiple branches checked out at once, each on its own working tree, without copying the repo. The whole agent run lives inside the worktree, and the main checkout where you type code stays untouched. When the run is done you either promote the branch or throw the directory away.
The five-command lifecycle
Memorize these and you are 90% of the way to the workflow:
# 1. Add — new worktree on a new branch, off main
git worktree add ../wt/issue-42 -b kanbots/issue-42 main
# 2. Run — Claude operates only in this directory
cd ../wt/issue-42
claude -p "implement issue #42 from the linked spec" \
--output-format stream-json \
--verbose \
--permission-mode bypassPermissions
# 3. Commit — the agent already did this, but inspect first
git log --oneline
git diff main..HEAD
# 4. Promote — land on a real branch (fast-forward or merge)
cd ../main-checkout
git fetch ./wt/issue-42 kanbots/issue-42:integration/issue-42
git push origin integration/issue-42
gh pr create --base main --head integration/issue-42
# 5. Remove — clean up the worktree (branch stays)
git worktree remove ../wt/issue-42Two details that bite people the first time. First, git worktree add ../foo -b new-branch base creates the branch andthe working tree atomically — if the branch exists already, the command fails. Drop the -b if you want to check out an existing branch instead. Second, git worktree remove is gentle: it refuses to nuke a dirty worktree. Use --force when you mean it, or run git worktree prune to clean up registered worktrees whose directories you already rm -rf’d.
How it actually works under the hood
A bare .git directory has HEAD, index, and worktrees/. The main checkout uses the top-level files; every additional worktree lives in .git/worktrees/<name>/ with its own HEAD, index, and admin files. The object database (.git/objects/) is shared. Refs are shared. Stashes are not shared. Hooks live in .git/hooks/and are shared across worktrees by default — which matters in a second.
That sharing is why worktrees are cheap. A 2 GB monorepo with five worktrees does not cost 10 GB of git data; it costs ~2 GB of objects plus five copies of the working files. That sharing is also why two worktrees on the same branch is forbidden: git worktree add errors out if the target branch is already checked out somewhere else. Two worktrees on different branches is fine.
How KanBots does this specifically
KanBots automates exactly this lifecycle. The dispatcher (@kanbots/dispatcher) is the OSS package that owns the agent runtime. When you click Dispatch on a card, it:
- Computes a worktree path:
<repo>/.kanbots/worktrees/issue-<n>-<runId>. - Computes a branch name:
kanbots/issue-<n>-<runId>. TherunIdis the autoincrement primary key of the row in SQLite, so collisions are impossible. - Runs
git worktree add -b <branch> <path> <baseRef>off the repo’s default branch. - Hardens the worktree: writes a
pre-pushhook that rejects any push of a ref underrefs/heads/kanbots/issue-. Humans can override with--no-verify; agents have no reason to. - Spawns the selected CLI (
claude -porcodex exec) with stream-JSON output against the worktree, parses each line, and forwards events to the UI.
Promotion is an explicit human action. The card shows three buttons after the run lands:
- Branch preview— start the worktree’s dev server (pulled from the configured check commands) and open a URL.
- Promote commit— bring the agent’s commits onto a real branch you choose. Uses a staging area at
.kanbots/promote/so a half-finished promote does not corrupt your checkout. - Open draft PR(GitHub mode only) — pushes the agent branch and opens a PR via the GitHub REST API.
On Discard the dispatcher runs git worktree remove --force and deletes the branch. Nothing leaks outside .kanbots/ except the branch ref itself, which is cheap.
A concrete walkthrough by hand
If you want to run the workflow without KanBots, here is the full sequence for two parallel tasks against issue #42 and #43, starting from a clean checkout of ~/code/app on main:
cd ~/code/app
# create the worktrees
git worktree add .kanbots/worktrees/issue-42-1 -b kanbots/issue-42-1 main
git worktree add .kanbots/worktrees/issue-43-1 -b kanbots/issue-43-1 main
# install a pre-push guard on the shared hooks dir
cat > .git/hooks/pre-push <<'SH'
#!/bin/sh
while read -r local_ref local_sha remote_ref remote_sha; do
case "$local_ref" in
refs/heads/kanbots/issue-*)
echo "kanbots: agent branch '$local_ref' cannot be pushed" 1>&2
exit 1
;;
esac
done
SH
chmod +x .git/hooks/pre-push
# dispatch two agents (background jobs)
( cd .kanbots/worktrees/issue-42-1 && \
claude -p "implement issue #42" --output-format stream-json --verbose --permission-mode bypassPermissions \
> .kanbots/worktrees/issue-42-1/run.ndjson ) &
( cd .kanbots/worktrees/issue-43-1 && \
claude -p "implement issue #43" --output-format stream-json --verbose --permission-mode bypassPermissions \
> .kanbots/worktrees/issue-43-1/run.ndjson ) &
# watch the streams
tail -f .kanbots/worktrees/issue-42-1/run.ndjson
# (in another terminal)
tail -f .kanbots/worktrees/issue-43-1/run.ndjsonWhen a run finishes, the last line of the NDJSON stream is a {"type":"result", ...}event with usage stats and a final result string. The diff is already committed on the agent’s branch — git -C .kanbots/worktrees/issue-42-1 log --oneline main..HEAD shows you what landed.
Common failure modes
“Branch already exists”
fatal: a branch named ‘kanbots/issue-42’ already exists. You ran the dispatch twice without disambiguating. Either delete the old branch with git branch -D kanbots/issue-42 or suffix the new one (kanbots/issue-42-2). KanBots uses the SQLite runId as the suffix specifically to make this unreachable.
“Worktree is dirty”
git worktree remove refuses if there are uncommitted changes. Either commit them (git -C <path>add -A && git -C <path> commit -m save) and then promote, or use git worktree remove --forceif you want to drop them. The agent normally commits as it goes, so this is rare — it happens when the run crashes mid-edit.
Hooks shared across worktrees
Git stores hooks in .git/hooks/ by default, which means a pre-push hook installed for an agent worktree also runs for your normal git push from main. The KanBots hook is deliberately scoped: it inspects $local_ref and only rejects refs under refs/heads/kanbots/issue-. Pushes of every other branch pass through. If you write your own hook, do the same — do not block all pushes.
“I deleted the directory; git still thinks it’s a worktree”
rm -rf ../wt/issue-42 removes the files but leaves the record in .git/worktrees/issue-42/. Future git worktree add at the same path will fail. Fix: git worktree prune. Or, less commonly, git worktree remove --force ../wt/issue-42.
When this is the wrong tool
The worktree workflow is overkill for:
- One-shot agent runs you have no intention of merging. Just
git stashyour work and run Claude in place. - Read-only agent jobs (analysis, summarization, dependency audits) that do not edit code. The agent never writes; you do not need branch isolation.
- Tiny repos. The setup overhead is real; a 200-line side project does not benefit.
For anything that produces a diff you might land — especially anything you want to run in parallel with other diffs — the worktree workflow is the right shape. Pair it with parallel Claude Code for multiple agents and safe parallelization patterns for the cost-control side.
Try it on your own folder
Drop a folder, get a board, dispatch parallel agents. The desktop runs locally on macOS, Linux, and Windows.
Related questions
- How do you run Claude Code in parallel?Run multiple Claude Code sessions at once, each in its own git worktree. The exact mechanics of parallel agent execution, and how KanBots makes it a one-click workflow.
- Can Claude Code work on multiple tasks at the same time?Claude Code is single-process by default. Here is how to put it on N tasks simultaneously without race conditions, using worktrees and a kanban dispatcher.
- How do you spawn multiple coding agents from one machine?Practical guide to running 2, 4, or more autonomous coding agents on a single developer machine without conflicts: process isolation, cost control, and a board to track them.
- How do you parallelize AI coding agents safely?The three failure modes of naive parallel-agent setups (worktree clobber, label drift, cost runaway) and the patterns that solve each one.