PreToolUse hooks with Edit|Write matcher silently never invoked for an entire session (bypassPermissions, v2.1.195/196) while Bash-matched hooks fire normally
Summary
In a session running under permissionMode: bypassPermissions, PreToolUse hooks with an Edit|Write matcher were never invoked at all for the entire session, while PreToolUse hooks with a Bash matcher fired normally in the same session. This silently disabled a safety hook (an edit-count guard that hard-denies past a threshold) for 99 consecutive Edit/Write tool calls.
This appears distinct from existing reports: not #13744 (hooks fire for Edit/Write but fail to block — here they never executed), not #69970 (Bash hooks not firing — here Bash hooks worked fine), and not #71950 (denials under bypassPermissions — here the opposite, no hook ran at all).
Environment
- Claude Code 2.1.195, upgraded mid-session to 2.1.196 (behavior identical before and after the upgrade)
- macOS (Darwin 25.x)
permissionMode: bypassPermissionsfor the whole session- Hooks registered in
~/.claude/settings.jsonsince well before the session (verified via file mtime and config-repo git history): PreToolUsematcherEdit|Write→ two scripts (a settings-file guard and an edit-count guard, both plain Python, both executable, both known-working in other sessions)PreToolUsematcherBash→ separate scripts
Evidence (from the session transcript JSONL)
- 99 top-level
Edit/Writetool_useentries (no sidechains:isSidechain:truecount = 0) - 0 hook-execution attachments for
PreToolUse:EditorPreToolUse:Write - 97 hook-execution attachments for
PreToolUse:Bash(logged as normalhook_successentries throughout the same session) - The edit-guard's warn/deny message strings appear nowhere in the transcript (so it never ran and allowed — it never ran at all)
- No override mechanism was used (the guard's opt-out marker file did not exist; opt-out phrase absent from transcript)
- The same hooks fire normally for Edit/Write in other sessions on the same machine
Expected
PreToolUse hooks run for every matched tool call regardless of permission mode (bypassPermissions skips permission prompts, not hooks — hooks are the only enforcement layer left in that mode, which makes silent non-invocation a safety problem).
Actual
Edit|Write-matched PreToolUse hooks silently never executed for an entire session; Bash-matched PreToolUse hooks in the same session executed normally.
Notes
- Because the failure is silent (no error, no log, tool calls proceed), users have no signal that their guard hooks are inactive. Even if the root cause is an edge case, a visible warning when a registered hook is skipped/not invoked would mitigate the safety impact.
- Happy to provide redacted transcript excerpts (hook-execution attachment counts, tool_use entries) on request.