PreToolUse hooks don't fire for subagents (Agent tool)
Summary
PreToolUse hooks defined in ~/.claude/settings.json fire correctly for the main agent but are silently skipped for all subagents spawned via the Agent tool. This means any hook-based command rewriting, safety checks, or instrumentation only covers a fraction of actual tool calls in multi-agent workflows.
Impact
In a Conductor environment running parallel agents, 72% of sessions are subagents. With rtk installed as a PreToolUse hook to filter/compress Bash output (saving ~40% tokens on grep, find, git, gh commands), the main agent gets the optimization but every subagent runs raw commands — wasting tokens on unfiltered output.
Measured gap (30-day window):
- Main sessions: ~11K commands went through the hook → tokens saved
- Subagent sessions: ~7K commands bypassed the hook entirely → full token cost
- Estimated waste: ~3M tokens/month from subagent commands that would have been filtered
Reproduction
- Add a
PreToolUsehook to~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/path/to/my-hook.sh"
}
]
}
]
}
}
- In a session, run a Bash command directly — hook fires ✅
- Spawn a subagent via the
Agenttool that runs Bash commands — hook does NOT fire ❌
Evidence from session transcripts:
Main session transcript shows hook invocations interleaved with Bash commands:
"command":"/Users/.../.claude/hooks/rtk-rewrite.sh"
"command":"grep -rn ..."
"command":"/Users/.../.claude/hooks/rtk-rewrite.sh"
"command":"find ..."
Subagent transcript shows raw Bash commands with zero hook invocations:
"command":"grep -r ..."
"command":"find ..."
"command":"grep -n ..."
Expected behavior
All hooks (PreToolUse, PostToolUse, etc.) should propagate to subagents spawned by the Agent tool, inheriting from the same settings hierarchy (user → project → local) as the main agent.
Environment
- Claude Code version: latest (via Conductor)
- rtk version: 0.30.0
- OS: macOS (Darwin 25.5.0)
- Hook location:
~/.claude/settings.json(user-level)
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗