Skip to main content
OrchestKit v7.43.0 — 104 skills, 36 agents, 173 hooks · Claude Code 2.1.105+
OrchestKit

106 Hooks: What Fires When

TypeScript functions that intercept every Claude Code lifecycle event -- blocking dangerous commands, injecting context, and syncing memory, all invisibly.

What Is a Hook?

A hook is a TypeScript function that runs automatically at specific moments in a Claude Code session. Hooks receive a JSON payload on stdin describing the event (which tool, what input, which session) and return a JSON response on stdout that either allows the operation, blocks it, or injects additional context.

You never call hooks yourself. Claude Code calls them for you -- on every tool use, every prompt, every session start and stop. They are the invisible guardians of your development workflow.

// The fundamental hook contract
type HookFn = (input: HookInput) => HookResult | Promise<HookResult>;

// Allow the operation silently
{ continue: true, suppressOutput: true }

// Block the operation with a reason
{ continue: false, stopReason: "Direct commits to main are not allowed." }

// Allow but inject guidance for Claude
{ continue: true, hookSpecificOutput: { additionalContext: "Consider using cursor-based pagination." } }

By the Numbers

CategoryCountDescription
Global hooks40Fire on every matching event regardless of agent
Agent-scoped hooks47Fire only when a specific agent is active
Skill-scoped hooks22Fire only during specific skill operations
Total109Registered in hooks.json, compiled into 12 split bundles

All 146 hooks are written in TypeScript, compiled via esbuild into ESM bundles, and executed by Node.js. Zero external dependencies in production.

Hook Events: The Full Timeline

Every Claude Code session follows the same lifecycle. Here is every event in the order it fires, and what OrchestKit does at each stage.

Setup

When: Plugin installation or first run.

Setup hooks handle first-run setup, maintenance checks, monorepo detection, and configuration repair.

SessionStart

When: A new Claude Code session begins.

5 hooks fire: a unified dispatcher (fire-and-forget) launches background tasks (pattern sync, coordination init), the session context loader reads prior state, the analytics consent checker runs, the PR status enricher loads context for --from-pr sessions, and the prefill guard scans for deprecated API patterns.

UserPromptSubmit

When: The user types a message and presses Enter.

13 hooks run on every prompt. The profile injector and memory context loader fire once (first prompt only). The context injector, todo enforcer, memory context searcher, satisfaction detector, communication style tracker, antipattern detector, antipattern warning, context pruning advisor, pipeline detector, intent capturer, and queue recovery handler run on each prompt.

PermissionRequest

When: Claude requests permission to use a tool.

3 hooks evaluate the request. Read/Glob/Grep operations are auto-approved (empty hook array -- Claude Code allows them). Safe bash commands (git status, npm test, ls) are auto-approved. Writes within the project directory are auto-approved, excluding node_modules, .git, and dist.

PreToolUse

When: After permission is granted, before the tool executes.

The largest group: hooks fire based on the tool matcher.

  • Bash (10 hooks): Dangerous command blocker, compound command validator, error pattern warner, issue docs requirement, multi-instance quality gate, default timeout setter, GitHub issue creation guide, license compliance, affected tests finder, agent browser safety.
  • Write|Edit (7 hooks): File guard, write headers injector, architecture change detector, security pattern validator, multi-instance lock, docstring enforcer, code quality gate.
  • Skill (1 hook): Skill usage tracker.
  • MCP (3 hooks): Context7 tracker, memory fabric initializer (once), memory validator.
  • Task (5 hooks): Agent block-writes, migration safety check, security command audit, CI safety check, deployment safety check.

PostToolUse

When: After a tool completes successfully.

10 hooks across three matchers:

  • Bash|Write|Edit|Task|Skill|NotebookEdit (3 hooks): Unified dispatcher (fire-and-forget, 7 analytics hooks), context budget monitor, unified error handler.
  • Write|Edit (6 hooks): File lock release, auto-lint, README sync, merge conflict predictor, coverage predictor, release lock on commit.
  • Bash (1 hook): Secret redactor.

PostToolUseFailure

When: A tool fails (nonzero exit code, write error, etc.).

1 hook: The failure handler logs the error, categorizes it, and provides recovery suggestions.

SubagentStart / SubagentStop

When: A subagent (Task) is spawned or completes.

  • SubagentStart (7 hooks): Context stager, graph memory inject, subagent validator, context gate, task linker, model cost advisor.
  • SubagentStop (7 hooks): Unified dispatcher (fire-and-forget), output validator, auto-spawn quality gate, multi-claude verifier, subagent quality gate, task completer, retry handler.

Notification

When: Claude Code emits a notification (permission prompt, idle, auth success).

2 hooks: A unified dispatcher for notification analytics, and a sound hook that plays audio alerts for permission prompts and idle notifications.

PreCompact

When: Context window is about to be compacted.

1 hook: The pre-compact saver preserves critical context (decisions, file list, key findings) before compaction discards conversation history.

ConfigChange

When: .claude/settings.json or project config changes mid-session (CC 2.1.50+).

Allows hooks to react to configuration updates without restarting the session -- for example, reloading permission rules or refreshing cached settings.

InstructionsLoaded

When: CLAUDE.md and .claude/rules/*.md files are loaded (CC 2.1.69+).

Fires after all project instructions have been parsed. Useful for hooks that need to validate or augment loaded instructions -- for example, checking for conflicting rules or injecting dynamic context based on instruction content.

TeammateIdle / TaskCompleted

When: Multi-agent coordination events fire (CC 2.1.33+).

  • TeammateIdle (1 hook): Progress reporter checks on idle teammates.
  • TaskCompleted (1 hook): Completion tracker records task outcomes.

WorktreeCreate / WorktreeRemove

When: A git worktree is created or removed (CC 2.1.50+).

These events fire on worktree lifecycle changes, enabling hooks to initialize or clean up worktree-specific state (coordination files, per-worktree caches, instance registration).

Stop

When: The user ends the session (/exit, Ctrl+C, or session timeout).

1 hook entry dispatches via fire-and-forget: a detached background worker runs 29 cleanup hooks in parallel after the session exits instantly. These cover context saving, memory sync, instance cleanup, security aggregation, and skill validation. See Lifecycle Hooks for the full breakdown.

SessionEnd

When: The session is formally ending (after Stop).

4 hooks: Coordination cleanup (unregister instance, release locks), session metrics summary, session cleanup (temp files), and pattern sync push (upload learned patterns).

Architecture: Split Bundles

OrchestKit does not load all hooks into memory for every event. Instead, esbuild compiles hooks into 11 event-specific bundles plus 1 unified bundle for CLI tools.

BundleSizeHooksLoaded When
permission.mjs8 KB3PermissionRequest
pretool.mjs48 KB26PreToolUse
posttool.mjs58 KB10PostToolUse
prompt.mjs57 KB13UserPromptSubmit
lifecycle.mjs31 KB9SessionStart / SessionEnd
stop.mjs33 KB29Stop
subagent.mjs56 KB14SubagentStart / SubagentStop
notification.mjs5 KB2Notification
setup.mjs24 KB9Setup
skill.mjs52 KB19Skill operations
agent.mjs8 KB5Agent operations
hooks.mjs (unified)324 KBallCLI tools only

Result: ~89% per-load savings. A typical hook invocation loads ~35 KB instead of 324 KB.

The CLI runner (bin/run-hook.mjs) maps hook name prefixes to bundles automatically:

const bundleMap = {
  permission: 'permission',
  pretool: 'pretool',
  posttool: 'posttool',
  prompt: 'prompt',
  lifecycle: 'lifecycle',
  stop: 'stop',
  'subagent-start': 'subagent',
  'subagent-stop': 'subagent',
  notification: 'notification',
  setup: 'setup',
  skill: 'skill',
  agent: 'agent',
};

How a Hook Executes

Every hook registration in hooks.json follows this pattern:

{
  "type": "command",
  "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/bin/run-hook.mjs pretool/bash/dangerous-command-blocker"
}

Claude Code pipes the event payload to stdin, and the runner:

  1. Parses the hook name from process.argv[2]
  2. Maps the prefix (pretool) to the correct bundle (pretool.mjs)
  3. Dynamic-imports the bundle
  4. Looks up the hook function by its full name
  5. Calls the function with the parsed input
  6. Writes the HookResult JSON to stdout

For fire-and-forget hooks, a separate silent runner (run-hook-silent.mjs) is used, and for Stop events, stop-fire-and-forget.mjs spawns a detached background worker.

Hook Types

Most hooks use "type": "command" to spawn a shell command. Two additional types exist:

TypeBehaviorExample
"command"Spawn a shell command, pipe JSON via stdin/stdoutAll blocking and fire-and-forget hooks
"http"POST JSON to a URL instead of spawning a process (CC 2.1.69+)12 native HTTP hooks for analytics, webhooks, and external integrations

Native HTTP hooks ("type": "http") send the hook input as a JSON POST body to the configured URL. They avoid the overhead of spawning a Node.js process, making them ideal for lightweight telemetry and webhook integrations.

Special Hook Flags

Some hooks in hooks.json have additional flags:

FlagMeaningExample
"once": trueRun only on the first matching event, then auto-remove (CC 2.1.69+)13 skill context loaders that inject context on first fire only
"async": trueRun in background without blockingAnalytics dispatchers
"timeout": 30Maximum execution time in secondsNetwork I/O hooks

Mental Model: Invisible Guardians

Think of hooks as a security and productivity layer that wraps every action Claude takes:

  • Before a bash command runs, the dangerous command blocker checks for rm -rf /, git push --force, and pipe-to-shell attacks.
  • Before a file is written, the file guard blocks modifications to .env, .pem, and credential files.
  • On every prompt, the memory context hook searches the knowledge graph for relevant past decisions.
  • When a session ends, 29 background hooks save context, sync memory, and clean up coordination state -- without making the user wait.

You get all of this automatically. No configuration required. The hooks are registered in hooks.json and fire based on matcher patterns that Claude Code evaluates against the current tool name.

To learn about individual hook categories in depth, continue to Lifecycle Hooks, Safety Hooks, and Memory Hooks. To build your own hook, see Writing Hooks.

Edit on GitHub

Last updated on