> ## Documentation Index
> Fetch the complete documentation index at: https://cisco-ea52c096.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Hooks

> Run scripts automatically before or after Claude Code performs actions. Use hooks for formatting, safety checks, logging, and more.

## What are hooks?

Hooks are scripts you configure to run automatically at specific points in Claude Code's execution — before a tool runs, after it completes, when a session starts, and so on. You can use hooks to:

* Auto-format files after Claude edits them
* Run tests after code changes
* Log every tool call for auditing
* Block commands that match a pattern
* Send notifications when a session ends

Hooks are configured in your `settings.json` (global or project-level) under the `hooks` key.

## Hook events

Each hook is tied to an **event**. Claude Code emits the following events:

| Event | When it fires |
| - | - |
| `PreToolUse` | Before a tool is invoked |
| `PostToolUse` | After a tool completes successfully |
| `PostToolUseFailure` | After a tool fails |
| `Notification` | When Claude sends a notification |
| `UserPromptSubmit` | When you submit a prompt |
| `SessionStart` | When a session begins |
| `SessionEnd` | When a session ends |
| `Stop` | When Claude stops generating |
| `StopFailure` | When Claude stops due to an error |
| `SubagentStart` | When a sub-agent starts |
| `SubagentStop` | When a sub-agent stops |
| `PreCompact` | Before context is compacted |
| `PostCompact` | After context is compacted |
| `PermissionRequest` | When Claude requests a permission |
| `PermissionDenied` | When a permission is denied |
| `Setup` | During initial setup |
| `FileChanged` | When a file is changed |
| `CwdChanged` | When the working directory changes |
| `InstructionsLoaded` | When project instructions are loaded |
| `ConfigChange` | When settings change |

## Configuration format

Hooks are defined per event as an array of **matchers**. Each matcher optionally filters by tool name, then runs one or more hook actions.

```json theme={null}
{
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<optional tool name pattern>",
        "hooks": [
          { "type": "command", "command": "<shell command>" }
        ]
      }
    ]
  }
}
```

<Note>
  The `matcher` field is optional. When omitted, the hook runs for every occurrence of that event regardless of which tool triggered it.
</Note>

## Hook types

Claude Code supports four hook types:

<AccordionGroup>
  <Accordion title="command — run a shell command">
    Executes a shell command. This is the most common hook type.

    ```json theme={null}
    {
      "type": "command",
      "command": "prettier --write $CLAUDE_TOOL_OUTPUT",
      "shell": "bash",
      "timeout": 30,
      "statusMessage": "Formatting...",
      "async": false
    }
    ```

    | Field | Description |
    | - | - |
    | `command` | The shell command to run |
    | `shell` | `"bash"` (default) or `"powershell"` |
    | `timeout` | Maximum seconds to wait (optional) |
    | `statusMessage` | Text shown in the spinner while the hook runs |
    | `if` | Permission rule syntax to filter when this hook fires (e.g. `"Bash(git *)"`) |
    | `once` | If `true`, removes itself after running once |
    | `async` | If `true`, runs in the background without blocking Claude |
    | `asyncRewake` | If `true`, runs in the background and wakes the model when the command exits with code `2` |
  </Accordion>

  <Accordion title="prompt — evaluate with an LLM">
    Sends a prompt to a model for evaluation. The model's response can block or modify tool execution.

    ```json theme={null}
    {
      "type": "prompt",
      "prompt": "Check if this change looks safe: $ARGUMENTS",
      "model": "claude-sonnet-4-6",
      "timeout": 60,
      "statusMessage": "Safety check..."
    }
    ```

    Use `$ARGUMENTS` in the prompt to inject the hook's input JSON. If no model is specified, Claude Code uses a small, fast model.
  </Accordion>

  <Accordion title="agent — run an agentic verifier">
    Spawns a small agent to verify the action. Useful for complex validation that needs multiple steps.

    ```json theme={null}
    {
      "type": "agent",
      "prompt": "Verify that unit tests ran and passed.",
      "model": "claude-sonnet-4-6",
      "timeout": 120,
      "statusMessage": "Verifying tests..."
    }
    ```

    If no model is specified, Claude Code uses Haiku. Defaults to a 60-second timeout.
  </Accordion>

  <Accordion title="http — POST to a URL">
    POSTs the hook input as JSON to an HTTP endpoint.

    ```json theme={null}
    {
      "type": "http",
      "url": "https://hooks.example.com/claude-events",
      "headers": {
        "Authorization": "Bearer $MY_TOKEN"
      },
      "allowedEnvVars": ["MY_TOKEN"],
      "timeout": 10,
      "statusMessage": "Logging event..."
    }
    ```

    Environment variable interpolation in header values only works for variables listed in `allowedEnvVars`.
  </Accordion>
</AccordionGroup>

## The /hooks command

Run `/hooks` in a session to open the interactive hooks configuration UI. From there you can:

* Browse all configured hook events
* Add, edit, or remove hook matchers
* Enable or disable individual hooks

## Examples

### Format files after edits

Run Prettier on any file Claude writes or edits:

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write \"$CLAUDE_TOOL_INPUT_PATH\"",
            "statusMessage": "Formatting file..."
          }
        ]
      }
    ]
  }
}
```

### Run tests after code changes

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "npm test --passWithNoTests",
            "async": true,
            "statusMessage": "Running tests..."
          }
        ]
      }
    ]
  }
}
```

### Audit log every tool call

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "http",
            "url": "https://audit.example.com/claude",
            "headers": { "Authorization": "Bearer $AUDIT_TOKEN" },
            "allowedEnvVars": ["AUDIT_TOKEN"],
            "async": true
          }
        ]
      }
    ]
  }
}
```

### Safety check before shell commands

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "The model wants to run this shell command: $ARGUMENTS. Is it safe? Reply BLOCK if it looks dangerous, otherwise ALLOW.",
            "statusMessage": "Safety check..."
          }
        ]
      }
    ]
  }
}
```

### Notify on session end

```json theme={null}
{
  "hooks": {
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Session complete\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
```

<Warning>
  Setting `disableAllHooks: true` in `settings.json` disables all hooks and status line execution for that settings scope.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.