# Hooks

> Хуки — это shell-команды, которые Kodik выполняет в ключевых точках жизненного цикла агента.

Источник: https://docs.kodik.ru/customization/hooks

Хуки позволяют запускать произвольные shell-команды в определённых точках жизненного цикла Kodik: перед и после вызова инструмента, при запуске сессии, при компактировании и в других ситуациях. С помощью хуков можно блокировать нежелательные действия, вести аудит-лог, автоматически модифицировать входные данные инструментов и многое другое.

## Где определяются хуки

Хуки могут поступать из трёх источников, которые загружаются одновременно:

| Источник     | Расположение файла                                                                   |
| ------------ | ------------------------------------------------------------------------------------ |
| Проект       | `.kodik/hooks/hooks.json` (или `.kodik/hooks/hooks.toml`) в корне рабочей директории |
| Пользователь | `~/Documents/Kodik/Hooks/hooks.json` (или `hooks.toml`)                              |
| Плагин       | `hooks/hooks.json` внутри директории установленного плагина                          |

Проектные хуки применяются только к доверенным рабочим директориям. При первом обнаружении файла хуков Kodik предложит подтвердить доверие к проекту.

Быстро создать хук можно с помощью команды `/create-hook`.

## Поддерживаемые события

| Событие             | Когда срабатывает                                   | Матчер                                      |
| ------------------- | --------------------------------------------------- | ------------------------------------------- |
| `PreToolUse`        | Перед выполнением любого инструмента                | Regex по имени инструмента                  |
| `PostToolUse`       | После выполнения инструмента                        | Regex по имени инструмента                  |
| `PermissionRequest` | При запросе разрешения на использование инструмента | Regex по имени инструмента                  |
| `SubagentStart`     | При запуске субагента                               | Regex по типу агента                        |
| `SubagentStop`      | При остановке субагента                             | Regex по типу агента                        |
| `SessionStart`      | При старте или возобновлении сессии                 | Regex по источнику (`startup` или `resume`) |
| `PreCompact`        | Перед компактированием контекста                    | Regex по триггеру (`manual` или `auto`)     |
| `PostCompact`       | После компактирования контекста                     | Regex по триггеру (`manual` или `auto`)     |
| `UserPromptSubmit`  | При отправке пользователем сообщения                | Матчер не применяется                       |
| `Stop`              | При остановке агента                                | Матчер не применяется                       |

## Матчер

Поле `matcher` — это строка регулярного выражения, которая проверяется против дискриминатора события:

- События с инструментами (`PreToolUse`, `PostToolUse`, `PermissionRequest`): проверяется имя инструмента.
- События субагентов (`SubagentStart`, `SubagentStop`): проверяется тип агента.
- `SessionStart`: проверяется источник — `startup` или `resume`.
- `PreCompact` / `PostCompact`: проверяется триггер — `manual` или `auto`.
- `UserPromptSubmit`, `Stop`: матчер игнорируется, хук срабатывает всегда.

Матчер привязывается к началу и концу значения — например, `Bash` соответствует только инструменту с именем `Bash`. Чтобы сопоставить несколько инструментов, используйте синтаксис `Edit|Write` или `.*`.

## Формат файла хуков

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 audit_tool.py",
            "timeout": 10
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo session started >> ~/kodik-sessions.log"
          }
        ]
      }
    ]
  }
}
```

Каждая запись в массиве события содержит:

- `matcher` — необязательная regex-строка (отсутствие означает «всегда совпадает»).
- `hooks` — массив обработчиков. Сейчас поддерживается только тип `command`.
  - `command` — shell-команда, которую нужно выполнить.
  - `timeout` — таймаут в секундах (по умолчанию 30, диапазон 1–300).

## Входные данные хука

Хук получает на `stdin` JSON-объект с информацией о событии:

```json
{
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "ls -la" },
  "context": { ... }
}
```

## Результат выполнения хука

Хук сигнализирует об исходе через код возврата и/или stdout:

| Код возврата | Значение                                                                   |
| ------------ | -------------------------------------------------------------------------- |
| `0`          | Продолжить выполнение                                                      |
| `2`          | Заблокировать действие; содержимое `stderr` становится причиной блокировки |

Кроме того, хук может вернуть структурированный JSON в последней непустой строке `stdout`. Поддерживаемые поля:

| Поле                 | Тип                      | Описание                                                        |
| -------------------- | ------------------------ | --------------------------------------------------------------- |
| `decision`           | `"block"` \| `"approve"` | Явно заблокировать или разрешить действие                       |
| `reason`             | string                   | Причина решения, показывается пользователю                      |
| `modified_input`     | object                   | Изменённые входные данные инструмента (только для `PreToolUse`) |
| `modified_prompt`    | string                   | Изменённый текст промпта (только для `UserPromptSubmit`)        |
| `additional_context` | string                   | Дополнительный контекст, передаваемый агенту                    |

Пример блокировки с причиной:

```json
{
  "decision": "block",
  "reason": "Изменения в продакшн-ветке запрещены без код-ревью."
}
```

## Переменные окружения

Kodik передаёт в хук переменные окружения в зависимости от источника хука:

- Проектный хук: `KODIK_PROJECT_ROOT` — путь к корню проекта.
- Пользовательский хук: `KODIK_HOOKS_ROOT` — путь к директории пользовательских хуков.
- Хук плагина: `KODIK_PLUGIN_ROOT` и `KODIK_PLUGIN_ID`.

## Создание хука с помощью /create-hook

Напечатайте `/create-hook` в чате и опишите, что должен делать хук. Kodik сгенерирует и сохранит файл хуков в `.kodik/hooks/hooks.json` вашего проекта (или в глобальную директорию, если вы явно укажете). После создания хука перезагрузите окно IDE или начните новую задачу, чтобы изменения вступили в силу.
