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

# Hooks System

> Automate actions with lifecycle hooks for events like tool execution, session start/end, and prompt submission

The ChatCLI **Hooks System** lets you execute automatic actions in response to application lifecycle events. With hooks, you can auto-format code after edits, send notifications, block dangerous commands, log audit trails, and much more.

<Info>
  Hooks are **additive**: global and workspace configurations are merged. Workspace hooks complement global ones -- they never replace them.
</Info>

***

## Configuration

Hooks are defined in JSON files at two levels:

| Level         | File                    | Scope                     |
| :------------ | :---------------------- | :------------------------ |
| **Global**    | `~/.chatcli/hooks.json` | All projects and sessions |
| **Workspace** | `.chatcli/hooks.json`   | Current project only      |

<Tip>
  Workspace hooks are **additive** -- they combine with global hooks. If the same event has hooks at both levels, all are executed (global first, then workspace).
</Tip>

### File Structure

```json theme={"system"}
{
  "hooks": [
    {
      "event": "PostToolUse",
      "type": "command",
      "command": "gofmt -w {{.FilePath}}",
      "toolPattern": "write|patch",
      "description": "Auto-format Go files after edits"
    },
    {
      "event": "SessionEnd",
      "type": "http",
      "url": "https://hooks.example.com/chatcli",
      "description": "Notify team of session end"
    }
  ]
}
```

***

## Available Events

ChatCLI emits 9 lifecycle events that hooks can bind to:

| Event          | When it fires                          | Blocking |
| :------------- | :------------------------------------- | :------- |
| `SessionStart` | When a new ChatCLI session starts      | No       |
| `SessionEnd`   | When the session ends (exit/quit)      | No       |
| `PromptSubmit` | When the user submits a prompt         | No       |
| `PreToolUse`   | **Before** executing a tool            | **Yes**  |
| `PostToolUse`  | **After** a tool executes successfully | No       |
| `ToolError`    | When a tool fails                      | No       |
| `AgentStart`   | When entering agent/coder mode         | No       |
| `AgentEnd`     | When exiting agent/coder mode          | No       |
| `CompactDone`  | After a history compaction             | No       |

<Warning>
  The `PreToolUse` event is **blocking**: if the hook returns exit code 2, the tool execution is **blocked**. This allows you to create guardrails that prevent dangerous operations.
</Warning>

***

## Hook Types

<Tabs>
  <Tab title="Command (Shell)">
    Executes a shell command on the operating system. The command has access to environment variables with event context.

    ```json theme={"system"}
    {
      "event": "PostToolUse",
      "type": "command",
      "command": "gofmt -w {{.FilePath}}",
      "toolPattern": "write|patch",
      "description": "Auto-format Go files after write/patch"
    }
    ```

    **Exit codes**:

    * `0` -- Success (execution continues normally)
    * `1` -- Error (logged, but does not block)
    * `2` -- **Blocks the operation** (only for `PreToolUse`)

    <Info>The command is executed via `sh -c` on Linux/macOS and `cmd /c` on Windows.</Info>
  </Tab>

  <Tab title="HTTP (Webhook)">
    Sends an HTTP POST request to the specified URL. The request body contains a JSON payload with the event data.

    ```json theme={"system"}
    {
      "event": "SessionEnd",
      "type": "http",
      "url": "https://hooks.example.com/chatcli/events",
      "description": "Send session end notification"
    }
    ```

    **JSON payload sent**:

    ```json theme={"system"}
    {
      "event": "SessionEnd",
      "timestamp": "2026-03-29T14:30:00Z",
      "session_id": "abc123",
      "tool": "",
      "data": {
        "duration": "45m12s",
        "messages": 32
      }
    }
    ```

    <Tip>Webhooks are fired asynchronously and do not block ChatCLI execution.</Tip>
  </Tab>
</Tabs>

***

## ToolPattern -- Tool Filtering

The `toolPattern` field lets you filter which tools trigger the hook. It accepts **glob** patterns:

| Pattern        | Matched tools                   |
| :------------- | :------------------------------ |
| `write`        | Only `write`                    |
| `write\|patch` | `write` or `patch`              |
| `exec*`        | `exec`, `exec_background`, etc. |
| `mcp_*`        | All MCP tools                   |
| `*`            | All tools (default if omitted)  |

```json theme={"system"}
{
  "event": "PreToolUse",
  "type": "command",
  "command": "echo 'BLOCKED: exec not allowed' && exit 2",
  "toolPattern": "exec*",
  "description": "Block all exec commands"
}
```

***

## Environment Variables

Command hooks receive environment variables with event context:

| Variable               | Description                               | Example              |
| :--------------------- | :---------------------------------------- | :------------------- |
| `CHATCLI_HOOK_EVENT`   | Name of the event that triggered the hook | `PostToolUse`        |
| `CHATCLI_HOOK_TOOL`    | Tool name (if applicable)                 | `write`              |
| `CHATCLI_HOOK_SESSION` | Current session ID                        | `session_abc123`     |
| `CHATCLI_HOOK_FILE`    | Affected file path (if applicable)        | `/project/main.go`   |
| `CHATCLI_HOOK_CWD`     | Current working directory                 | `/Users/dev/project` |
| `CHATCLI_HOOK_MODE`    | Current mode (chat, agent, coder)         | `agent`              |

***

## Complete Examples

<Tabs>
  <Tab title="Auto-Format">
    Auto-format Go files after any edit:

    ```json theme={"system"}
    {
      "hooks": [
        {
          "event": "PostToolUse",
          "type": "command",
          "command": "if [[ \"$CHATCLI_HOOK_FILE\" == *.go ]]; then gofmt -w \"$CHATCLI_HOOK_FILE\"; fi",
          "toolPattern": "write|patch",
          "description": "Auto-format Go files"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Notifications">
    Send a Slack notification at the end of each session:

    ```json theme={"system"}
    {
      "hooks": [
        {
          "event": "SessionEnd",
          "type": "http",
          "url": "https://hooks.slack.com/services/T00/B00/xxx",
          "description": "Notify Slack on session end"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Block Commands">
    Block `rm -rf` and `DROP TABLE` in production:

    ```json theme={"system"}
    {
      "hooks": [
        {
          "event": "PreToolUse",
          "type": "command",
          "command": "if echo \"$CHATCLI_HOOK_ARGS\" | grep -qE 'rm -rf|DROP TABLE'; then echo 'BLOCKED: dangerous command' >&2; exit 2; fi",
          "toolPattern": "exec*",
          "description": "Block dangerous shell commands"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Audit">
    Log all tool executions:

    ```json theme={"system"}
    {
      "hooks": [
        {
          "event": "PostToolUse",
          "type": "command",
          "command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) $CHATCLI_HOOK_EVENT $CHATCLI_HOOK_TOOL $CHATCLI_HOOK_FILE\" >> ~/.chatcli/audit.log",
          "description": "Audit log for all tool executions"
        }
      ]
    }
    ```
  </Tab>
</Tabs>

***

## Use Cases

<CardGroup cols={2}>
  <Card title="Auto-Format" icon="wand-magic-sparkles">
    Run formatters (gofmt, prettier, black) automatically after file edits.
  </Card>

  <Card title="Notifications" icon="bell">
    Send alerts to Slack, Discord, or email at the end of sessions or on errors.
  </Card>

  <Card title="Guardrails" icon="shield-halved">
    Block dangerous commands (rm -rf, DROP TABLE, force push) with PreToolUse.
  </Card>

  <Card title="Audit" icon="clipboard-list">
    Log all agent actions to files for compliance.
  </Card>

  <Card title="Auto-Test" icon="flask-vial">
    Run tests automatically after every code edit.
  </Card>

  <Card title="Linting" icon="broom">
    Run linters (golangci-lint, eslint) after every write/patch.
  </Card>
</CardGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Coder Security" icon="shield-halved" href="/features/coder-security">
    Security policies and approval for coder operations.
  </Card>

  <Card title="Security" icon="shield-halved" href="/features/security">
    Understand the ChatCLI security model.
  </Card>

  <Card title="Compact UI" icon="minimize" href="/features/compact-ui">
    Minimalist display mode for coder mode.
  </Card>

  <Card title="Coder Mode" icon="code" href="/core-concepts/coder-mode">
    The full engineering cycle with integrated hooks.
  </Card>
</CardGroup>
