Bash tool refuses read-only and worktree-local commands as 'too complex to verify' in git worktree isolation

Status Open
Reported on v2.1.283
Maintainer reply None cached
Activity 1 comment · opened Sep 26, 2026

Environment

  • Claude Code 2.1.283, headless (claude -p)
  • macOS (Darwin 25.6)
  • Reproduced with hooks, plugins and MCP servers disabled

Summary

Inside a subagent dispatched with isolation: "worktree", the Bash tool refuses many read-only and worktree-local commands. These commands never leave the agent's own worktree, yet they are rejected with two classes of messages:

  • "too complex to verify that it stays inside the worktree"
  • "isolated in the worktree ... cannot be shown not to be git"

The refusals block valid workflows. The commands below have been confirmed as safe by an installed tm hook --pm-guard (trusty-tools 1.7.8), which accepts all 16 shapes; the refusals originate in Claude Code 2.1.283.

Refused command shapes

  1. uv run pytest tests/unit/test_github_sync_pull_recovery.py — path contains "github" substring, not a git command
  2. sed call on a shell variable path ($F or loop variable $f)
  3. grep -n 'pattern_containing_git' <file> — pattern text contains "git" substring, not a git command
  4. grep with pattern text containing "eval" substring
  5. grep -n <pattern> <path-a> <path-b> — multiple path arguments to read-only grep
  6. ls a b — multiple path arguments to ls
  7. cat a b c — multiple path arguments to cat
  8. grep -n "rustdoc" .github/workflows/ci.yml — path contains .github/ subdirectory
  9. terraform fmt infra/terraform/digitalocean/... — path contains "digitalocean" substring
  10. git range-diff <a>..<b> — read-only git query
  11. cd <worktree> && git ... — directory change (cd) before git, worktree-local
  12. git fetch origin; git checkout -b <branch> — chained git commands with semicolon
  13. for f in <paths>; do sed -i '' ... "$f"; done — loop variable used as sed argument
  14. Heredoc containing literal { (e.g. Rust snippet piped to rustfmt)
  15. git checkout -b <branch> — create new branch, no -C redirect, worktree-local
  16. awk -f /dev/stdin <<'AWK' ... — awk program in quoted heredoc

Observed vs expected

Observed: Refusals are triggered by:

  • Substring matches on "git", "eval", "github", "digitalocean" anywhere in arguments (not just command position)
  • Path segments like .github/ or filenames containing pattern keywords
  • Multiple positional arguments to read-only commands (ls, cat, grep)
  • Shell constructs like loops, cd, semicolon chaining, heredocs
  • Environment variables like $PWD or $F in command arguments

One refusal can cascade, causing the isolation guard to refuse nearly every later command in the same session with "too complex to verify", including unrelated commands like cargo and ls.

Expected: Commands that run entirely within the agent's own worktree and never invoke git should be accepted. Substring matching in argument text should not trigger git-operation refusals when the command position is not a git operation. Refusals should be documented with actionable substitutes, or validated before implementation.

Workarounds

  • Redirect grep/find to a file instead of piping
  • Use absolute worktree paths instead of variables or relative paths
  • Run single-argument invocations rather than multi-argument ones
  • Write scripts to the scratchpad with the Write tool instead of inline heredocs
  • Use Read tool instead of cat/grep for file inspection
  • Avoid variable names or filenames containing "git", "eval", "github", "digitalocean"

Related

  • bobmatnyc/trusty-tools#6982 — tracking issue collecting refused shapes
  • anthropics/claude-code#97224 — isolation: "worktree" cannot target existing trees
  • anthropics/claude-code#97225 — earlier issue on the same Bash-tool refusals

🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools

https://claude.ai/code/session_01XqeCnxEa77fK97L6tYTPsE

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗