[BUG] User settings.json PreToolUse hooks never fire for Bash calls inside Task-spawned subagents

Status Open
Reported on v2.1.234
Maintainer reply None cached
Activity 1 comment · opened Aug 21, 2026

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: PreToolUse with matcher Bash, command rtk hook claude (a command-rewriting proxy that returns hookSpecificOutput.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-shaped hookSpecificOutput.updatedInput response 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

  1. Register a user-scope PreToolUse hook on Bash in ~/.claude/settings.json that observably modifies or logs commands (e.g. writes a line to a file per invocation).
  2. In a session, run a Bash command directly → hook fires.
  3. Ask Claude to spawn a Task subagent that runs the same Bash command → hook does not fire; no log line, no rewrite.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗