Get featured

How to set up Claude Code hooks, with examples

Guide · checked against the docs on

Hooks are shell commands that Claude Code runs on its own at set moments, like right before it uses a tool or right after it edits a file. You can use them to format code, send yourself an alert, or stop a risky command. This guide shows where hooks go, the events you'll use most, what exit codes mean, two examples from Anthropic's docs, and the security rules. Everything here comes from Anthropic's hooks guide and hooks reference, read on October 15, 2026.

Not affiliated with or endorsed by Anthropic. Check Anthropic's current docs before relying on these details.

Our tool page: Claude Code

Where hooks go

Hooks live in a "hooks" object in a Claude Code settings file. Where you put them sets who they apply to. From the reference:

LocationScopeShareable
~/.claude/settings.jsonAll your projectsNo, local to your machine
.claude/settings.jsonSingle projectYes, can be committed to the repo
.claude/settings.local.jsonSingle projectNo, gitignored when Claude Code saves a setting to it

The reference says to type /hooks "in Claude Code to open a read-only browser for your configured hooks." It labels each hook with where it came from.

The events you'll use most

The reference lists many events. Two cover most needs:

Each hook has a matcher that picks which tools it runs for, like "Edit|Write" or "Bash".

What exit codes mean

Your hook tells Claude Code what happened through its exit code. From the reference:

The detail that matters most: "Without valid JSON on stdout, Claude Code treats exit code 1 as a non-blocking error, even though 1 is the conventional Unix failure code. If your hook is meant to enforce a policy, use exit 2."

Example: format files after every edit (NOT TESTED)

This is the guide's Prettier example. It uses PostToolUse with an Edit|Write matcher. The guide says to add it to .claude/settings.json in your project root:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

The guide notes: "When the hook succeeds, Claude Code shows nothing in the conversation." To check that it worked, look for the edited file being reformatted.

Example: block rm commands (NOT TESTED)

This script is from the reference. Registered as a PreToolUse hook on Bash, it blocks commands that start with rm by exiting 2. Every other command goes through the normal permission flow:

#!/bin/bash
# Reads JSON input from stdin, checks the command
input=$(cat)
command=$(jq -r '.tool_input.command' <<<"$input")
if [[ "$command" == rm* ]]; then
  echo "Blocked: rm commands are not allowed" >&2
  exit 2 # Blocking error: tool call is prevented
fi
exit 0 # No decision: the normal permission flow applies

The reference also explains why exit 0 here doesn't mean "allow": "Exit code 0 with no output means the hook has no decision to report, so the tool call continues through the normal permission flow. The hook can deny the call, but staying silent doesn't approve it."

Security: read this before adding any hook

The reference's disclaimer, word for word: "Command hooks execute shell commands with your full user permissions. They can modify, delete, or access any files your user account can access. Review and test all hook commands before adding them to your configuration."

Its security checklist:

Watch out for other people's repos. A project's .claude/settings.json can hold hooks, and it can be committed. In an interactive session, the reference says Claude Code holds hooks back "until you accept the workspace trust dialog for the folder." But in -p or SDK sessions, it "never shows the dialog and treats the folder as trusted, so hooks committed in a repository's .claude/settings.json run in a folder you've never trusted." Before you run claude -p on a repo you didn't write, the reference says to "review its .claude/ settings files, start with --bare, or turn hooks off for that run".

Hooks are an extra safety layer, not a full one. For keeping secrets out of reach in the first place, see our guide to keeping secrets safe with AI coding tools. For project instructions, see our AGENTS.md and CLAUDE.md guide, and for connecting outside tools, our MCP setup guide.

Not affiliated with or endorsed by Anthropic. Check Anthropic's current docs before relying on these details.