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

# Hooks

> Run shell commands, HTTP requests, or LLM prompts at key lifecycle events to automate logging, enforce policies, and extend Claude Code behavior.

Hooks let you attach commands, HTTP calls, or LLM prompts to lifecycle events inside Claude Code. Whenever a matching event fires—such as before a tool runs or when the session ends—your hook executes. Use hooks for audit logging, enforcing team policies, sending notifications, or any side effect that should run automatically alongside Claude.

## Hook events

Each hook is keyed by an **event name**. The full list of available events is:

| Event                | When it fires                                                        |
| -------------------- | -------------------------------------------------------------------- |
| `PreToolUse`         | Before a tool call is executed                                       |
| `PostToolUse`        | After a tool call completes successfully                             |
| `PostToolUseFailure` | After a tool call fails                                              |
| `Notification`       | When Claude Code emits a user-visible notification                   |
| `UserPromptSubmit`   | When the user submits a prompt                                       |
| `SessionStart`       | At the start of a new session (also fires on resume, clear, compact) |
| `SessionEnd`         | When the session ends                                                |
| `Stop`               | When Claude finishes a response turn                                 |
| `StopFailure`        | When a response turn ends in error                                   |
| `SubagentStart`      | When a sub-agent is spawned                                          |
| `SubagentStop`       | When a sub-agent finishes                                            |
| `PreCompact`         | Before context compaction                                            |
| `PostCompact`        | After context compaction                                             |
| `PermissionRequest`  | When a permission prompt is about to be shown                        |
| `PermissionDenied`   | When a permission request is denied                                  |
| `Setup`              | Early one-time setup phase                                           |
| `TeammateIdle`       | When a teammate agent becomes idle                                   |
| `TaskCreated`        | When a background task is created                                    |
| `TaskCompleted`      | When a background task completes                                     |
| `Elicitation`        | When an elicitation is triggered                                     |
| `ElicitationResult`  | When an elicitation result is received                               |
| `ConfigChange`       | When the configuration changes                                       |
| `WorktreeCreate`     | When a git worktree is created                                       |
| `WorktreeRemove`     | When a git worktree is removed                                       |
| `InstructionsLoaded` | When CLAUDE.md instructions are loaded                               |
| `CwdChanged`         | When the working directory changes                                   |
| `FileChanged`        | When a watched file changes                                          |

## Configuring hooks

Hooks are defined in a `hooks` key in any Claude Code settings file:

* **User settings**: `~/.claude/settings.json`
* **Project settings**: `.claude/settings.json`
* **Local settings**: `.claude/settings.local.json`
* **Managed settings**: `/etc/claude-code/managed-settings.json` (Linux) or MDM profile (macOS/Windows)

The `hooks` object is a map from event name to an array of **matcher** objects. Each matcher optionally filters by a string pattern (e.g., a tool name) and contains an array of hook commands.

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"About to run Bash\" >> /tmp/audit.log"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/usr/local/bin/notify-team.sh"
          }
        ]
      }
    ]
  }
}
```

You can also manage hooks interactively with the `/hooks` command inside a Claude Code session.

## Hook types

Claude Code supports four hook types.

<AccordionGroup>
  <Accordion title="command — shell command">
    Runs a shell command. The hook input is passed as JSON on stdin.

    ```json theme={null}
    {
      "type": "command",
      "command": "jq '.tool_name' >> /tmp/tools-used.log",
      "timeout": 10
    }
    ```

    | Field           | Description                                                                                       |
    | --------------- | ------------------------------------------------------------------------------------------------- |
    | `command`       | Shell command string to execute                                                                   |
    | `shell`         | `"bash"` (default) or `"powershell"`                                                              |
    | `timeout`       | Timeout in seconds (positive number)                                                              |
    | `if`            | Permission rule syntax filter (e.g., `"Bash(git *)"`) — hook runs only when the tool call matches |
    | `statusMessage` | Custom spinner message shown while the hook runs                                                  |
    | `once`          | Run once and remove after first execution                                                         |
    | `async`         | Run in the background without blocking                                                            |
    | `asyncRewake`   | Run in background; exit code 2 wakes the model with a blocking error                              |

    **Exit codes for `command` hooks:**

    * `0` — success, execution continues
    * `2` — blocks the operation and surfaces stderr to Claude as an error
    * Any other non-zero — shows stderr to the user only (non-blocking)
  </Accordion>

  <Accordion title="prompt — LLM prompt hook">
    Evaluates a prompt with an LLM. Use `$ARGUMENTS` in the prompt string to receive the hook input JSON.

    ```json theme={null}
    {
      "type": "prompt",
      "prompt": "Does this tool call look safe? $ARGUMENTS\nRespond with {ok: true} or {ok: false, reason: '...'}",
      "timeout": 30
    }
    ```

    | Field           | Description                                                                  |
    | --------------- | ---------------------------------------------------------------------------- |
    | `prompt`        | Prompt string; use `$ARGUMENTS` to inject hook input JSON                    |
    | `model`         | Model to use (e.g., `"claude-sonnet-4-6"`); defaults to the small fast model |
    | `timeout`       | Timeout in seconds                                                           |
    | `if`            | Permission rule syntax filter                                                |
    | `statusMessage` | Custom spinner message                                                       |
    | `once`          | Run once and remove                                                          |
  </Accordion>

  <Accordion title="agent — agentic verifier hook">
    Runs a multi-turn LLM agent to verify a condition. The agent must call a structured output tool with `{ok: boolean, reason?: string}`.

    ```json theme={null}
    {
      "type": "agent",
      "prompt": "Verify that all unit tests passed before this commit is allowed.",
      "timeout": 60
    }
    ```

    | Field           | Description                                                         |
    | --------------- | ------------------------------------------------------------------- |
    | `prompt`        | Description of what to verify; use `$ARGUMENTS` for hook input JSON |
    | `model`         | Model to use; defaults to Haiku                                     |
    | `timeout`       | Timeout in seconds (default 60)                                     |
    | `if`            | Permission rule syntax filter                                       |
    | `statusMessage` | Custom spinner message                                              |
    | `once`          | Run once and remove                                                 |
  </Accordion>

  <Accordion title="http — HTTP webhook hook">
    POSTs the hook input JSON to a URL. Useful for sending events to external systems.

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

    | Field            | Description                                                         |
    | ---------------- | ------------------------------------------------------------------- |
    | `url`            | URL to POST the hook input JSON to                                  |
    | `headers`        | Additional headers; values may reference `$VAR_NAME` env vars       |
    | `allowedEnvVars` | Explicit list of env var names allowed for interpolation in headers |
    | `timeout`        | Timeout in seconds                                                  |
    | `if`             | Permission rule syntax filter                                       |
    | `statusMessage`  | Custom spinner message                                              |
    | `once`           | Run once and remove                                                 |

    <Warning>
      Only env vars explicitly listed in `allowedEnvVars` are interpolated. All other `$VAR` references in headers resolve to empty strings.
    </Warning>
  </Accordion>
</AccordionGroup>

## Matcher patterns

The `matcher` field on a hook entry filters which invocations trigger the hook. It is matched against values relevant to the event—most often the tool name for `PreToolUse` / `PostToolUse` events.

The `if` field inside an individual hook command provides finer-grained filtering using permission rule syntax (e.g., `"Bash(git *)"` or `"Read(*.ts)"`). A hook with an `if` condition only runs when the tool call matches that pattern.

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "./audit.sh",
            "if": "Bash(rm *)"
          }
        ]
      }
    ]
  }
}
```

## Environment variables in hook scripts

Shell command hooks (`type: "command"`) inherit the full process environment plus the following additional variables:

| Variable                     | Description                                                                                                                                                                                        |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLAUDE_PROJECT_DIR`         | Absolute path to the project root directory                                                                                                                                                        |
| `CLAUDE_ENV_FILE`            | Path to a `.sh` file your hook can write `export KEY=VALUE` lines into, injected into subsequent Bash tool commands. Set for `SessionStart`, `Setup`, `CwdChanged`, and `FileChanged` events only. |
| `CLAUDE_PLUGIN_ROOT`         | Plugin or skill base directory (when the hook comes from a plugin or skill)                                                                                                                        |
| `CLAUDE_PLUGIN_DATA`         | Plugin data directory (when the hook comes from a plugin)                                                                                                                                          |
| `CLAUDE_PLUGIN_OPTION_<KEY>` | Plugin configuration option values (uppercased)                                                                                                                                                    |

<Note>
  When running inside GitHub Actions with `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` set, sensitive credentials (e.g., `ANTHROPIC_API_KEY`, `AWS_SECRET_ACCESS_KEY`) are stripped from the hook subprocess environment to prevent prompt-injection exfiltration.
</Note>

## Example configurations

<CodeGroup>
  ```json Audit log for all tool calls theme={null}
  {
    "hooks": {
      "PreToolUse": [
        {
          "hooks": [
            {
              "type": "command",
              "command": "echo \"$(date -u) PreToolUse\" >> /var/log/claude-audit.log"
            }
          ]
        }
      ],
      "PostToolUse": [
        {
          "hooks": [
            {
              "type": "command",
              "command": "echo \"$(date -u) PostToolUse\" >> /var/log/claude-audit.log"
            }
          ]
        }
      ]
    }
  }
  ```

  ```json Block destructive Bash commands theme={null}
  {
    "hooks": {
      "PreToolUse": [
        {
          "matcher": "Bash",
          "hooks": [
            {
              "type": "command",
              "command": "echo \"Destructive command blocked\" >&2; exit 2",
              "if": "Bash(rm -rf *)"
            }
          ]
        }
      ]
    }
  }
  ```

  ```json Notify Slack on session stop theme={null}
  {
    "hooks": {
      "Stop": [
        {
          "hooks": [
            {
              "type": "http",
              "url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
              "timeout": 5
            }
          ]
        }
      ]
    }
  }
  ```

  ```json Load .envrc on session start theme={null}
  {
    "hooks": {
      "SessionStart": [
        {
          "hooks": [
            {
              "type": "command",
              "command": "[ -f .envrc ] && grep -E '^export ' .envrc >> \"$CLAUDE_ENV_FILE\""
            }
          ]
        }
      ]
    }
  }
  ```
</CodeGroup>

## Use cases

* **Audit logging** — record every tool call to a file or SIEM system
* **Policy enforcement** — block specific commands (exit code 2 surfaces an error to Claude)
* **Notifications** — send Slack or webhook messages when sessions complete
* **Environment setup** — load `.envrc` or inject credentials at session start via `CLAUDE_ENV_FILE`
* **Quality gates** — use `agent` hooks to verify tests pass before allowing commits

## Security considerations

<Warning>
  Hook commands run with the same OS privileges as Claude Code itself. Only configure hooks from sources you trust.
</Warning>

* **`allowManagedHooksOnly`** — when set to `true` in managed settings, only hooks from managed settings (MDM/`managed-settings.json`) run. User, project, and local hooks are silently ignored. This lets IT administrators restrict hook execution to approved scripts.
* **`disableAllHooks`** — setting this to `true` in any settings file disables all hooks and status line execution.
* **`allowedHttpHookUrls`** — an allowlist of URL patterns HTTP hooks may target. When set, HTTP hooks with non-matching URLs are blocked. Supports `*` as a wildcard (e.g., `"https://hooks.example.com/*"`).
* **`httpHookAllowedEnvVars`** — restricts which env vars HTTP hooks may interpolate into headers; the effective set is the intersection of this list and each hook's own `allowedEnvVars`.
* Hook scripts should validate their inputs. The JSON input is controlled by Claude Code but may reflect user-supplied content.
