Skip to content

Any function-hook tool.call on Bash breaks Agent isolation: "worktree" — every Bash call refused with "isolation context for this agent was lost" #92533

Description

@navidemad

What's Wrong?

When a function-hooks plugin (CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1) registers any tool.call hook on Bash, a subagent spawned with Agent(isolation: "worktree") has every Bash call refused, including pwd and true:

The working-directory isolation context for this agent was lost, so this command would run in the parent session's directory instead of this agent's worktree (<repo>/.claude/worktrees/agent-xxx). Refusing to run it. Retry the command; if this keeps failing, report that worktree isolation was lost.

Retrying never helps (6 retries observed, all refused). Read/Edit and MCP tools keep working, only Bash is blocked. The hook itself can be a pure passthrough next(e) with no logic: the mere registration of a Bash tool.call hook triggers the loss (tengu_agent_worktree_cwd_escape_blocked / context_lost).

Bisection (all runs headless, claude -p, --output-format json, prompt asking the main agent to spawn one isolation: "worktree" general-purpose subagent that runs pwd once):

Configuration Subagent pwd
Project plugin with Bash hooks active refused
Same, --settings '{"env":{"CLAUDE_CODE_ENABLE_FUNCTION_HOOKS":"0"}}' OK
Fresh git init repo, --plugin-dir minimal plugin with only a session.start hook OK, prints the worktree path
Fresh git init repo, --plugin-dir minimal plugin with only a Bash tool.call passthrough refused

Side effect worth noting: if the blocked subagent calls EnterWorktree(path: <its worktree>) to recover, the parent session gets switched into that worktree (its own git commands are then refused outside that directory until ExitWorktree).

What Should Happen?

A passthrough function hook on Bash should not change where the command runs; the subagent's worktree cwd override should survive the hook chain (next(e)), and pwd should print <repo>/.claude/worktrees/agent-xxx.

Error Messages/Logs

The working-directory isolation context for this agent was lost, so this command would run in the parent session's directory instead of this agent's worktree (/path/to/repo/.claude/worktrees/agent-a0bafd2e8cb4295b0). Refusing to run it. Retry the command; if this keeps failing, report that worktree isolation was lost.

Steps to Reproduce

mkdir -p /tmp/repro/repo /tmp/repro/plug/.claude-plugin /tmp/repro/plug/hooks
cd /tmp/repro/repo && git init -q . && git commit -q --allow-empty -m init

printf '{"name":"plug","version":"0.0.1","description":"repro"}' > /tmp/repro/plug/.claude-plugin/plugin.json
echo '{"modules":["./h.ts"]}' > /tmp/repro/plug/hooks/hooks.json
cat > /tmp/repro/plug/hooks/h.ts <<'TS'
export const register = (on: any) => {
  on("tool.call", { tool: "Bash" }, async ($: any, e: any, next: any) => next(e));
};
TS

P='Do not modify files. Spawn ONE subagent via the Agent tool with isolation: "worktree" and subagent_type general-purpose, with this prompt: "Run `pwd` once via Bash. Report verbatim the output or the full error message. Do not retry." Then paste the subagent report verbatim and stop.'

claude -p "$P" --output-format json --allowedTools "Agent,Bash" \
  --plugin-dir /tmp/repro/plug \
  --settings '{"env":{"CLAUDE_CODE_ENABLE_FUNCTION_HOOKS":"1"}}' | jq -r .result
# → "The working-directory isolation context for this agent was lost …"

# Control: replace the hook by `on("session.start", ($, e, next) => next(e))` → pwd prints the worktree path.

Claude Model

Fable 5.1 (claude-fable-5-1) in the parent session; also reproduced with the default model in claude -p.

Is this a regression?

Unknown

Last Working Version

Unknown

Claude Code Version

2.1.263

Platform

macOS

Operating System

macOS (Darwin 25.6.0), Apple Silicon

Terminal/Shell

zsh 5.9 (Bash tool), fish as login shell

Additional Information

Function hooks are an early-access feature, so this may be a known limitation; if so, an explicit note in the function-hooks docs (or the error message) that Bash tool.call hooks are incompatible with isolation: "worktree" would save a lot of debugging. Our workaround is to create worktrees by hand (git worktree add … origin/main) and spawn agents without isolation, prefixing each command with cd <worktree> &&.

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