# Complete Guide to hooks.json Configuration Options in Everything Claude Code

> Explore the hooks.json configuration options for Claude Code. Understand PreToolUse, SessionStart, and more to customize Claude's behavior with matchers, commands, and parameters.

- Repository: [Affaan Mustafa/everything-claude-code](https://github.com/affaan-m/everything-claude-code)
- Tags: how-to-guide
- Published: 2026-03-20

---

**The [`hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks.json) file in the affaan-m/everything-claude-code repository defines six lifecycle hook events—`PreToolUse`, `PreCompact`, `SessionStart`, `PostToolUse`, `Stop`, and `SessionEnd`—that accept `matcher` patterns, command definitions, and optional `async` and `timeout` parameters to customize Claude Code's behavior.**

The [`hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks.json) file serves as the central configuration hub for the Everything Claude Code (ECC) plugin, defining when and how custom scripts intercept Claude's tool execution flow. This JSON configuration follows the Claude Code settings schema and enables developers to inject validation, formatting, and governance checks at precise moments during a coding session. Understanding the available configuration options allows you to enforce code quality, block unsafe operations, and automate post-processing tasks.

## Hook Lifecycle Events

The configuration file organizes hooks into six distinct lifecycle events that fire at specific points during a Claude session. Each event array contains objects that define which tools trigger the hook and what commands execute in response.

### PreToolUse

Defined in lines 4-99 of [`hooks/hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks/hooks.json), the `PreToolUse` event runs **before** any tool (Bash, Write, Edit, etc.) executes. This event is ideal for validation, security checks, or blocking unsafe flags before they reach the system.

### PreCompact

Located at lines 100-110, `PreCompact` fires **before** the automatic context-compaction step occurs. Use this to persist state, dump diagnostics, or capture session metrics before Claude condenses the conversation history.

### SessionStart

Found at lines 111-124, `SessionStart` executes once when a new Claude session begins. This hook can load prior session data, detect package managers, or initialize environment-specific configurations.

### PostToolUse

Defined in lines 125-158, `PostToolUse` runs **after** a tool finishes execution. This is the appropriate place for formatting, type-checking, quality-gate checks, or logging tool outcomes.

### Stop

Located at lines 162-236, the `Stop` event triggers when the assistant stops responding after each turn. This hook enforces final linting, captures governance events, or computes session costs before the next user input.

### SessionEnd

Found at lines 237-274, `SessionEnd` represents the final hook before the process exits. Typically, this writes a clean termination marker for downstream analytics or cleanup operations.

## Core Configuration Schema

Each hook entry within the event arrays follows a strict schema with required and optional keys that control execution behavior.

### matcher

The **`matcher`** key defines a tool-pattern string (e.g., `Bash`, `Write`, `Edit|Write`) that determines which tool invocations trigger the hook. The pattern supports the pipe character (`|`) to match multiple tools and the asterisk (`*`) as a wildcard to match all tools.

### hooks

The **`hooks`** key contains an array of action objects. Currently, ECC exclusively uses `"type": "command"` objects, which specify a shell command—usually a Node.js or Bash script—to execute when the matcher criteria are met.

### description

The optional **`description`** field provides human-readable text explaining the hook's purpose. This documentation aids maintenance and debugging when reviewing complex configuration files.

### async

When set to `true`, the **`async`** flag runs the hook **non-blocking**, allowing the assistant to continue processing without waiting for the command to complete. This is essential for long-running analysis tasks that should not interrupt the coding flow.

### timeout

The **`timeout`** parameter specifies the maximum seconds a hook may run before the system forcibly terminates it. This prevents runaway scripts from hanging the Claude session indefinitely.

## Execution Order and Matching Logic

The runtime evaluates hook execution through a precise matching sequence. First, the system identifies the current lifecycle **event** (`PreToolUse`, `PostToolUse`, etc.). Then, it evaluates each entry's `matcher` against the **tool name** being invoked. The first entry that matches runs its associated `command`, and multiple entries can match sequentially, executing **in the order they appear** in the JSON array.

## Built-in Hook Implementations

The default [`hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks.json) includes several production-ready hooks that demonstrate practical configurations:

- **`PreToolUse`** with matcher `Bash`: Executes `npx block-no-verify@1.1.2` to prevent `--no-verify` flags that would bypass git hooks
- **`PreToolUse`** with matcher `Write`: Runs [`scripts/hooks/doc-file-warning.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/doc-file-warning.js) to warn when non-standard documentation files are edited
- **`PostToolUse`** with matcher `Edit`: Calls [`scripts/hooks/post-edit-format.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/post-edit-format.js) to auto-format JavaScript/TypeScript files after edits
- **`PostToolUse`** with matcher `Edit`: Invokes [`scripts/hooks/post-edit-typecheck.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/post-edit-typecheck.js) to run TypeScript type-checking on [`.ts/.tsx`](https://github.com/affaan-m/everything-claude-code/blob/main/.ts/.tsx) files
- **`Stop`** with matcher `*`: Executes [`scripts/hooks/check-console-log.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/check-console-log.js) to scan modified files for stray `console.log` statements
- **`SessionEnd`** with matcher `*`: Runs [`scripts/hooks/session-end-marker.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/session-end-marker.js) to emit a lifecycle marker for downstream analytics

## Custom Configuration Examples

### Blocking Destructive Bash Commands

Add this `PreToolUse` hook to prevent accidental recursive deletions:

```json
{
  "matcher": "Bash",
  "hooks": [
    {
      "type": "command",
      "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/run-with-flags.js\" \"pre:protect-rm\" \"scripts/hooks/protect-rm.js\" \"standard,strict\""
    }
  ],
  "description": "Blocks accidental recursive deletes"
}

```

Place this object inside the `PreToolUse` array. The [`protect-rm.js`](https://github.com/affaan-m/everything-claude-code/blob/main/protect-rm.js) script inspects `process.argv` and exits with an error if the pattern `/rm\s+-rf/` is detected.

### Enforcing Linting on File Writes

Configure this `PostToolUse` hook to run a linter after any write operation:

```json
{
  "matcher": "Write",
  "hooks": [
    {
      "type": "command",
      "command": "npm run lint --silent"
    }
  ],
  "description": "Enforces linting on every file write"
}

```

Add this entry to the `PostToolUse` event array. The `npm run lint` script must be defined in the repository's [`package.json`](https://github.com/affaan-m/everything-claude-code/blob/main/package.json).

### Non-Blocking Async Analysis

Use the `async` flag for long-running build analysis without blocking the assistant:

```json
{
  "matcher": "Bash",
  "hooks": [
    {
      "type": "command",
      "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/post-bash-build-complete.js\"",
      "async": true,
      "timeout": 30
    }
  ],
  "description": "Runs static-analysis after a build without blocking the assistant"
}

```

This mirrors the built-in example on lines 140-146 of [`hooks/hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks/hooks.json), allowing 30 seconds for static analysis to complete while Claude continues responding.

### Custom Session Initialization

Override default startup behavior with a custom `SessionStart` hook:

```json
{
  "matcher": "*",
  "hooks": [
    {
      "type": "command",
      "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/custom-session-start.js\""
    }
  ],
  "description": "Loads a user-specific context file when a session begins"
}

```

Insert this object in the `SessionStart` array to execute custom logic when a new Claude session initializes.

## Key Files and Implementation Details

Several supporting scripts work alongside [`hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks.json) to provide the full hook infrastructure:

- **[`hooks/hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks/hooks.json)**: The master configuration file defining all events, matchers, and commands
- **[`scripts/hooks/run-with-flags.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/run-with-flags.js)**: A wrapper utility that normalizes flag handling for every hook command
- **[`scripts/hooks/post-edit-format.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/post-edit-format.js)**: Concrete formatter implementation used after `Edit` operations
- **[`scripts/hooks/post-edit-typecheck.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/post-edit-typecheck.js)**: TypeScript type-checking script executed after file modifications
- **[`scripts/hooks/quality-gate.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/quality-gate.js)**: Comprehensive quality gate suite triggered after file changes
- **[`scripts/hooks/check-console-log.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/check-console-log.js)**: Scanner that detects stray `console.log` statements when the `Stop` event fires
- **[`scripts/hooks/session-end-marker.js`](https://github.com/affaan-m/everything-claude-code/blob/main/scripts/hooks/session-end-marker.js)**: Utility that emits terminal markers during session termination

These files collectively define the complete lifecycle of hook execution inside the ECC environment.

## Summary

- The [`hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks.json) configuration supports six lifecycle events: `PreToolUse`, `PreCompact`, `SessionStart`, `PostToolUse`, `Stop`, and `SessionEnd`
- Each hook requires a **`matcher`** pattern (supporting `|` and `*` wildcards) and a **`hooks`** array containing command definitions
- Optional **`async`** and **`timeout`** parameters control execution blocking and script duration limits
- Hooks execute sequentially in the order they appear in the JSON array, with the first matching pattern triggering the associated command
- Built-in implementations demonstrate security validation, auto-formatting, type-checking, and session analytics

## Frequently Asked Questions

### What is the difference between PreToolUse and PostToolUse hooks?

**`PreToolUse`** hooks execute before Claude invokes a tool, making them ideal for validation, security checks, or blocking dangerous commands before they run. **`PostToolUse`** hooks execute after the tool completes, which is the appropriate place for formatting, linting, or logging the results of an operation. According to the source code in [`hooks/hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks/hooks.json), `PreToolUse` is defined at lines 4-99 while `PostToolUse` occupies lines 125-158.

### Can I use wildcards in the matcher pattern?

Yes. The **`matcher`** field supports the asterisk (`*`) as a wildcard to match all tool types, and the pipe character (`|`) to match multiple specific tools (e.g., `"Edit|Write"`). This pattern matching is evaluated sequentially, with the first matching entry in the array executing its command.

### How do I prevent a hook from blocking the assistant's response?

Set the **`async`** property to `true` within the hook definition. This runs the command non-blocking, allowing Claude to continue processing while the script executes in the background. Always pair async hooks with a **`timeout`** value to prevent runaway processes from consuming system resources indefinitely.

### Where are the actual hook scripts located in the repository?

The hook scripts reside in the **`scripts/hooks/`** directory, while the master configuration lives at **[`hooks/hooks.json`](https://github.com/affaan-m/everything-claude-code/blob/main/hooks/hooks.json)**. Key scripts include [`run-with-flags.js`](https://github.com/affaan-m/everything-claude-code/blob/main/run-with-flags.js) (a wrapper for normalized execution), [`post-edit-format.js`](https://github.com/affaan-m/everything-claude-code/blob/main/post-edit-format.js) (for code formatting), and [`check-console-log.js`](https://github.com/affaan-m/everything-claude-code/blob/main/check-console-log.js) (for governance scanning). The configuration references these using the `${CLAUDE_PLUGIN_ROOT}` environment variable to ensure portable path resolution.