In this categoryClaude Code · 45
Claude CodeIntermediate

How to Set Up Hooks for Automation in Claude Code

Run shell commands automatically at key points in Claude Code's lifecycle: auto-format code, block dangerous commands, send notifications, and enforce project rules without manual intervention.

12 minIntermediate

Hooks are shell commands that run automatically at specific points in Claude Code's lifecycle, like after file edits or before command execution. They provide deterministic control over Claude Code's behavior, ensuring certain tasks always happen rather than relying on the model to choose to do them. Use hooks to auto-format code, block dangerous operations, send notifications, and enforce project conventions.

  • Claude Code CLI installed and a working project
  • Basic shell scripting knowledge (bash or sh)
  • A text editor to write hook configuration JSON
  • Optionally: Prettier, a code formatter (npm install -g prettier)

Understanding hook events and lifecycle

Hooks fire at specific moments in Claude Code's execution: when a session starts, before or after tools run, when files change, or when the model finishes working. You configure them in a settings file with a matcher to filter which hooks run on which events, and a command or HTTP endpoint to trigger.

  • SessionStart — fires when you start a Claude Code session; useful for injecting context or loading environment variables
  • PreToolUse — runs before any tool executes; use to block dangerous commands or validate input
  • PostToolUse — runs after a tool finishes; ideal for auto-formatting or validation
  • Notification — fires when Claude needs your input; useful for desktop alerts so you don't watch the terminal
  • FileChanged — runs when any file changes; good for reloading config like .env or .envrc

Example 1: Auto-format code with Prettier

The most common hook runs a code formatter after every edit. This example uses Prettier to format JavaScript, TypeScript, and other files automatically. Add this configuration to .claude/settings.json in your project root so it applies only to this repo.

.claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}
zsh - my-project
$claude
Edit a file; hook runs automatically after
Applied prettier to src/utils/format.ts
No manual formatting needed
$

Example 2: Block dangerous commands

Prevent Claude from running destructive commands like rm -rf by checking the command before execution. This bash script checks the input and exits with code 2 to block the operation if it matches a dangerous pattern.

.claude/hooks/protect-commands.sh
#!/bin/bash
# protect-commands.sh - block dangerous commands

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if echo "$COMMAND" | grep -qE "rm -rf|rm -r/|: /|(\|\s*sudo)"; then
  echo "Blocked: potentially destructive command" >&2
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Destructive command blocked for safety"
    }
  }'
  exit 2
fi

exit 0
.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ""$CLAUDE_PROJECT_DIR"/.claude/hooks/protect-commands.sh"
          }
        ]
      }
    ]
  }
}
Make hook scripts executable
If you create a separate hook script file like protect-commands.sh, run chmod +x .claude/hooks/protect-commands.sh on macOS and Linux. On Windows, store hooks in the same settings.json file using inline commands instead of external scripts.

Viewing and debugging your hooks

Claude Code provides a built-in hooks browser to inspect all registered hooks, see which event they fire on, and confirm they are loaded correctly. Type the /hooks slash command during a session to open it.

zsh - my-project
$claude
$/hooks
Hooks browser:
PostToolUse (1 hook configured)
Edit|Write → command: npx prettier --write
PreToolUse (1 hook configured)
Bash → command: .claude/hooks/protect-commands.sh
Press Esc to return; hooks are read-only. Edit settings.json to modify them.
$

Related guides

Watch related tutorials

Free weekly email

New guides in your inbox

Fresh step-by-step how-to guides as we publish them. One email a week, no more.

Tags
#hooks#automation#formatting#bash#settings#lifecycle-events