--- name: hooks-reference description: CC hooks API — event types, payload shapes, exit codes, and where hooks run. layer: reference cc_feature: hooks source: https://docs.claude.com/en/docs/claude-code/hooks concept: hooks-api-surface last_verified: 2026-04-18 ngram_overlap_score: null review_status: approved --- # Hooks — Reference Hooks are shell commands or scripts that the Claude Code harness runs in response to events. They give the harness — not Claude — the final say on whether a tool call, prompt, or session action proceeds. Claude cannot bypass a hook by prompting itself; the hook runs outside the model's control loop. ## Event types - **UserPromptSubmit** — fires when the user sends a prompt. Runs before Claude processes it. Common use: inject extra context, reject disallowed prompts. - **PreToolUse** — fires before a tool call. Can deny the call. Common use: block destructive commands, require confirmation. - **PostToolUse** — fires after a tool call completes. Sees the result. Common use: log side effects, redact output, trigger follow-up work. - **Stop** — fires when the agent finishes a turn. Common use: commit reminders, session summaries. - **Notification** — fires when Claude wants to show the user a notification (e.g., long-running task). - **SessionStart** — fires when a session begins. Common use: print repo state, inject context. ## Payload shape Hooks receive a JSON payload on stdin. Common fields: - `session_id` — the current session identifier. - `transcript_path` — path to the conversation transcript. - `cwd` — current working directory. - `tool_name` (PreToolUse, PostToolUse) — which tool is running. - `tool_input` (PreToolUse) — the arguments to the tool. - `tool_response` (PostToolUse) — the tool's result. - `prompt` (UserPromptSubmit) — the submitted text. Exact field availability depends on event type. Read the payload JSON rather than assuming a schema. ## Exit codes and control Hooks communicate back via exit code and stdout JSON: - Exit 0, no stdout → proceed normally. - Exit 0, stdout JSON with `decision` field → harness honors the decision (e.g., `{"decision": "block", "reason": "..."}`). - Exit non-zero → harness treats as a denial or error, depending on event and hook type. Some hook types support structured output beyond deny/allow (e.g., adding context to the prompt). Details differ per event. ## Where hooks live - Project hooks: `.claude/settings.json` `hooks` field, paths relative to project. - User hooks: `~/.claude/settings.json` (global). - Plugin hooks: packaged with a plugin, activated when the plugin is enabled. Hooks run in the harness process's shell, not in Claude's tool-use sandbox. They can spawn subprocesses, read environment variables, and touch the filesystem. ## Implications for architecture - Hooks are the mechanism for **deterministic policy** (things that must always or never happen, regardless of what Claude decides). - Hooks are load-bearing for security: prompt-injection-resistant defenses live here, not in prompts. - Hooks add latency to every tool call they gate — keep them fast. - Hook output is part of the context window; verbose hooks burn tokens quickly.