---
title: "Claude Code Hooks: Exhaustive Reference"
description: "This document provides a comprehensive reference for the Claude Code hooks system, including all hook event types, JSON schemas, edge cases, known bugs, and undocumented behaviors."
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/claude-code-hooks
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:13:54.608Z
license: CC-BY-4.0
attribution: "Claude Code Hooks: Exhaustive Reference — Claudary (https://claudary.paisolsolutions.com/skills/claude-code-hooks)"
---

# Claude Code Hooks: Exhaustive Reference
This document provides a comprehensive reference for the Claude Code hooks system, including all hook event types, JSON schemas, edge cases, known bugs, and undocumented behaviors.

## Overview

# Claude Code Hooks: Exhaustive Reference

This document provides a comprehensive reference for the Claude Code hooks system, including all hook event types, JSON schemas, edge cases, known bugs, and undocumented behaviors.

**Last Updated:** January 2026
**Claude Code Version Coverage:** v1.0.38 through v2.1.1

---

## Table of Contents

1. [Hook Event Types](#hook-event-types)
2. [Tool Names and Input Schemas](#tool-names-and-input-schemas)
3. [Configuration Format](#configuration-format)
4. [Hook Input JSON Schema](#hook-input-json-schema)
5. [Hook Output JSON Schema](#hook-output-json-schema)
6. [Permission Decision Types](#permission-decision-types)
7. [Exit Code Behavior](#exit-code-behavior)
8. [Error Handling](#error-handling)
9. [Async and Parallel Execution](#async-and-parallel-execution)
10. [Version History and Changelog](#version-history-and-changelog)
11. [Known Bugs and Issues](#known-bugs-and-issues)
12. [Edge Cases and Gotchas](#edge-cases-and-gotchas)
13. [Undocumented Behavior](#undocumented-behavior)

---

## Hook Event Types

Claude Code provides **11 hook events** covering the complete session lifecycle:

| Event                  | Trigger                          | Matcher Support | Primary Use Cases                           |
| ---------------------- | -------------------------------- | --------------- | ------------------------------------------- |
| **PreToolUse**         | Before tool execution            | Yes             | Validation, modification, approval/denial   |
| **PostToolUse**        | After successful tool completion | Yes             | Logging, formatting, analysis               |
| **PostToolUseFailure** | After tool execution fails       | Yes             | Error handling, retry logic                 |
| **PermissionRequest**  | Before permission dialog shown   | Yes             | Auto-approve/deny permission requests       |
| **UserPromptSubmit**   | When user submits a prompt       | No              | Context injection, prompt validation        |
| **Notification**       | When Claude sends notifications  | Partial         | Logging, custom reactions                   |
| **Stop**               | Main agent finishes responding   | No              | Completeness validation, force continuation |
| **SubagentStop**       | Subagent finishes                | No              | Task validation, output quality checks      |
| **SubagentStart**      | Subagent spawns (v2.0.64+)       | No              | Agent lifecycle tracking                    |
| **PreCompact**         | Before context compaction        | No              | Transcript backup, context preservation     |
| **SessionStart**       | Session begins or resumes        | No              | Environment setup, context loading          |
| **SessionEnd**         | Session terminates               | No              | Cleanup, state saving, logging              |

### Event Details

#### PreToolUse
- **When:** After Claude creates tool parameters, before execution
- **Can:** Block, allow, modify tool inputs, request user confirmation
- **Introduced:** v2.0.38
- **Input modification:** v2.0.10+

#### PostToolUse
- **When:** Immediately after a tool completes successfully
- **Can:** Provide feedback to Claude, log results, trigger follow-up actions
- **Note:** `tool_result` field available in input

#### PostToolUseFailure
- **When:** After a tool execution fails
- **Can:** Handle errors, suggest retries
- **Documentation:** Sparse; mentioned in Agent SDK but not main hooks docs

#### PermissionRequest
- **When:** Before permission dialog is shown to user
- **Can:** Auto-approve or deny on behalf of user
- **Introduced:** v2.0.45
- **Warning:** Race condition bug exists (see [Known Bugs](#known-bugs-and-issues))

#### UserPromptSubmit
- **When:** User submits a prompt, before Claude processes it
- **Can:** Block prompts, inject context via `additionalContext`
- **Note:** stdout is added to context (unlike other hooks)

#### Notification
- **When:** Claude Code sends a notification
- **Matchers:** `permission_prompt` and other notification types
- **Payload includes:** `message`, `notification_type`

#### Stop / SubagentStop
- **When:** Agent/subagent finishes responding
- **Can:** Force continuation, validate completeness
- **Split:** v2.0.42 separated Stop and SubagentStop

#### SubagentStart
- **When:** Subagent spawns via Task tool
- **Introduced:** v2.0.64 (November 19, 2025)
- **Payload:** `agent_id`, `parent_agent_id`, `subagent_type`, `description`

#### PreCompact
- **When:** Before context compaction/summarization
- **Use:** Last chance to preserve critical information
- **Introduced:** v2.0.30

#### SessionStart / SessionEnd
- **When:** Session lifecycle boundaries
- **SessionStart special:** Can persist variables via `$CLAUDE_ENV_FILE`
- **SessionEnd:** Supports `systemMessage` (v2.1.0+)

---

## Tool Names and Input Schemas

Claude Code has **16+ built-in tools**. Hook matchers must use exact tool names (case-sensitive).

### Complete Tool List

#### File Operations
| Tool             | Description                          | Key Input Parameters                                                                                                 |
| ---------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| **Read**         | Read files (images, PDFs, notebooks) | `file_path`, `offset?`, `limit?`                                                                                     |
| **Write**        | Create/overwrite files               | `file_path`, `content`                                                                                               |
| **Edit**         | Single find-and-replace              | `file_path`, `old_string`, `new_string`, `replace_all?`                                                              |
| **MultiEdit**    | Multiple sequential edits            | `file_path`, `edits[]` (array of edit operations)                                                                    |
| **NotebookEdit** | Edit Jupyter cells                   | `notebook_path`, `new_source`, `cell_id?`, `cell_type?`, `edit_mode?`                                                |
| **LS**           | List directory contents              | `path`, `ignore?`                                                                                                    |
| **Glob**         | File pattern matching                | `pattern`, `path?`                                                                                                   |
| **Grep**         | Content search (ripgrep)             | `pattern`, `path?`, `output_mode?`, `glob?`, `type?`, `-A?`, `-B?`, `-C?`, `-i?`, `-n?`, `multiline?`, `head_limit?` |

#### Execution
| Tool           | Description                 | Key Input Parameters                                        |
| -------------- | --------------------------- | ----------------------------------------------------------- |
| **Bash**       | Shell commands              | `command`, `description?`, `timeout?`, `run_in_background?` |
| **BashOutput** | Get background shell output | `bash_id`, `filter?`                                        |
| **KillShell**  | Terminate background shell  | `shell_id`                                                  |

#### Web
| Tool          | Description            | Key Input Parameters                            |
| ------------- | ---------------------- | ----------------------------------------------- |
| **WebFetch**  | Fetch and analyze URLs | `url`, `prompt`                                 |
| **WebSearch** | Web search             | `query`, `allowed_domains?`, `blocked_domains?` |

#### Task Management
| Tool             | Description                 | Key Input Parameters                               |
| ---------------- | --------------------------- | -------------------------------------------------- |
| **Task**         | Launch subagents            | `subagent_type`, `prompt`, `description`           |
| **TodoWrite**    | Manage task lists           | `todos[]` (with `content`, `status`, `activeForm`) |
| **ExitPlanMode** | Exit planning mode          | `plan`                                             |
| **Skill**        | Execute user-defined skills | `skill`, `args?`                                   |
| **SlashCommand** | Execute slash commands      | `command`                                          |

#### IDE Integration
| Tool               | Description              | Key Input Parameters |
| ------------------ | ------------------------ | -------------------- |
| **getDiagnostics** | VS Code diagnostics      | `uri?`               |
| **executeCode**    | Jupyter kernel execution | `code`               |

### MCP Tool Naming Convention

MCP (Model Context Protocol) tools follow this pattern:
```
mcp__<server_name>__<tool_name>
```

Examples:
- `mcp__github__create_issue`
- `mcp__memory__retrieve_memory`
- `mcp__filesystem__read_file`

Matcher patterns for MCP tools:
```json
"matcher": "mcp__memory__.*"      // All tools from memory server
"matcher": "mcp__.*"              // All MCP tools
"matcher": "mcp__github__create_issue"  // Specific tool
```

---

## Configuration Format

### Configuration Locations (Precedence Order)

1. `.claude/settings.local.json` (local, not committed)
2. `.claude/settings.json` (project-level, shared)
3. `~/.claude/settings.json` (user-level)

### Settings File Format

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/script.sh",
            "timeout": 60
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Verify all tasks are complete: $ARGUMENTS",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
```

### Plugin Format (hooks/hooks.json)

```json
{
  "description": "Brief explanation (optional)",
  "hooks": {
    "PreToolUse": [...],
    "Stop": [...]
  }
}
```

### Hook Types

| Type      | Description                  | Default Timeout |
| --------- | ---------------------------- | --------------- |
| `command` | Bash command execution       | 60 seconds      |
| `prompt`  | LLM-based evaluation (Haiku) | 30 seconds      |

### Matcher Syntax

| Pattern             | Matches                          |
| ------------------- | -------------------------------- |
| `"Write"`           | Exact match (case-sensitive)     |
| `"Write\\|Edit"`     | Pipe OR: Write or Edit           |
| `"*"` or `""`       | All tools                        |
| `"Bash(npm test*)"` | Argument patterns with wildcards |
| `"mcp__memory__.*"` | Regex patterns                   |

**Important:** Matchers are case-sensitive. `"bash"` will NOT match `"Bash"`.

### Configuration Options

| Field     | Type    | Default  | Description                       |
| --------- | ------- | -------- | --------------------------------- |
| `matcher` | string  | `"*"`    | Tool name pattern                 |
| `hooks`   | array   | required | Array of hook definitions         |
| `type`    | string  | required | `"command"` or `"prompt"`         |
| `command` | string  | -        | Shell command (for type: command) |
| `prompt`  | string  | -        | LLM prompt (for type: prompt)     |
| `timeout` | number  | 60/30    | Seconds before timeout            |
| `once`    | boolean | false    | Run only once per session         |

### Component-Scoped Hooks (v2.1.0+)

Hooks can be defined in Skills, subagents, and slash commands via frontmatter:

```yaml
---
hooks:
  PreToolUse:
    - matcher: "Write"
      hooks:
        - type: command
          command: "./validate.sh"
---
```

These hooks are scoped to the component's lifecycle and auto-cleanup when finished.

---

## Hook Input JSON Schema

All hooks receive JSON via stdin with these common fields:

### Common Fields (All Hooks)

```json
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
  "cwd": "/Users/lily/project",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse"
}
```

| Field             | Type   | Description                                                                |
| ----------------- | ------ | -------------------------------------------------------------------------- |
| `session_id`      | string | Unique session identifier                                                  |
| `transcript_path` | string | Path to conversation JSONL transcript                                      |
| `cwd`             | string | Current working directory                                                  |
| `permission_mode` | string | `"default"`, `"plan"`, `"acceptEdits"`, `"dontAsk"`, `"bypassPermissions"` |
| `hook_event_name` | string | The hook event type                                                        |

### Tool-Related Hooks (PreToolUse, PostToolUse, PermissionRequest)

Additional fields:

```json
{
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_use_id": "toolu_abc123"
}
```

### PostToolUse Additional Fields

```json
{
  "tool_result": "Success: file written"
}
```

### UserPromptSubmit

```json
{
  "user_prompt": "The user's submitted text"
}
```

### Stop / SubagentStop

```json
{
  "reason": "Task completed"
}
```

### SubagentStart (v2.0.64+)

```json
{
  "agent_id": "agent_xyz",
  "parent_agent_id": "agent_abc",
  "subagent_type": "general-purpose",
  "description": "Research task"
}
```

### SessionStart Additional

```json
{
  "agent_type": "custom-agent"
}
```

### Notification

```json
{
  "message": "Claude needs your permission to use Bash",
  "notification_type": "permission_prompt"
}
```

### Environment Variables Available

| Variable                 | Description               | Availability      |
| ------------------------ | ------------------------- | ----------------- |
| `CLAUDE_PROJECT_DIR`     | Project root path         | All hooks         |
| `CLAUDE_PLUGIN_ROOT`     | Plugin directory          | Plugin hooks      |
| `CLAUDE_CODE_REMOTE`     | Set if remote context     | All hooks         |
| `CLAUDE_ENV_FILE`        | For persisting variables  | SessionStart only |
| `CLAUDE_CODE_ENTRYPOINT` | Entry point (e.g., "cli") | All hooks         |

---

## Hook Output JSON Schema

Hooks communicate via stdout with optional JSON structure.

### Universal Output Fields

```json
{
  "continue": true,
  "stopReason": "Optional message when continue=false",
  "suppressOutput": false,
  "systemMessage": "Message shown to USER (not Claude)"
}
```

| Field            | Type    | Default | Description                       |
| ---------------- | ------- | ------- | ------------

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/claude-code-hooks) · https://claudary.paisolsolutions.com
