Hook Runtime: Add centralized hook manager with parallel dispatch and priority ordering

Resolved 💬 2 comments Opened Mar 16, 2026 by thamam Closed Apr 13, 2026

Problem

As the Claude Code plugin ecosystem grows, hooks are becoming a performance and security bottleneck. Each plugin registers its own hooks independently, and Claude Code runs them all sequentially — every registered hook must complete (or timeout) before the next starts and before the actual tool call proceeds.

Real-world impact (measured on a moderately-equipped setup)

With plugins like read-back, hookify, security-guidance, cc10x, and claude-dev-infrastructure installed:

| Tool call type | PreToolUse hooks | PostToolUse hooks | Total hooks per call |
|---|---|---|---|
| Read/Grep/Glob | 2 (unfiltered) | 2 (unfiltered) | 4 |
| Edit/Write | 5 (all match) | 3 (all match) | 8 |

At ~10-50ms each, that's 80-400ms of hook overhead per Edit/Write — and this scales linearly with every new plugin. Adding a monitoring tool like cctop would push Edit/Write to 10 hooks per call.

The deeper issue

There are two fundamentally different categories of hooks being treated identically:

  1. Side-channel hooks — write logs, update state, track metrics. Their stdout is empty. They don't affect Claude's behavior. (e.g., cctop, cc10x audit logging, read-back state tracking)
  1. Flow-control hooks — return permissionDecision: deny, systemMessage, decision: block. These are part of the LLM conversation loop. (e.g., security-guidance blocking dangerous patterns, hookify rule engine, ralph-loop continuing iterations)

Currently both categories run sequentially and block the pipeline identically. A logging hook that writes to a file has the same execution cost as a security hook that needs to make a block/allow decision.

Proposal: Smarter Hook Runtime

1. Hook classification via manifest flag

Allow plugins to declare their hooks' nature:

{
  "hooks": {
    "PreToolUse": [{
      "sideEffectOnly": true,
      "hooks": [{ "type": "command", "command": "..." }]
    }]
  }
}
  • "sideEffectOnly": true — hook cannot block, stdout is ignored. Claude Code can fire-and-forget without waiting.
  • Default (false) — current behavior, sequential execution with result handling.

2. Parallel dispatch for side-effect hooks

Side-effect hooks should run in parallel and non-blocking. The tool call proceeds immediately while they execute in the background. This alone would cut the overhead roughly in half for typical setups.

3. Priority ordering for flow-control hooks

Allow plugins to declare execution priority:

{
  "hooks": {
    "PreToolUse": [{
      "priority": 10,
      "hooks": [{ "type": "command", "command": "..." }]
    }]
  }
}

Lower number = runs first. Security hooks should run before convenience hooks. This also enables short-circuiting — if a high-priority hook blocks, lower-priority hooks can be skipped.

4. Output validation / sandboxing

Currently any plugin can return permissionDecision: deny and block any tool call with no oversight. Consider:

  • A "canBlock": true permission that plugins must explicitly declare (and users approve)
  • Size caps on systemMessage injection to prevent context window abuse
  • Telemetry/logging of which hooks block and how often, so users can audit

5. (Stretch) Built-in hook manager / event bus

Long-term, a centralized hook manager within Claude Code that plugins register with, rather than each spawning their own process:

Current:   Claude Code → hook1 (wait) → hook2 (wait) → hook3 (wait) → proceed
Proposed:  Claude Code → Runtime Manager
                          ├── parallel: side-effect hooks (fire & forget)
                          ├── sequential: flow-control hooks (by priority)
                          └── single aggregated response → proceed

Benefits

  • Performance: Parallel dispatch for observe-only hooks could cut hook overhead by 50%+
  • Security: Explicit canBlock permissions prevent rogue plugins from hijacking tool calls
  • Scalability: The plugin ecosystem can grow without linearly degrading performance
  • Transparency: Users can see which hooks block, how often, and at what cost

Context

This was identified by auditing the data flow of 10 active plugin hooks across 7 event types. Happy to share the full hook data flow analysis if useful.

🤖 Generated with Claude Code

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗