Skip to content

Bash tool in a worktree-isolated agent refuses commands that never leave the worktree #97225

Description

@bobmatnyc

Environment

  • Claude Code 2.1.282, headless (claude -p), --permission-mode bypassPermissions
  • macOS 26.6.2, arm64
  • Reproduced with hooks, plugins and MCP servers disabled.
  • Flags: --safe-mode --setting-sources "" --settings '{"disableAllHooks":true}' --strict-mcp-config --mcp-config '{"mcpServers":{}}'. The debug log reports "Registered 0 hooks from 2 plugins" (the built-in agents-md and telemetry) and "Found 0 total hooks in registry".

Summary

Inside a subagent dispatched with isolation: "worktree", the Bash tool refuses some commands because it cannot prove they are not git operations on another tree. The shapes below run only inside the agent's own worktree, yet each is refused. Results reproduced in two separate runs.

Minimal reproduction

Throwaway repo with one commit and scripts/hello.sh. Dispatch one general-purpose subagent with isolation: "worktree" and run each command as its own Bash call, cwd the worktree. <own> stands for the worktree path.

  1. git -C . status --short. Refused:
This agent is isolated in the worktree <own>, but this command points git at a directory computed at runtime (-C .), which can't be verified before it runs. Refusing to run it — a worktree-isolated agent's git operations must target its own worktree. Run the equivalent from <own> without the redirect.
  1. awk -f /dev/stdin <<'AWK' < /dev/null / { print } / AWK. Refused:
This agent is isolated in the worktree <own>, but this command runs awk with -f inside a construct too complex to verify, so what it runs cannot be shown not to be git. Refusing to run it — a worktree-isolated agent's git operations must target its own worktree. Split it into plain, separate commands and run them from <own>.

echo "a b" | awk -f /dev/stdin <<'AWK' / { print $2 } / AWK is refused with "runs awk with -f in a plain command" in place of "inside a construct too complex to verify".

  1. export TD=$PWD/target-alt && echo $TD. Refused:
This agent is isolated in the worktree <own>, but this command runs export TD= with a value every later program inherits (the variable PWD) inside a construct too complex to verify, so what it runs cannot be shown not to be git. Refusing to run it — a worktree-isolated agent's git operations must target its own worktree. Split it into plain, separate commands and run them from <own>.

The same command with the literal worktree path in place of $PWD is accepted.

Observed vs expected

Observed: -C . is the cwd, which is the worktree, not a directory computed at runtime, and nothing is redirected. $PWD at the start of a Bash call is the worktree. An awk program read from a quoted heredoc is fixed text. Each refusal costs a turn, and there is no documented list of accepted shapes.

Expected: accept git -C . and $PWD when the cwd is the agent's own worktree, and inspect a quoted heredoc's literal text before refusing it. Failing that, publish the accepted shapes.

Workaround in use

  • git -C . becomes git status with no -C, or git -C <absolute worktree path>
  • an awk -f heredoc becomes a script written with the Write tool and run by path
  • export VAR=$PWD/... && cmd becomes the literal absolute path, or a script run by path

Evidence (public issues, for reference only)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions