PostToolUse hooks do not fire in daemon/background-job sessions (PreToolUse + SessionStart do) — v2.1.208
Summary
In a daemon-backed background session (Claude Code's background-job / daemon backend — "backend": "daemon" in the job state, cliVersion 2.1.208), PostToolUse hooks configured in settings.json never fire. PreToolUse and SessionStart hooks from the same settings.json fire normally in the same session, and the identical PostToolUse hooks fire correctly in an interactive session.
The hooks reference documents PostToolUse as running after every successful tool call, with no execution-mode caveat — so this appears to contradict documented behavior.
Environment
- Claude Code
2.1.208 - Linux (Ubuntu)
- Session backend:
daemon(the background-job feature; jobstate.jsonhas"backend": "daemon","template": "claude") - Hooks defined in the user
settings.json(symlinked, shared with interactive sessions)
Repro
- In
settings.json, register aPostToolUsehook with aBashmatcher that appends a marker, e.g.:
``json``
{ "hooks": { "PostToolUse": [ { "matcher": "Bash",
"hooks": [ { "type": "command", "command": "echo fired >> /tmp/posttooluse-marker" } ] } ] } }
- Start a background/daemon session and run any
Bashtool call. - Observed:
/tmp/posttooluse-markeris never written; the hook does not run. - Run the same tool call in an interactive session → the marker is written.
- Feed the hook script its JSON payload manually (
echo "$payload" | hook.sh) → it works. The hook script itself is healthy; it is simply never invoked in the daemon session.
Evidence from a real session
- A
PostToolUsehook that appends to~/.claude/logs/hook-events.jsonlon everyBash/Editrecorded zero new rows across ~30 minutes and dozens ofBashtool calls in a daemon session; its last row predates the session's tool activity entirely. PreToolUsedispatcher hooks (andSessionStartcontext injection) from the samesettings.jsonfired throughout that same session normally.- Confirmed by an independent controlled repro (hook healthy on manual payload; never fired in the background session;
PreToolUsefired).
Impact
Any guardrail that relies on PostToolUse is silently bypassed in background/daemon sessions — auto-formatters, post-write secret scanners, telemetry/event logging, doc-regeneration, and (our case) a git worktree add auto-normalizer. Because PreToolUse still fires, the failure is easy to miss.
Not a duplicate of
- #73586 — MCP tool calls only; this is native
Bash. - #68970 — Windows ~1.2% trigger rate; this is Linux, 0% for
PostToolUsespecifically, 100% forPreToolUse. - #69519 — path-join bug for edits outside CWD; unrelated.
- #6305 — reports both Pre and Post not executing; here
PreToolUse/SessionStartfire and onlyPostToolUseis dropped, specifically in the daemon backend.
Question
Is PostToolUse intentionally suppressed in the daemon/background execution mode? If intended, please document the mode caveat; if not, PostToolUse delivery is broken for background sessions and every PostToolUse-based guardrail is unreliable there.