[BUG] Worktree guard refuses git -C ~/… in user ! commands; reason withheld under Remote Control

Status Closed — duplicate
Reported on v2.1.291
Maintainer reply None cached
Activity 2 comments · opened Oct 6, 2026 · closed Oct 9, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

In a session that EnterWorktree binds to a worktree, a user ! command fails when it runs git -C ~/<path>. The worktree command guard refuses it before spawn, because it treats a ~ path as "computed at runtime". The same command with an absolute path or with "$HOME/<path>" runs. I tested the three path forms with git status; the refusal text names only the -C path.

Three problems combine:

  1. The guard rejects ~ but accepts $HOME. Tilde expansion is static; $HOME is the runtime value.
  2. The guard applies to commands that the user types with !. Those commands are the user's own pass-through, not agent tool calls.
  3. When the session is connected through Remote Control, the user's own terminal shows only Command failed: shell command failed (detail withheld on this connection). The refusal reason goes only to the debug log. Without --debug-file, the user cannot see why the command failed.

Result: ! git -C ~/other-repo push failed in about 50 ms with no reason shown. The same push ran in a plain terminal and in a session without a worktree binding.

What Should Happen?

  • ! <command> runs the command as typed, or shows the real refusal reason in the user's terminal.
  • The guard handles ~/path the same way as $HOME/path (both resolve before spawn).
  • The guard does not apply the agent worktree-isolation policy to user ! commands, or it says so in the visible error.

Error Messages/Logs

Transcript, user terminal:

<bash-stderr>Command failed: shell command failed (detail withheld on this connection)</bash-stderr>

Debug log (--debug-file):

[WARN] [worktree] blocked shell exec: command guard refused (This session is isolated in the worktree /path/to/repo.feature, but this command points git at a directory computed at runtime (-C ~/other-repo), which can't be verified before it runs. Refusing to run it — a worktree-isolated session's git operations must target its own worktree. Run the equivalent from /path/to/repo.feature without the redirect.): cwd=/path/to/repo.feature isolationRoot=/path/to/repo.feature
[ERROR] bash spawn failure detail: This session is isolated in the worktree /path/to/repo.feature, but this command points git at a directory computed at runtime (-C ~/other-repo), ...

Steps to Reproduce

  1. Have a repository with a linked worktree, for example ~/repo and ~/repo.feature. Have a second, unrelated repository, for example ~/other-repo.
  2. Start claude --debug-file /tmp/cc.txt in ~/repo, with Remote Control connected.
  3. Ask Claude to call EnterWorktree with path: ~/repo.feature (absolute path).
  4. Type ! git -C ~/other-repo status. Result: Command failed: shell command failed (detail withheld on this connection).
  5. Type ! git -C /Users/<you>/other-repo status. Result: normal git status output.
  6. Type ! git -C "$HOME/other-repo" status. Result: normal git status output.
  7. Run grep 'command guard refused' /tmp/cc.txt. It shows the refusal for step 4 only.

In a session without EnterWorktree, step 4 runs normally.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.291 (Claude Code). Also reproduced on 2.1.289.

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Ghostty with tmux, zsh

Additional Information

The guard also refuses the agent's own Bash tool call git -C ~/other-repo status. For that tool call the model receives the full refusal reason. Only the user ! path replaces the reason with the withheld message.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗