Hooks fail open when CWD is invalidated (e.g. worktree deletion)

Resolved 💬 0 comments Opened Jul 12, 2026 by in4mer Closed Jul 12, 2026

Summary

When the shell's working directory becomes invalid — whether from an external process deleting it OR from a command within the same session (e.g., git worktree remove) — all hooks fail with ENOENT: no such file or directory, posix_spawn '/bin/sh'. The harness treats these execution failures as "hook didn't block," so tool calls proceed without any hook-based enforcement.

Reproduction

  1. Launch Claude Code with a git worktree as the project root (or cd into one during the session)
  2. Run git worktree remove <path> from within the session, or delete the directory from another terminal
  3. Issue any subsequent tool call
  4. Observe: hooks error out with posix_spawn ENOENT, but the tool call proceeds as if allowed

This also reproduces when the session itself runs git -C <parent> worktree remove <target> — the git command succeeds, the directory is gone, and every subsequent hook invocation fails open.

Expected behavior

  1. A hook that fails to execute (ENOENT, missing CWD, posix_spawn failure) should be distinguishable from a hook that ran and returned "allow." The harness should either:
  • Block the tool call (fail-closed) when hooks cannot execute due to environment errors, OR
  • Surface a visible warning that hook enforcement is degraded, OR
  • Detect that CWD is invalid before attempting to spawn hooks, and enter a recovery state
  1. The harness should expose a mechanism to change the session's working directory — a shell-level hook, API call, or tool that lets the model, the user, or a hook script set the CWD that subsequent tool calls and hook invocations inherit. Currently there is no way to recover from an invalidated CWD without restarting the session. A cd-equivalent that actually persists across tool calls would allow recovery (move to a valid directory) and prevent the unbounded fail-open window.

Actual behavior

  • Hook execution errors are treated identically to "hook allowed the operation" (fail-open)
  • No warning or indication that enforcement is absent
  • Multiple consecutive tool calls proceed without any gate checking
  • Recovery only happens when the Bash tool's shell detects the missing CWD and resets it (may be many turns later)
  • There is no mechanism for anyone (model, user, hook) to change the session CWD to a valid path

Impact

Any hook-based enforcement (PreToolUse gates, PostToolUse tracking, UserPromptSubmit validation) is silently disabled for an unbounded window. The session continues operating as if no hooks are configured.

Environment

  • Claude Code CLI, Linux 5.15
  • Triggered by: git worktree removal (in-session or external), external directory deletion, any operation that invalidates the shell's CWD while the session is active

View original on GitHub ↗