# Hooks в Claude Code для начинающих: автоматизируем повторяющиеся действия

> Полное практическое руководство по настройке Hooks в Claude Code: автоматический линтинг, форматирование, защитные проверки перед коммитом, уведомления и Headless-автоматизация.

## 1. Что такое Hooks в Claude Code и зачем они нужны

Работая с AI-ассистентом в терминале, разработчики часто вынуждены повторять одни и те же рутинные команды: *"теперь запусти ESLint"*, *"отформатируй код через Prettier"*, *"проверь типы перед коммитом"*. Даже если прописать эти правила в системных инструкциях `CLAUDE.md`, языковая модель может периодически забывать их выполнить или пропускать ради экономии токенов.

**Hooks (хуки)** в Claude Code решают эту проблему радикально: это детерминированные триггеры, которые автоматически вызывают системные команды или скрипты в точные моменты жизненного цикла работы ассистента.

Принцип работы хуков предельно прост:
> **Если Claude выполнил событие X → операционная система гарантированно запускает действие Y.**

```mermaid
flowchart LR
    subgraph Текстовая_инструкция["CLAUDE.md (Вероятностная)"]
        A["Промпт: 'Всегда запускай линтер'"] --> B{"Модель помнит?"}
        B -->|Иногда| C["Запуск проверки"]
        B -->|Пропустила| D["Ошибки накапливаются"]
    end
    subgraph Нативный_Hook["Hooks в settings.json (Детерминированная)"]
        E["Событие: Редактирование файла"] --> F["Автоматический триггер ОС"]
        F --> G["Гарантированное выполнение npx eslint"]
    end
```

### Сравнение подходов к автоматизации

| Характеристика | Ручные промпты | Инструкции в CLAUDE.md | Нативные Hooks |
| :--- | :--- | :--- | :--- |
| **Надежность выполнения** | Низкая (зависит от человеческого внимания) | Средняя (вероятностное поведение LLM) | 100% (детерминированный перехват событий) |
| **Расход токенов** | Высокий (тратятся токены на каждый запрос) | Средний (правило подгружается в каждый контекст) | Нулевой (выполняется локально в shell) |
| **Скорость реакции** | Медленная (ручной ввод команд) | Требует дополнительного раунда генерации | Мгновенная (нативный вызов процесса) |
| **Возможность блокировки** | Отсутствует | Отсутствует | Есть (ненулевой exit code останавливает действие) |

> [!NOTE]
> Хуки Claude Code настраиваются в формате JSON в файле `.claude/settings.json` на уровне отдельного репозитория или глобально в `~/.claude/settings.json`.

---

## 2. Жизненный цикл событий: PreToolUse, PostToolUse, Notification и Stop

В Claude Code предусмотрено четыре фундаментальные точки перехвата (события), к которым можно привязать запуск автоматических команд.

```mermaid
sequenceDiagram
    autonumber
    actor Dev as Разработчик
    participant Agent as Claude Code
    participant Hook as Система Hooks
    participant Tool as Инструмент (Bash/Edit/Write)

    Dev->>Agent: Запрос на изменение кода
    Agent->>Hook: Попытка вызова инструмента
    Note over Hook: PreToolUse Hook
    Hook-->>Agent: Проверка пройдена (Exit Code 0)
    Agent->>Tool: Выполнение операции
    Tool-->>Agent: Результат успешен
    Agent->>Hook: Событие завершения операции
    Note over Hook: PostToolUse Hook
    Hook-->>Agent: Результат линтинга / форматирования
    Agent->>Hook: Завершение ответа модели
    Note over Hook: Stop Hook (Уведомление)
    Agent-->>Dev: Финальный ответ
```

### Основные точки срабатывания

1. **`PreToolUse` (Перед использованием инструмента):** срабатывает *до* того, как агент выполнит действие. Если команда хука возвращает ошибку (exit code не равен 0), выполнение блокируется. Идеальное место для защитных проверок перед коммитом или пушем.
2. **`PostToolUse` (После использования инструмента):** срабатывает *сразу после* успешного завершения инструмента. Самый востребованный триггер для автоматического форматирования кода (Prettier) или линтинга измененного файла (ESLint).
3. **`Notification` (Уведомление):** активируется, когда ассистенту необходимо уведомить пользователя или запросить подтверждение.
4. **`Stop` (Завершение ответа):** срабатывает в момент, когда Claude Code полностью завершил генерацию ответа и ожидает следующей реплики пользователя. Используется для воспроизведения звуковых сигналов и десктопных уведомлений.

![Точки срабатывания Hooks в жизненном цикле](/api/guides-media/automation/hooks-automation-guide-for-beginners/images/hooks-automation-guide-for-beginners-extra-02.webp)

---

## 3. Структура конфигурации в settings.json и синтаксис Matcher

Конфигурация хуков хранится в файле `.claude/settings.json`. Если этого файла еще нет в корне вашего проекта, создайте его.

### Базовый синтаксис конфигурации

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Начинается редактирование файла...'"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Bash-команда завершена успешно'"
          }
        ]
      }
    ]
  }
}
```

### Как работает поле Matcher

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

- `"Edit"` — перехватывает изменение уже существующих файлов.
- `"Write"` — срабатывает при создании нового файла или полной перезаписи.
- `"Bash"` — реагирует на запуск любых консольных команд.
- `"Bash(git commit*)"` — точечный шаблон, фильтрующий вызовы Bash, начинающиеся с команды `git commit`.
- `"*"` — универсальный селектор (wildcard), срабатывающий на любой доступный инструмент агента.

> [!TIP]
> Шаблоны `matcher` чувствительны к регистру. Используйте стандартные названия инструментов Claude Code: `Edit`, `Write`, `Bash`, `Glob`, `Grep`.

---

## 4. Автоматический линтинг и форматирование (ESLint + Prettier)

Наиболее практичный ежедневный сценарий — передача форматирования и первичной проверки стиля утилитам `Prettier` и `ESLint`. Благодаря этому весь код сохраняется в репозитории в идеальном виде.

### Настройка PostToolUse для ESLint и Prettier

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx eslint --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      },
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}
```

### Разбор флагов безопасности в команде

- `"$CLAUDE_FILE_PATH"` — динамическая переменная окружения, куда Claude автоматически подставляет полный путь к файлу, только что измененному агентом.
- `2>/dev/null` — подавляет избыточный служебный вывод потока ошибок stderr, сохраняя консоль чистой.
- `|| true` — критически важная конструкция bash. Она гарантирует, что даже если линтер обнаружит неисправимые ошибки и вернет код `1`, сам хук завершится с кодом `0` и не прервет рабочий процесс ассистента.

```mermaid
flowchart TD
    A["Claude вызывает Edit"] --> B["Файл записан на диск"]
    B --> C["PostToolUse триггер"]
    C --> D["npx eslint --fix $CLAUDE_FILE_PATH"]
    D --> E{"Успешно или || true"}
    E --> F["Агент продолжает решать задачу"]
```

---

## 5. Защитные барьеры перед git commit (TypeCheck + Тесты)

Если для форматирования мы использовали мягкие хуки с `|| true`, то для фиксации изменений в системе контроля версий требуется строгий контроль качества (Quality Gate).

С помощью `PreToolUse` можно заблокировать создание коммита, если в проекте есть ошибки компиляции TypeScript или падают модульные тесты.

### Настройка блокирующего Pre-commit хука

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git commit*)",
        "hooks": [
          {
            "type": "command",
            "command": "npm run typecheck && npm run lint"
          }
        ]
      }
    ]
  }
}
```

### Что происходит при обнаружении ошибок

1. Claude формирует команду `git commit -m "..."`.
2. Перед ее исполнением система активирует `PreToolUse`.
3. Запускаются скрипты валидации: `npm run typecheck` и `npm run lint`.
4. **Если обнаружена ошибка:** процесс возвращает ненулевой код завершения (exit code 1).
5. Claude Code перехватывает вывод ошибки компилятора прямо в своем контексте.
6. Вместо сломанного коммита ассистент анализирует текст ошибки, исправляет типы в коде и делает повторную чистую попытку коммита.

> [!IMPORTANT]
> Обратите внимание: в блокирующих проверках `PreToolUse` **никогда** не используйте `|| true`, иначе проверка всегда будет считаться успешной, и защитный барьер перестанет действовать.

---

## 6. Аудио- и десктопные уведомления при завершении задач (Stop Hook)

Сложный рефакторинг или прогон полного набора тестов могут занимать от 2 до 10 минут. Вместо того чтобы непрерывно наблюдать за консолью, настройте уведомление через событие `Stop`.

:::tabs
@tab macOS
```json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Glass.aiff && osascript -e 'display notification \"Задача выполнена!\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
```
@tab Linux (Ubuntu / Debian)
```json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null || notify-send 'Claude Code' 'Задача успешно завершена!'"
          }
        ]
      }
    ]
  }
}
```
@tab Windows (WSL / PowerShell)
```json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe -c \"[System.Media.SystemSounds]::Asterisk.Play(); [System.Console]::Beep(800, 250)\""
          }
        ]
      }
    ]
  }
}
```
:::

> [!TIP]
> Уведомление срабатывает только тогда, когда агент полностью завершает формирование итогового ответа, а не между промежуточными вызовами инструментов.

---

## 7. Передача контекста через переменные окружения

Чтобы скрипты автоматизации были гибкими и контекстно-зависимыми, Claude Code автоматически экспортирует метаданные текущей операции в переменные окружения операционной системы.

![Переменные окружения Claude Code для хуков](/api/guides-media/automation/hooks-automation-guide-for-beginners/images/hooks-automation-guide-for-beginners-extra-01.webp)

### Справочник системных переменных Claude Code

| Переменная окружения | Тип значения | Описание и пример содержания |
| :--- | :--- | :--- |
| **`$CLAUDE_FILE_PATH`** | Абсолютный путь | Путь к целевому файлу, который сейчас создается или редактируется (`/Users/dev/project/src/index.ts`) |
| **`$CLAUDE_TOOL_NAME`** | Строковый ID | Название инструмента, инициировавшего событие (`Edit`, `Write`, `Bash`) |
| **`$CLAUDE_PROJECT_DIR`** | Абсолютный путь | Корневая директория проекта, где запущена текущая сессия Claude Code |

### Пример контекстного Bash-скрипта для хука

Создадим скрипт `.claude/hooks/smart-validator.sh`:

```bash
#!/usr/bin/env bash
set -e

# Проверяем, существует ли файл и какое у него расширение
if [[ -f "$CLAUDE_FILE_PATH" ]]; then
  case "$CLAUDE_FILE_PATH" in
    *.ts|*.tsx)
      echo "⚡ Валидация TypeScript файла: $CLAUDE_FILE_PATH"
      npx eslint --fix "$CLAUDE_FILE_PATH" || true
      ;;
    *.json)
      echo "🔍 Проверка валидности JSON..."
      jq empty "$CLAUDE_FILE_PATH" 2>/dev/null || echo "Ошибка формата JSON!"
      ;;
    *.md)
      echo "📝 Документация обновлена: $(basename "$CLAUDE_FILE_PATH")"
      ;;
  esac
fi
```

Теперь в `.claude/settings.json` достаточно указать вызов этого скрипта:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/smart-validator.sh"
          }
        ]
      }
    ]
  }
}
```

---

## 8. Паттерн «CI-in-a-Loop»: непрерывная обратная связь

В классической разработке без использования хуков возникает разрыв: агент правит десяток файлов, после чего запускается сборка проекта, выдающая 40 ошибок компиляции. Агенту сложно разобраться, какая конкретно правка вызвала регрессию.

**CI-in-a-Loop (Короткий цикл обратной связи)** устраняет эту проблему:

```mermaid
flowchart TD
    A["Claude вносит правку в код"] --> B["Мгновенный запуск tsc"]
    B --> C{"Есть ошибка?"}
    C -->|Да| D["Claude видит 1 точечную ошибку"]
    D --> E["Мгновенное исправление за 5 секунд"]
    E --> B
    C -->|Нет| F["Переход к следующей строке/файлу"]
```

### Конфигурация циклического TypeScript-аудита

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx tsc --noEmit 2>&1 | head -n 20 || true"
          }
        ]
      }
    ]
  }
}
```

### Почему необходимо использовать `head -n 20`

Если вывод компилятора возвращает сотни строк логов, они попадают в контекст модели и могут быстро переполнить лимит токенов. Ограничение через `head -n 20` отображает первые ключевые ошибки, давая модели четкий ориентир для немедленного исправления без перегрузки диалога.

---

## 9. Headless-автоматизация: режим -p, Cron и Git Hooks

Хуки можно объединять с автономным (headless) режимом Claude Code — флагом `-p` (print/prompt). Это позволяет автоматизировать выполнение инженерных задач полностью без участия человека.

```mermaid
flowchart LR
    A["Расписание Cron (02:00)"] --> B["Скрипт nightly-audit.sh"]
    B --> C["claude -p 'Run test suite, fix bugs, commit'"]
    C --> D["Хуки PostToolUse контролируют код"]
    D --> E["Автоматический Push результата"]
```

### Автономный скрипт ночного аудита (nightly-audit.sh)

```bash
#!/usr/bin/env bash
cd /var/www/my-project

# Запуск Claude Code в автономном режиме с фиксированной задачей
claude -p "Run full test suite. If any tests fail, inspect the stack trace and fix them. Ensure typecheck passes. Finally, commit all fixes with a conventional commit." >> /var/log/claude-audit.log 2>&1
```

### Настройка расписания выполнения через Cron

Откройте планировщик задач (`crontab -e`) и настройте выполнение каждую ночь в 03:00:

```text
0 3 * * * /usr/local/bin/nightly-audit.sh
```

### Запуск проверки в нативном Git Hook (.git/hooks/post-merge)

Чтобы после каждого получения обновлений через `git pull` автоматически запускался аудит совместимости:

```bash
#!/usr/bin/env bash
# .git/hooks/post-merge
echo "🚀 Запуск автоматической проверки зависимостей через Claude..."
claude -p "Check if package.json was updated. If so, run npm install, verify build, and report summary."
```

Не забудьте выдать права на выполнение: `chmod +x .git/hooks/post-merge`.

---

## 10. Лучшие инженерные практики и правила безопасности Hooks

Неправильно сконфигурированные хуки могут зациклить выполнение или заблокировать работу терминала. Следуйте четырем фундаментальным правилам инженерной гигиены.

### Четыре правила безопасной разработки хуков

1. **Субсекундное быстродействие:** Хуки с событием `PostToolUse` вызываются после каждой модификации файла. Если хук выполняется дольше 1-2 секунд, интерактивная работа с Claude станет некомфортной. Оставляйте тяжелые E2E-тесты для `PreToolUse` перед коммитом, но не после каждого `Edit`.
2. **Обязательное логирование вывода:** Всегда перенаправляйте вывод диагностических скриптов во временный лог-файл:
   ```bash
   "command": "bash .claude/hooks/check.sh >> /tmp/claude-hooks.log 2>&1 || true"
   ```
   Если хук перестанет работать, вы сможете открыть `/tmp/claude-hooks.log` и мгновенно локализовать сбой.
3. **Изолированное тестирование в чистом терминале:** Перед добавлением любой команды в `settings.json` выполните ее вручную в обычном shell. Если команда падает с ошибкой в консоли, она гарантированно нарушит сессию Claude Code.
4. **Защита от бесконечной рекурсии:** Никогда не настраивайте команду в `PostToolUse`, которая сама изменяет файлы проекта без правил игнорирования. Если скрипт вызовет повторный `Edit`, ассистент попадет в вечный цикл вызовов.

> [!WARNING]
> Не запускайте через хуки команды, ожидающие интерактивного ввода от пользователя (например, подтверждения `read -p` или `sudo` с запросом пароля). Это приведет к зависанию терминального процесса.

---

## 11. Практический воркшоп, шпаргалка и итоговый чек-лист

Для быстрого старта в собственном проекте используйте готовую шпаргалку решений и проверенный production-конфиг.

![Шпаргалка по выбору типа Hook для автоматизации](/api/guides-media/automation/hooks-automation-guide-for-beginners/images/hooks-automation-guide-for-beginners-extra-03.webp)

### Готовый файл конфигурации `.claude/settings.json`

Скопируйте этот эталонный конфиг в папку `.claude` вашего проекта:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git commit*)",
        "hooks": [
          {
            "type": "command",
            "command": "npm run typecheck && npm test"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      },
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Работа завершена!\" with title \"Claude Code\"' 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}
```

### Быстрая самопроверка

> **1. Чем `PreToolUse` принципиально отличается от `PostToolUse`?**
>
> > [!TIP]
> > **Ответ:** `PreToolUse` запускается *до* выполнения действия инструмента и способен заблокировать операцию при ненулевом коде возврата. `PostToolUse` запускается *после* успешного завершения и применяется для мягкой постобработки (форматирование, линтинг).

> **2. Зачем в хуках форматирования добавляют конструкцию `|| true`?**
>
> > [!TIP]
> > **Ответ:** Чтобы предупреждения или ошибки форматирования не возвращали аварийный код завершения и не прерывали процесс генерации ответа модели.

> **3. Какая переменная окружения содержит путь к файлу, который только что редактировался?**
>
> > [!TIP]
> > **Ответ:** Переменная `$CLAUDE_FILE_PATH`.

### Итоговый чек-лист внедрения Hooks

- [ ] Создана директория `.claude/` и файл `settings.json` в корне проекта.
- [ ] Настроено автоматическое форматирование измененных файлов через `PostToolUse` + `Prettier`.
- [ ] Добавлен защитный барьер `PreToolUse` на `Bash(git commit*)` с запуском `typecheck`.
- [ ] Подключено звуковое или экранное уведомление на событие `Stop`.
- [ ] Все команды хуков проверены вручную в терминале перед сохранением в конфигурацию.
- [ ] Проверено отсутствие интерактивных команд, ожидающих ввода пароля или подтверждения `[y/N]`.