> For the complete documentation index, see [llms.txt](https://docs.tabnine.com/main/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tabnine.com/main/getting-started/tabnine-cli/features/hooks/configuration.md).

# Configuration

{% hint style="warning" %}
**Tabnine CLI is in maintenance mode.** As of 6.6, we have stopped active development. It will receive only critical updates through December 31, 2026. After that, we will fully deprecate it. We are transitioning CLI users to [Tabnine Plugin for OpenCode](/main/getting-started/tabnine-plugin-for-opencode.md).
{% endhint %}

Hooks are configured in `settings.json`, **not** in `TABNINE.md`. Tabnine CLI merges configurations from multiple layers (highest to lowest precedence):

1. **Project settings**: `.tabnine/agent/settings.json` in the project root.
2. **User settings**: `~/.tabnine/agent/settings.json`.
3. **System settings**: Platform-specific system config directory.
4. **Extensions**: Hooks defined by installed extensions.

## Configuration schema

```json
{
  "hooksConfig": {
    "enabled": true,
    "disabled": [],
    "notifications": true
  },
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "sequential": true,
        "hooks": [
          {
            "type": "command",
            "command": "node $TABNINE_PROJECT_DIR/hooks/validate-write.js",
            "name": "validate-write",
            "description": "Validate file writes before execution",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
```

## `hooksConfig` fields

| Field           | Type       | Default | Description                                                                           |
| --------------- | ---------- | ------- | ------------------------------------------------------------------------------------- |
| `enabled`       | `boolean`  | `true`  | Master toggle for the hooks system. Set to `false` to disable all.                    |
| `disabled`      | `string[]` | `[]`    | List of hook identifiers to skip. Matches against `name` if set, otherwise `command`. |
| `notifications` | `boolean`  | `true`  | Show visual indicators when hooks execute.                                            |

## Hook definition fields

Each event contains an array of **hook definitions**:

| Field        | Type      | Required | Description                                                                                                         |
| ------------ | --------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `matcher`    | `string`  | No       | A regex for tool events (`BeforeTool`, `AfterTool`) or exact string for lifecycle events. Omit to match everything. |
| `sequential` | `boolean` | No       | If `true`, hooks in this group run sequentially. If `false` (default), they run in parallel.                        |
| `hooks`      | `array`   | **Yes**  | An array of **hook configurations** (see below).                                                                    |

## Hook configuration fields

| Field         | Type                     | Required | Description                                                                    |
| ------------- | ------------------------ | -------- | ------------------------------------------------------------------------------ |
| `type`        | `string`                 | **Yes**  | Must be `"command"`. No default — hooks without `type` are silently discarded. |
| `command`     | `string`                 | **Yes**  | The shell command to execute.                                                  |
| `name`        | `string`                 | No       | A friendly identifier for logs and the `disabled` list.                        |
| `description` | `string`                 | No       | A brief explanation of the hook's purpose.                                     |
| `timeout`     | `number`                 | No       | Timeout in **milliseconds**. Default: `60000` (60 seconds).                    |
| `env`         | `Record<string, string>` | No       | Additional environment variables to set for this hook.                         |

## Matchers

The `matcher` field controls which specific tools or triggers fire your hook:

* **Tool events** (`BeforeTool`, `AfterTool`): Matchers are **regular expressions** (e.g., `"write_file|replace"`, `"read_.*"`).
* **Lifecycle events**: Matchers are **exact strings** (e.g., `"startup"` for `SessionStart`).
* **Match all**: Omit `matcher` or set to `".*"` to match everything.

### Tool naming conventions

* **Built-in tools**: Match by their name (e.g., `read_file`, `run_shell_command`, `write_file`, `replace`).
* **MCP tools**: Follow the pattern `mcp_<server_name>_<tool_name>`.

## Multiple hooks

You can define multiple hooks for the same event. By default they run in parallel; set `sequential: true` to run them in order:

```json
{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": ".*",
        "sequential": true,
        "hooks": [
          {
            "type": "command",
            "command": "node ./hooks/validate.js",
            "name": "validate"
          },
          {
            "type": "command",
            "command": "node ./hooks/log.js",
            "name": "log-tool"
          }
        ]
      }
    ]
  }
}
```

You can also define multiple hook definitions per event with different matchers:

```json
{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          {
            "type": "command",
            "command": "node ./hooks/validate-writes.js"
          }
        ]
      },
      {
        "matcher": "run_shell_command",
        "hooks": [
          {
            "type": "command",
            "command": "node ./hooks/validate-commands.js"
          }
        ]
      }
    ]
  }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.tabnine.com/main/getting-started/tabnine-cli/features/hooks/configuration.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
