[BUG] Agent tool isolation: "worktree" has no effect for team agents — agent runs in main repo

Resolved 💬 20 comments Opened Mar 11, 2026 by bonanza465 Closed Jul 16, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When spawning a team agent with isolation: "worktree" via the Agent tool, no git worktree is created. The agent runs in the main repository on the current branch, with full read/write access to the main working tree. The parameter is silently ignored.

This is distinct from #23715 (which is about multiple Claude sessions sharing ~/.claude/teams/ state). This bug is specifically about the isolation: "worktree" Agent tool parameter having no effect at runtime.

Note: #28175 describes the same bug but was incorrectly closed as a duplicate of #23715.

What Should Happen?

When isolation: "worktree" is set on an Agent tool call, a temporary git worktree should be created (as the parameter description states: "creates a temporary git worktree so the agent works on an isolated copy of the repo") and the agent's working directory should be set to that worktree path.

Steps to Reproduce

  1. Start Claude Code in a git repository
  2. Create a team: TeamCreate { team_name: "test-team" }
  3. Spawn an agent with isolation:

``
Agent {
description: "worktree isolation test",
name: "test-agent",
team_name: "test-team",
isolation: "worktree",
run_in_background: false,
prompt: "Run: pwd, then run: git worktree list, then report both outputs."
}
``

  1. Observe the agent's reported pwd and git worktree list output

Observed Output

pwd: /home/user/my-repo          ← main repo path, not a temp worktree
git worktree list:
/home/user/my-repo  abc1234 [main]   ← only one worktree, no isolated copy created

Expected Output

pwd: /tmp/claude-XXXX/worktree-test-agent    ← isolated worktree path
git worktree list:
/home/user/my-repo              abc1234 [main]
/tmp/claude-XXXX/worktree-...   def5678 [worktree-agent-XXXX]

Error Messages/Logs

No error — the parameter is silently ignored.

Additional Context

The isolation parameter enum in the Agent tool schema only has one valid value ("worktree"), with the description: "Isolation mode. 'worktree' creates a temporary git worktree so the agent works on an isolated copy of the repo."

As a workaround, we manually create git worktrees before spawning agents:

git worktree add /tmp/claude-1000/worktree-{story_id} -b worktree-story-{story_id}

...and set project_root in the agent prompt to the worktree path. This works correctly, but the isolation: "worktree" parameter should handle this automatically.

Related issues:

  • #28175 (closed as duplicate of #23715 — but that's a different bug)
  • #27881 (worktree creation silent fallback after context compaction)

Claude Code Version

2.1.72

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux (WSL2)

Terminal/Shell

bash

View original on GitHub ↗

20 Comments

github-actions[bot] · 4 months ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/28175
  2. https://github.com/anthropics/claude-code/issues/27749

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

bonanza465 · 4 months ago

Thanks for surfacing these — just wanted to clarify why I don't think either is a duplicate of this one:

#28175 is about the same symptom (team agents not getting their own worktree), but it was closed as a duplicate of #23715, which is actually a different issue — that one is about multiple Claude Code sessions sharing ~/.claude/teams/ state and TeamDelete in one session wiping teams in another. Neither addresses the root cause here.

#27749 is a feature request for configurable branch naming when isolation: "worktree" is used — which presupposes the feature works. This issue is one step earlier: the worktree isn't being created at all for team agents.

This issue is specifically about the Agent tool's isolation: "worktree" parameter being silently ignored at runtime when team_name is set — the agent lands in the main repo with no worktree created and no error raised. Happy to provide additional repro details if that would help\!

bonanza465 · 4 months ago

One additional data point from a second test run: I checked git worktree list from the parent session while the team agent was actively running (idle, waiting for input). The parent also showed only one worktree — the main repo. So the worktree is never created at any point during the agent's lifetime: not at spawn, not during execution, not transiently. The isolation: "worktree" parameter appears to have no effect whatsoever on the spawned agent's environment.

miscellanea · 4 months ago

same here

miscellanea · 4 months ago

btw how do you get it working with project_root? could you please share that

bonanza465 · 4 months ago

Update: isolation: "worktree" works on standalone agents, broken only on TeamCreate agents.

Further testing on 2.1.77 reveals the bug is specific to the TeamCreate code path:

| Spawn method | Worktree created | Isolation works |
|---|---|---|
| Agent({ isolation: "worktree" }) (standalone) | Yes | Yes — full isolation |
| Agent({ isolation: "worktree", team_name: "..." }) (TeamCreate teammate) | No | No — runs on main |

Standalone agent test: Two agents spawned in parallel with isolation: "worktree" and run_in_background: true, each editing a different line of the same file. Each got its own worktree (.claude/worktrees/agent-{hash}) on its own branch (worktree-agent-{hash}). Complete isolation — neither agent saw the other's edits. Relative paths resolved correctly within each worktree.

TeamCreate agent test (same file, same setup but with team_name): Both agents ran in the main repo on main. No worktree created. Real-time file collision confirmed. Also tested with dangerouslyDisableSandbox: true — same result, ruling out sandbox as a factor.

Conclusion: The worktree creation logic exists and works. The TeamCreate agent spawn code path just doesn't invoke it.

Correction to original issue: The workaround described ("set project_root in the agent prompt to the worktree path") was inaccurate. For standalone agents, no manual workaround is needed — isolation: "worktree" just works. For TeamCreate agents, the parameter is ignored entirely.

bonanza465 · 4 months ago
btw how do you get it working with project_root? could you please share that

Update: further testing on 2.1.77 shows isolation: "worktree" actually works — but only on standalone agents, not TeamCreate agents. The bug is that the TeamCreate code path skips worktree creation.

Apologies for the misleading info in the original issue — the claim about setting project_root in the agent prompt was inaccurate. For standalone agents, no manual workaround is needed at all.

Working pattern (standalone agents):

Agent({
  name: "my-agent",
  isolation: "worktree",
  run_in_background: true,
  prompt: "Your task here..."
})

That's it — no manual worktree setup needed. The agent gets its own worktree at .claude/worktrees/agent-{hash} on branch worktree-agent-{hash}. Relative paths resolve correctly within the worktree. run_in_background: true keeps the main session unblocked.

We verified this with two parallel agents editing the same file — complete isolation, no cross-contamination.

What you lose vs TeamCreate: No shared task list, no inter-agent messaging, no coordinated shutdown. For independent parallel tasks those aren't needed.

If you need TeamCreate features (task coordination, messaging), you can manually create worktrees before spawning teammates:

git worktree add .claude/worktrees/agent-a -b worktree-agent-a
git worktree add .claude/worktrees/agent-b -b worktree-agent-b

Then include this at the top of each teammate's spawn prompt:

CRITICAL: Your working directory is /absolute/path/to/repo/.claude/worktrees/agent-a
You MUST run `cd /absolute/path/to/repo/.claude/worktrees/agent-a` before ANY bash command.
ALL file reads and edits MUST use absolute paths starting with /absolute/path/to/repo/.claude/worktrees/agent-a/
ALL Glob and Grep calls MUST pass the `path` parameter set to /absolute/path/to/repo/.claude/worktrees/agent-a/
Relative paths will resolve to the MAIN repo, not your worktree.

Note: with manual worktrees on TeamCreate agents, the agent's internal project root does NOT change — only Bash cd respects the worktree path. Read, Edit, Glob, and Grep all need explicit absolute paths. Sandbox permissions inherit to subdirectories, so all agents can technically access sibling worktrees — isolation is enforced by the prompt, not filesystem permissions.

Cleanup after agents finish:

git worktree remove --force .claude/worktrees/agent-{name}
git branch -d worktree-agent-{name}
yurukusa · 3 months ago

A PreToolUse hook on the Agent tool can enforce worktree isolation by creating the worktree before the agent starts:

INPUT=$(cat)
ISOLATION=$(echo "$INPUT" | jq -r '.tool_input.isolation // empty')
[ "$ISOLATION" = "worktree" ] || exit 0
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
    MAIN_DIR=$(git rev-parse --show-toplevel)
    CURRENT_DIR=$(pwd)
    if [ "$MAIN_DIR" = "$CURRENT_DIR" ]; then
        BRANCH="agent-$(date +%s)-$RANDOM"
        WORKTREE_DIR="/tmp/cc-worktrees/$BRANCH"
        mkdir -p /tmp/cc-worktrees
        git worktree add "$WORKTREE_DIR" -b "$BRANCH" HEAD 2>/dev/null
        if [ $? -eq 0 ]; then
            echo "[WorktreeGuard] Created worktree at $WORKTREE_DIR" >&2
            echo "$WORKTREE_DIR" >> /tmp/cc-active-worktrees.txt
        fi
    fi
fi
exit 0

Cleanup hook for session end:

while IFS= read -r wt; do
    [ -d "$wt" ] && git worktree remove "$wt" --force 2>/dev/null && echo "Cleaned up: $wt" >&2
done < /tmp/cc-active-worktrees.txt 2>/dev/null
rm -f /tmp/cc-active-worktrees.txt
exit 0

Note: The hook can create the worktree and log it, but it cannot change the agent's working directory. The agent itself would need to cd into the worktree. A CLAUDE.md instruction can help: "When isolation: worktree is set, always cd to the worktree path shown in the PreToolUse output."

shevisj · 3 months ago

I'm seeing this issue as well.

deggers · 3 months ago

I have this issue too and its a deal breaker

itsbohara · 3 months ago

This is honestly a f*cking disaster with the claude agent sdk. It doesn’t work with openai models at all, even hooks like preToolUse don’t function properly.

Are you guys intentionally blocking openai models, or is this just broken?

phobologic · 3 months ago

Running into this as well - thought I was doing something wrong, pushed a lot on it to try and fix it, finally came here.

AlexandrePh · 3 months ago

Confirming this is still broken on macOS.

Environment: Darwin 25.3.0 (macOS 26.3), Claude Code 2.1.94 (probe spawner) and 2.1.96 (other agents), Opus 4.6 parent session.

Repro: Same as the original — TeamCreate then Agent(team_name, subagent_type: Explore, isolation: "worktree", …).

What I observed (additional to the OP's findings):

  1. Verified at OS level, not just self-report. The spawned agent reports pwd = /path/to/main/repo, and I confirmed independently via lsof -p <spawned_pid> | awk '\$4=="cwd"' — the kernel agrees it's in the main repo's cwd, not a worktree.
  1. Worktree creation is inconsistent across agent types. With subagent_type: Explore, a new worktree under .claude/worktrees/agent-<hash>/ IS created on disk (we can see it in \git worktree list\) — the agent just isn't placed in it. With \subagent_type: general-purpose\, no worktree is created at all. Same team, same isolation parameter, different behavior.
  1. Spawn result is missing the documented fields. The \Agent\ tool description says \"the path and branch are returned in the result\" when isolation is on. The actual spawn result contains only \agent_id\, \name\, \team_name\ — no \path\ or \branch\.
  1. Submodules may be a factor. The repo I hit this in has 7 submodules (\.gitmodules\). \git worktree add\ does not recursively init submodules, which may be why the harness silently bails mid-setup for some agent types.

Impact beyond file conflicts: when users have PreToolUse hooks like \block-main-edits.sh\ or branch verifiers, the isolation bug silently places agents on main and those safeguards fire against the child agents unexpectedly — double damage from a single root cause.

Still looking for a response on whether this is being worked on. Happy to provide more diagnostic data if useful.

him0 · 3 months ago

I investigated this issue and identified the root cause.

When an agent is spawned with isolation: "worktree" in a team context, the generated CLI command does not include the --worktree flag. Here's an example of the spawned command (paths sanitized):

$ cd <project-dir> && env CLAUDECODE=1 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 \
  <path-to-claude-binary> \
  --agent-id <agent-id>@<team-name> \
  --agent-name <agent-name> \
  --team-name <team-name> \
  --agent-color green \
  --parent-session-id <session-id> \
  --permission-mode auto \
  --model claude-opus-4-6

Notice that --worktree is missing from the command, even though isolation: "worktree" was specified in the Agent tool call.

The fix seems straightforward: when isolation: "worktree" is set, the --worktree flag should be appended to the spawned agent's CLI command.

As a workaround, I'm currently instructing team agents to call EnterWorktree explicitly in their prompt, but this is fragile (e.g., context compaction can cause nested worktrees as noted in #27881).

akravetz · 2 months ago

confirming I'm seeing this as well for non-team agents. Multiple parallel agents run in the background do not appear to consistently respect the worktree isolation flag. Happy to post session logs if its helpful

razhangwei · 2 months ago

Adding another data point — observed on Claude Code (Opus 4.7, 1M context) on macOS, April 2026.

Fan-out of 5 parallel teammates via TeamCreate + 5 Agent tool calls with isolation: "worktree", each with a distinct name and subagent_type: "general-purpose". All spawned in separate tool-use blocks within two consecutive parent turns.

Expected: 5 freshly-created worktrees at .claude/worktrees/<slug>/, each teammate fully isolated.

Observed: only 1 secondary worktree auto-created. The first teammate effectively commandeered the primary checkout (branch silently flipped from main to its feature branch). The remaining 3 teammates all landed in the primary checkout as well, on different branches, with each other's uncommitted files visible. One teammate had to manually git worktree add to recover clean isolation.

$ git worktree list
/path/to/repo                                       <sha> [opencli-port/x-bookmarks]   ← primary checkout, branch flipped
/path/to/repo/.claude/worktrees/bold-jackson-XXXX  <sha> [opencli-port/x-digest]      ← the one auto-created worktree
/path/to/repo/.claude/worktrees/wechat-reader-port  <sha> [opencli-port/wechat-reader] ← self-created by the teammate

Slight variant from #48811's "0 worktrees, literal null path" symptom: here exactly 1 worktree was created, suggesting a race where the first spawn wins and subsequent ones fall back to the primary checkout instead of creating their own.

Impact: cross-contamination risk at commit time — if any teammate had used git add . they'd have pulled in another teammate's WIP. In practice the teammates were disciplined (explicit git add <paths>), so no commits were corrupted, but the foot-gun is real. Also leaves the parent session's cwd on an unexpected branch after teammates complete.

DanielTatarkin · 2 months ago

Issue still persists on v2.1.136

cyphercider · 1 month ago

+1 — we're hitting this in a multi-repo workspace orchestrator pattern (SalesPath: 1 executor repo + 4 sibling app repos coordinated via subagent dispatch).

Our concrete shape (Wave 1 2026-05-18 postmortem):

7 parallel Agent(subagent_type: "<repo>-worker", isolation: "worktree") dispatches across 2 sibling repos (salespath-ui + salespath-backend). 3-of-7 workers reported cross-pollution despite all passing isolation: "worktree":

  1. Worker A: "shared backend worktree was switched out from under me by a concurrent session. Reflog shows feat/ci-parity-automation-X + feat/stripe-webhook-receiver-Y checkouts that I did not initiate"
  2. Worker B: "shared checkout was being repeatedly git checkout main'd by another session" — self-escaped to /tmp/wt-<id>
  3. Worker C: git checkout -b <branch> origin/main landed the working changes on a DIFFERENT branch (a sibling worker's branch). Recovery via cherry-pick.

Root cause we believe: Agent(isolation: "worktree") creates a worktree of the leader's cwd (the executor repo where the orchestrator runs). The team-agent worker then cds into a sibling repo (MAIN_APPS/<repo>) per its .md definition, and that sibling repo is a single shared checkout with no per-worker isolation. The flag name implies end-to-end isolation but is scoped to leader cwd only.

Our workaround (Option B): each <repo>-worker.md now opens with a mandatory pre-flight bash block that does git worktree add -b "$BRANCH" /tmp/wt-<repo>-<branch>-$$ origin/main on the sibling repo, then cds into it for all subsequent operations. Leader sweeps /tmp/wt-* at session halt. Works reliably but requires per-worker discipline.

What would solve it cleanly upstream:

  • Agent(isolation: "worktree", isolation_repos: ["./", "../sibling-repo-1", "../sibling-repo-2"]) — explicit list of repos to isolate
  • OR Agent(isolation: "all-declared-repos") reading from a workspace manifest
  • OR fix the team-agent dispatch path so the existing isolation: "worktree" actually covers the agent's working directory regardless of where it cds

We considered using the WorktreeCreate hook (documented as the extension point that "replaces the default git worktree logic entirely") but rejected it because (a) we'd lose the default executor-repo isolation that does work, and (b) if the harness skips worktree creation for team agents per this issue, the hook never fires.

Happy to provide a redacted excerpt of our orchestrator dispatch pattern if it helps reproduce.

jacksteamdev · 1 month ago

Not stale, this is still biting me in v2.1.168.

Additionally, the team lead agent's branch is being changed when team agents use EnterWorktree.

github-actions[bot] · 9 hours ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.