anthropics / anthropics/claude-code
Worktree isolation refuses git-free Bash on 2.1.272/2.1.273: literal-assigned variables, $(…) args, loops, heredocs after && (75 refusals in 3 days)
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
## Summary
In a worktree-isolated session (`isolation: "worktree"` / `EnterWorktree`), Claude Code **2.1.272 and 2.1.273** refuse Bash calls that contain no `git` at all and reference only paths inside the worktree. The 2.1.257 changelog says loops, `$VAR` reads, `"$(…)"` and heredocs that never touch git were fixed; the shapes below are still refused on 2.1.272/273.
Across six worktree sessions on 2026-09-15..17 this produced **75 refusals and roughly 115 wasted tool calls** (the refusal plus the retry), out of 249 tool errors of all kinds in the same window.
Related: #87959, #84182, #93193.
## Environment
- Claude Code 2.1.272 and 2.1.273 (CLI, Linux/WSL2 Ubuntu), sessions started inside a linked worktree under `/.claude/worktrees/`
- Models: Opus 5 / Fable 5.1
- Bash tool; no `git` invocation in any of the refused commands below
## Reproducers (inside the worktree, no git anywhere in the command)
| Command | Refusal text (verbatim fragment) |
|---|---|
| `D=/path/to/worktree/.agent/tasks/x/raw; mkdir -p "$D"; python3 $D/summary.py` | `runs python with a program computed at runtime (the variable D) inside a construct too complex to verify, so what it runs cannot be shown not to be git` |
| `S=/path/to/worktree/.agent/scratch/cov.py; python3 /path/to/worktree/.agent/scratch/run.py $S` | `runs python with a value computed at runtime (the variable S) (a computed argument goes after the script or --)` |
| `W=/tmp/scratch/wiki; ls "$W/Incidents"` | `runs ls with a value computed at runtime (the variable W) …` |
| `for f in a.md b.md; do sed -n 2,14p "$f"; done` | `runs sed with a value computed at runtime (the variable f) …` |
| `grep -n 'def redact' x.py; sed -n "$(grep -n 'def redact' x.py \| cut -d: -f1),+5p" x.py` | `runs sed with a value computed at runtime (command output) where an option may stand …` |
| `mkdir -p out && cat > /path/to/worktree/projects/x/REPORT.md <<'EOF' … EOF` | `this command is too complex to verify that it stays inside the worktree` |
| `cd /path/to/worktree && for f in run_etc_backup.sh run_db_backup.sh; do sha256sum "$f"; done` | `names git in a form too complex to verify that it stays inside the worktree` (there is no `git` token in the command) |
| `ls runs \| head -1 \| xargs -I{} sh -c 'cat runs/{}/stdout.log'` | `runs sh from a find -exec or xargs slot …` |
Every path is a literal inside the worktree or under `/tmp`; every variable is assigned a literal in the same command.
## Expected
Per the worktrees documentation ("How Claude Code enforces isolation"), the command-shape check should refuse only commands whose git invocation cannot be located. A variable assigned a literal path in the same command, a `for` over literal words, or a `$(grep …)` argument to `sed -n` cannot run git. The wording "names git" is wrong when the command contains no `git` token.
## Actual
Each call is refused before it runs; the model retries with a rewritten shape (typically writing the logic to a file and running `python3 /literal/path.py`), so every refusal costs at least two tool calls.
## Requests
1. Resolve same-command literal assignments (`D=/literal; … $D/…`) before the shape check, as the 2.1.257 note suggests was intended.
2. Do not refuse a heredoc whose redirect target is an absolute path inside the worktree because an earlier `&&` exists in the call.
3. Never report "names git" when the command contains no `git` token.
4. Offer a setting or environment variable to downgrade the shape check to a warning for sessions that enforce git isolation by other means (e.g. their own PreToolUse hooks), since the docs state the check cannot be turned off.
I can share the full list of 75 refused commands with the preceding and following tool calls on request.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the Bash tool's worktree-isolation command-shape check and compare its behavior with the worktrees documentation and the 2.1.257 changelog note. Reproduce the listed commands in an isolated worktree; done means safe non-git commands run without refusal, refusal wording matches the command, and any warning-mode setting behaves as documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100