claude-code - 💡(How to fix) Fix Agent({ isolation: "worktree" }) inherits last-checked-out branch instead of pinning to a base ref — causes cross-agent contamination on parallel spawn

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

There's also a related symptom: the parent session's tree can drift if it does its own git checkout while parallel worktree agents are running — git checkout feature-branch can silently fail because a still-running agent's worktree holds the ref, and the parent session ends up on the wrong branch without noticing. Defensive: check the exit code, or surface the failure to the user.

Fix Action

Fix / Workaround

When creating the worktree, use git worktree add -B agent-<id> <path> <baseRef> where <baseRef> is the parent session's HEAD (or, ideally, an explicit baseRef argument accepted on the Agent call). The -B flag creates a new named branch at the worktree fully isolated from whatever HEAD currently points to, which also obviates the workarounds agents have to perform.

Workarounds for users in the meantime

Code Example

T+0s    agent A   cwd=worktrees/agent-A...  gitBranch=feature-branch
T+37s   agent B   cwd=worktrees/agent-B...  gitBranch=feature-branch
T+54s   agent C   cwd=worktrees/agent-C...  gitBranch=feature-branch
T+65s   agent D   cwd=worktrees/agent-D...  gitBranch=worktree-agent-C   ← inherited C's auto-named branch
T+72s   agent E   cwd=worktrees/agent-E...  gitBranch=worktree-agent-C   ← same
T+82s   agent F   cwd=worktrees/agent-F...  gitBranch=worktree-agent-C   ← same
RAW_BUFFERClick to expand / collapse

When multiple Agent({ isolation: "worktree" }) calls are made in rapid succession (parallel fan-out from a parent session), the harness creates each worktree at .claude/worktrees/agent-<id>/ via git worktree add <path> without -b or an explicit ref. The new worktree therefore inherits whatever branch was last checked out in the underlying repository state. When agent N+1 spawns moments after agent N has switched its worktree to its own auto-named branch, agent N+1's worktree initializes on agent N's branch — not the parent session's branch.

Reproduce

  1. Start a session on a branch other than main (e.g. feature-branch).
  2. In one message, spawn three Agent({ isolation: "worktree" }) calls with file-disjoint tasks.
  3. Inspect each agent's first response — gitBranch field in the transcript header.

Observed (6-agent parallel fan-out)

T+0s    agent A   cwd=worktrees/agent-A...  gitBranch=feature-branch
T+37s   agent B   cwd=worktrees/agent-B...  gitBranch=feature-branch
T+54s   agent C   cwd=worktrees/agent-C...  gitBranch=feature-branch
T+65s   agent D   cwd=worktrees/agent-D...  gitBranch=worktree-agent-C   ← inherited C's auto-named branch
T+72s   agent E   cwd=worktrees/agent-E...  gitBranch=worktree-agent-C   ← same
T+82s   agent F   cwd=worktrees/agent-F...  gitBranch=worktree-agent-C   ← same

Agents D/E/F each detected this and hard-reset to the correct base, adding 30–60s of recovery time per agent and creating real risk of accidentally merging unrelated work back to the parent branch.

There's also a related symptom: the parent session's tree can drift if it does its own git checkout while parallel worktree agents are running — git checkout feature-branch can silently fail because a still-running agent's worktree holds the ref, and the parent session ends up on the wrong branch without noticing. Defensive: check the exit code, or surface the failure to the user.

Suggested fix

When creating the worktree, use git worktree add -B agent-<id> <path> <baseRef> where <baseRef> is the parent session's HEAD (or, ideally, an explicit baseRef argument accepted on the Agent call). The -B flag creates a new named branch at the worktree fully isolated from whatever HEAD currently points to, which also obviates the workarounds agents have to perform.

Workarounds for users in the meantime

  • Stagger spawns past branch-switch (~60s gap between agents), or
  • Have the parent session re-git checkout <baseRef> immediately before each Agent call, or
  • Pre-create the per-agent branch yourself and pass the worktree path explicitly.

Other notes

  • The harness's worktree directories appear to accumulate as locked even after the spawning Claude process exits (git worktree list -v showed 40+ stale locked worktrees from prior sessions). Some prune-on-exit / liveness-check behavior would also help.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Agent({ isolation: "worktree" }) inherits last-checked-out branch instead of pinning to a base ref — causes cross-agent contamination on parallel spawn