Claude Code hooks documentation: a practical guide

Use current Claude Code hooks documentation to choose events, matchers, handlers, outputs, and safe test steps for reliable workflow…

A hand-drawn Claude Code hook path from selecting an event through matching, handling, deciding, testing, and monitoring.

Design a reliable lifecycle hook

The flow moves from event and match selection through handler, decision, testing, and monitoring.

  1. Event
  2. Match
  3. Handle
  4. Decide
  5. Test
  6. Monitor

Better Design

On this page

Direct answer

Claude Code hooks documentation describes handlers that run at defined points in a Claude Code session. A hook can validate a tool call before it runs, format a file after an edit, send a notification, add context, or record an event. Start with one narrow command hook, test its input and output, and keep normal permission checks in place.

Summary

Choose the lifecycle event, narrow it with a matcher and optional condition, then run the smallest suitable handler. Parse the event JSON as untrusted input. Return only the documented output for that event. Test allowed, denied, failed, malformed, and timeout paths. Roll out locally before sharing a project or organization hook.

What Claude Code hooks are

A Claude Code hook is a user-defined handler that runs automatically when a matching lifecycle event fires. Command hooks provide deterministic automation because a configured command runs when the condition matches. Prompt and agent hooks can use a model for judgment, so their result is not deterministic in the same sense. HTTP and MCP tool hooks send the event to another supported handler type.

Choose the right extension point

Hook
run or evaluate something at a specific lifecycle point.
Permission rule
enforce the supported allow, ask, or deny policy for a tool or command pattern.
CLAUDE.md or rule file
give persistent project instructions and context.
Skill
package instructions and executable commands that Claude can use for a task.
Subagent
delegate work into a separate context with its own tools and instructions.
Plugin
package hooks, skills, agents, commands, or MCP integrations for distribution.

How to use Claude Code hooks documentation

  1. Event: the lifecycle point, such as `PreToolUse`, `PostToolUse`, `Notification`, `Stop`, or `SessionStart`.
  2. Matcher group: an optional event-specific filter that selects tool names, notification types, session reasons, or other documented values.
  3. Condition: an optional `if` rule for supported tool events that narrows by tool name and arguments.
  4. Handler: a command, HTTP endpoint, MCP tool, prompt, or agent that receives the event.
  5. Input: event-specific JSON passed on standard input or through the handler's documented transport.
  6. Output: standard output, standard error, exit code, or structured JSON that Claude Code interprets for that event.
  7. Scope: the settings or component location that decides whether the hook is personal, project, local, managed, or packaged.

Use Anthropic's current hooks reference for exact events, schemas, outputs, and timeouts.

Build a safe first hook

A notification or narrow formatter is easier to verify than a permission decision. The official guide starts with a desktop notification. For a shared repository, a formatter after `Edit` or `Write` can also provide visible, reversible behavior when the team already uses that formatter.

  1. Choose one outcome, one event, and the narrowest matcher that represents it.
  2. Decide the scope. Use user settings for personal behavior, project settings for reviewed shared behavior, and local settings for project-specific experiments.
  3. Write the handler as a small script when logic, parsing, or quoting is more than trivial.
  4. Use `${CLAUDE_PROJECT_DIR}` for a project script and prefer exec form when paths or arguments need safe separation.
  5. Feed representative JSON to the handler manually and inspect its standard output, standard error, and exit code.
  6. Register the hook, open `/hooks`, and confirm the event, source, matcher, type, and command.
  7. Trigger the event in a disposable repository, inspect the result, then test failure and timeout behavior.
  8. Commit a shared hook only after another person reviews the script, dependencies, permissions, portability, and removal path.

Follow Anthropic's hook setup guide for current working examples.

Hook timing

Before an action
use `PreToolUse` when a tool call must be checked or changed before execution.
At a permission prompt
use `PermissionRequest` only when the documented interactive or SDK permission flow will create that prompt.
After an action
use `PostToolUse` for successful calls and `PostToolUseFailure` for failed calls. A post-action hook cannot undo the action.
After a batch
use `PostToolBatch` when the full set of parallel tool results matters.
Around a session
use `SessionStart`, `PreCompact`, `PostCompact`, or `SessionEnd` for supported setup, context, and cleanup tasks.
For people
use `Notification` to signal supported input, permission, authentication, or background-agent states.
For configuration and workspace changes
consider `InstructionsLoaded`, `ConfigChange`, `CwdChanged`, `FileChanged`, or worktree events.

The event list is versioned and now extends beyond the older set found in many tutorials. Avoid a fixed event count in lasting documentation. Link to the current reference and record the minimum Claude Code version when a matcher or event needs one.

Handler types

Command
prefer it for deterministic local validation, formatting, logging, or policy checks.
HTTP
post event JSON to a controlled service. Return the documented JSON body; an HTTP error status alone does not block a tool.
MCP tool
call an already connected MCP tool when the integration belongs there.
Prompt
use a single model decision when the event input contains enough evidence but a rule cannot express the judgment.
Agent
use an experimental multi-turn verifier only when it must inspect files or run tools. Prefer command hooks for stable production checks.

Treat hook input and output as an interface

Parse JSON instead of searching raw strings. Validate the event name, tool name, expected fields, path, and command shape. Handle absent fields and new fields safely. Keep diagnostic text on standard error when standard output must contain structured JSON. Return the event-specific decision format exactly; output fields that work for one event may not work for another.

A successful command with no output normally reports no decision and leaves the normal flow in place. Some events use exit code 2 or structured JSON to block. The exact effect depends on the event, so copy neither an exit-code rule nor a JSON decision across events without checking the reference.

Expect matching hooks to run in parallel

Claude Code runs matching hooks and then merges their results. A denial from one hook does not prevent sibling hooks from producing side effects. For `PreToolUse`, the most restrictive permission result wins. Avoid multiple hooks that rewrite the same tool input because the last completion wins and execution order is not deterministic.

Useful hook patterns

  • Format only the file that a successful edit changed, then report formatter failures clearly.
  • Block a protected path before an edit and return a short reason that helps Claude choose another approach.
  • Notify the user when an approved notification type says input is required.
  • Record configuration changes in an append-only audit destination without placing secrets in the log.
  • Restore approved context after compaction, while keeping stable project rules in the normal instruction files.
  • Reload a controlled environment when the working directory changes, without printing secret values into context.
  • Run narrow tests after relevant edits instead of starting the whole suite after every tool call.

Security and policy checklist

  • Treat repository hook configuration and scripts as executable code. Review them before enabling the project.
  • Use supported permission rules for hard tool policy. The optional `if` filter is best effort and can fail open by running the hook.
  • Keep matchers and conditions narrow, but enforce the final authorization inside a reviewed policy boundary.
  • Limit any automatic permission approval to an exact, low-risk action and keep stronger deny rules active.
  • Keep secrets out of prompts, logs, command arguments, and unrestricted HTTP headers. Allow only required environment variables.
  • Constrain network destinations, file paths, subprocesses, time, output, retries, and concurrent effects.
  • Make handlers idempotent when an event can repeat, and provide rollback or cleanup for material side effects.
  • Use managed settings when an organization must enforce a hook that local users cannot disable.

Important limitations

  • Post-action hooks observe completed work and cannot reverse it.
  • PermissionRequest behavior differs between interactive, non-interactive, SDK, and background-agent paths.
  • Stop fires when Claude finishes a response, not only when the full task is complete.
  • Handler timeouts vary by type and event; shorter event-specific budgets can override the usual default.
  • Prompt and agent handlers consume model usage and can make variable decisions.
  • Shell commands inherit an environment and working directory. Use explicit paths, dependencies, encodings, and portability tests.

Debug a hook that does not work

  1. Open `/hooks` and confirm the hook loaded from the expected source under the expected event.
  2. Validate the settings JSON and remember that comments and trailing commas are invalid.
  3. Check the case-sensitive matcher and confirm the event actually fires in this interaction mode.
  4. Run the handler manually with representative JSON and inspect both the output and exit code.
  5. Confirm the script is executable and every dependency resolves in Claude Code's environment.
  6. Use an absolute path or project placeholder, or switch to exec form to avoid shell quoting problems.
  7. Inspect the Claude Code debug log, reproduce in a disposable repository, and reduce the hook to its smallest working form.

What current tutorials emphasize

Current tutorials focus on notifications, automatic formatting, testing, logging, and blocking dangerous commands. They are useful for seeing complete configurations. This guide adds current handler types, events, parallel resolution, and `if` filter limits. It also covers interaction modes, managed scope, interface validation, and rollout controls that a copied snippet may omit.

Install and verify Claude Code before adding lifecycle automation.

Read the subagents guide when the requirement is delegated work rather than a lifecycle hook.

Frequently asked questions