BeClaude
Documentation2026-04-01

Claude Code Hooks: Complete Documentation and Reference

Learn everything about Claude Code hooks — pre-action and post-action hooks, configuration, practical examples, and best practices for automating your development workflow.

Quick Answer

Claude Code hooks let you run custom shell commands before or after Claude performs actions like file edits, command execution, or tool calls. Configure hooks in your `.claude/settings.json` file to automate workflows like running linters, formatting code, or triggering deployments.

claude-codehooksautomationcli

What are Claude Code Hooks?

Hooks are shell commands that execute automatically in response to events in Claude Code. They allow you to integrate custom automation into your AI-assisted development workflow. Hooks run before (pre) or after (post) specific actions, giving you fine-grained control over how Claude Code interacts with your project.

Hook Types

Pre-Action Hooks

Pre-action hooks run before Claude Code performs an action. They can be used to:

  • Validate changes before they happen
  • Set up environment requirements
  • Prevent unwanted actions by returning a non-zero exit code
  • Prepare context or state

Post-Action Hooks

Post-action hooks run after Claude Code completes an action. They are useful for:

  • Running linters and formatters on changed files
  • Triggering builds or tests
  • Sending notifications
  • Updating documentation
  • Committing changes to version control

Configuration

Hooks are configured in your project's .claude/settings.json file:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "echo 'About to modify a file'"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "npx prettier --write $CLAUDE_FILE_PATH"
      }
    ],
    "Notification": [
      {
        "command": "osascript -e 'display notification \"Claude Code finished\" with title \"BeClaude\"'"
      }
    ],
    "Stop": [
      {
        "command": "echo 'Claude Code session ended'"
      }
    ]
  }
}

Hook Events

EventWhen it firesUse case
PreToolUseBefore a tool is usedValidate inputs, block certain actions
PostToolUseAfter a tool is usedFormat code, run linters
NotificationWhen Claude sends a notificationCustom alerts, logging
StopWhen Claude stops generatingCleanup, final checks

Matcher Patterns

Matchers use regex patterns to filter which tools trigger the hook:

  • Edit|Write — Match file modification tools
  • Bash — Match shell command execution
  • .* — Match all tools
  • Read — Match file reads

Environment Variables

Hooks receive these environment variables:

  • CLAUDE_TOOL_NAME — The name of the tool being used
  • CLAUDE_FILE_PATH — The file path (for file-related tools)
  • CLAUDE_SESSION_ID — The current session identifier

Practical Examples

1. Auto-format on File Changes

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
      }
    ]
  }
}

2. Lint Check Before Edits

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "npx eslint --no-warn-ignored \"$CLAUDE_FILE_PATH\" || exit 1"
      }
    ]
  }
}

3. Auto-run Tests After Changes

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "npm test -- --related \"$CLAUDE_FILE_PATH\" --passWithNoTests"
      }
    ]
  }
}

4. Desktop Notifications

{
  "hooks": {
    "Notification": [
      {
        "command": "osascript -e 'display notification \"$CLAUDE_TOOL_NAME completed\" with title \"Claude Code\"'"
      }
    ]
  }
}

5. Block Sensitive File Modifications

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "echo \"$CLAUDE_FILE_PATH\" | grep -qE '\\.(env|secret|key)$' && exit 1 || exit 0"
      }
    ]
  }
}

Best Practices

  • Keep hooks fast — Hooks run synchronously and block Claude Code while executing. Keep them under a few seconds.
  • Use graceful error handling — Append || true to commands that shouldn't block Claude's workflow.
  • Test hooks incrementally — Start with simple hooks and add complexity gradually.
  • Use matchers wisely — Be specific with matchers to avoid running hooks unnecessarily.
  • Document your hooks — Add comments in your settings file explaining what each hook does.
  • Consider project-level vs user-level — Put project-specific hooks in .claude/settings.json and personal preferences in ~/.claude/settings.json.
  • Handle edge cases — Account for missing files, network issues, and other failure modes.

Troubleshooting

Hooks not running:
  • Verify the JSON syntax in your settings file is valid
  • Check that the command is executable (try running it manually)
  • Ensure the matcher pattern matches the tool name
Hooks blocking Claude:
  • Pre-hooks returning non-zero exit codes will block the action
  • Use || true to prevent accidental blocking
  • Check hook command output for errors
Performance issues:
  • Profile your hooks with time to identify slow commands
  • Consider using incremental tools (e.g., --related flags for test runners)
  • Avoid hooks that trigger full project scans