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> &&.
What's Wrong?
When a function-hooks plugin (
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1) registers anytool.callhook onBash, a subagent spawned withAgent(isolation: "worktree")has every Bash call refused, includingpwdandtrue: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 Bashtool.callhook 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 oneisolation: "worktree"general-purpose subagent that runspwdonce):pwd--settings '{"env":{"CLAUDE_CODE_ENABLE_FUNCTION_HOOKS":"0"}}'git initrepo,--plugin-dirminimal plugin with only asession.starthookgit initrepo,--plugin-dirminimal plugin with only a Bashtool.callpassthroughSide effect worth noting: if the blocked subagent calls
EnterWorktree(path: <its worktree>)to recover, the parent session gets switched into that worktree (its owngitcommands are then refused outside that directory untilExitWorktree).What Should Happen?
A passthrough function hook on
Bashshould not change where the command runs; the subagent's worktree cwd override should survive the hook chain (next(e)), andpwdshould print<repo>/.claude/worktrees/agent-xxx.Error Messages/Logs
Steps to Reproduce
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.callhooks are incompatible withisolation: "worktree"would save a lot of debugging. Our workaround is to create worktrees by hand (git worktree add … origin/main) and spawn agents withoutisolation, prefixing each command withcd <worktree> &&.