[BUG] User settings.json PreToolUse hooks never fire for Bash calls inside Task-spawned subagents
Summary
User-level PreToolUse hooks configured in ~/.claude/settings.json execute for Bash tool calls in the top-level interactive session, but silently never fire for Bash tool calls issued from Task-spawned subagent contexts.
Environment
- Claude Code 2.1.234 (macOS, desktop app session; also reproduced under CLI sessions)
- Hook:
PreToolUsewith matcherBash, commandrtk hook claude(a command-rewriting proxy that returnshookSpecificOutput.updatedInput)
Expected behavior
settings.json PreToolUse hooks apply to Bash tool calls wherever they run — including inside subagents spawned via the Task/Agent tool — or, if subagent exclusion is intentional, it is documented and configurable.
Actual behavior
- Top-level session: hook fires, command is rewritten as expected.
- Inside any Task-spawned subagent: the hook subprocess is never invoked. Verified by (a) running a Bash call in a subagent and observing the raw, un-rewritten command execute, and (b) the hook's own invocation log showing zero new entries for that call, while a concurrent top-level session's calls did log.
- The hook binary itself is healthy: piping the identical PreToolUse JSON payload (
{"tool_name":"Bash","tool_input":{"command":"git status"}}) to it by hand returns a correctly-shapedhookSpecificOutput.updatedInputresponse with exit 0.
Impact
Any workflow that delegates work to subagents loses hook coverage entirely. In our case a token-optimizing rewrite hook covered only 2.8% of Bash calls over 30 days (76,973-command window) because the orchestrator delegates most work to subagents — the un-rewritten remainder cost ~5.7M tokens. The same gap would apply to guard/audit hooks (command blocking, secret scanning), which is a heavier concern than tokens: a user who installs a PreToolUse guard reasonably believes it covers all Bash execution.
Repro
- Register a user-scope PreToolUse hook on Bash in
~/.claude/settings.jsonthat observably modifies or logs commands (e.g. writes a line to a file per invocation). - In a session, run a Bash command directly → hook fires.
- Ask Claude to spawn a Task subagent that runs the same Bash command → hook does not fire; no log line, no rewrite.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗