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

The 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 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, 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 includes several production-ready hooks that demonstrate practical configurations:

Custom Configuration Examples

Blocking Destructive Bash Commands

Add this PreToolUse hook to prevent accidental recursive deletions:

{
  "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 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:

{
  "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.

Non-Blocking Async Analysis

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

{
  "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, allowing 30 seconds for static analysis to complete while Claude continues responding.

Custom Session Initialization

Override default startup behavior with a custom SessionStart hook:

{
  "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 to provide the full hook infrastructure:

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

Summary

  • The 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, 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. Key scripts include run-with-flags.js (a wrapper for normalized execution), post-edit-format.js (for code formatting), and check-console-log.js (for governance scanning). The configuration references these using the ${CLAUDE_PLUGIN_ROOT} environment variable to ensure portable path resolution.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →