# 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 автоматично експортує метадані поточної операції у системні змінні оточення (Environment Variables).

![Змінні середовища 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`** | Текстовий ідентифікатор | Назва інструмента, який ініціював подію (`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` запускається *до* виконання дії інструмента і здатний заблокувати її при ненульовому exit code. `PostToolUse` запускається *після* успішного завершення операції та використовується для форматування або лінтингу.

> **2. Навіщо в хуках форматування додають `|| true`?**
>
> > [!TIP]
> > **Відповідь:** Щоб помилки лінтера чи форматера не повертали аварійний статус і не зупиняли процес генерації відповіді агента.

> **3. Яка змінна оточення містить шлях до файлу, який щойно редагувався?**
>
> > [!TIP]
> > **Відповідь:** Змінна `$CLAUDE_FILE_PATH`.

### Підсумковий чек-лист впровадження Hooks

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