Открыть список гайдов

AfterAI Guides / Claude Code

Хуки Claude Code: автоматизация рутины при каждом коммите

Разбираем систему хуков в Claude Code: pre-tool и post-tool хуки, настройка через settings.json, форматирование кода и уведомления без ручного труда.

Claude CodeСредний25 мая 2026 г.
claude-codehooksавтоматизацияworkflow

Что такое хуки

Хуки в Claude Code — это shell-команды, которые выполняются автоматически в определённые моменты работы агента. Они позволяют встроить в рабочий процесс Claude Code любую логику: форматирование кода, линтинг, тесты, уведомления в Slack или логирование действий.

Ключевая идея: хуки выполняет система (оболочка), а не сам Claude. Это значит, что они работают детерминированно — Claude не может их обойти или «забыть» применить.

Типичные сценарии:

  • Автоматический prettier или black после каждого редактирования файла
  • Запуск eslint --fix перед записью JS/TS файлов
  • Уведомление в Telegram/Slack когда агент завершил задачу
  • Логирование всех выполненных команд в файл аудита

Типы хуков

Claude Code поддерживает четыре типа хуков, привязанных к жизненному циклу инструментов:

ТипКогда срабатывает
PreToolUseДо того как Claude вызывает инструмент (Read, Write, Bash и др.)
PostToolUseПосле успешного вызова инструмента
NotificationПри отправке Claude уведомления пользователю
StopКогда агент завершает сессию

Самые полезные на практике — PreToolUse и PostToolUse. Первый позволяет заблокировать или модифицировать действие, второй — реагировать на уже совершённые изменения.


Шаг 1: Настройка settings.json

Хуки конфигурируются в файле настроек Claude Code. Есть два уровня:

  • Глобальный: ~/.claude/settings.json — применяется ко всем проектам
  • Проектный: .claude/settings.json в корне проекта — переопределяет глобальный

Базовая структура секции hooks:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'File written: $CLAUDE_TOOL_INPUT_FILE_PATH'"
          }
        ]
      }
    ]
  }
}

Каждый хук имеет:

  • matcher — имя инструмента (Write, Bash, Read, Edit, * для всех)
  • hooks — массив команд
  • type — всегда command
  • command — shell-команда, которую нужно выполнить

Шаг 2: Pre-tool хук — форматирование перед записью

PreToolUse срабатывает до выполнения инструмента. Если хук завершается с кодом выхода 2 — инструмент блокируется, Claude получает сообщение об ошибке.

Пример: запускаем валидацию JSON перед записью .json файлов:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'if [[ \"$CLAUDE_TOOL_INPUT_FILE_PATH\" == *.json ]]; then echo \"$CLAUDE_TOOL_INPUT_CONTENT\" | python3 -m json.tool > /dev/null 2>&1 || (echo \"Invalid JSON\" && exit 2); fi'"
          }
        ]
      }
    ]
  }
}

Переменные окружения, доступные в хуках:

ПеременнаяОписание
CLAUDE_TOOL_NAMEИмя инструмента (Write, Bash и т.д.)
CLAUDE_TOOL_INPUT_FILE_PATHПуть к файлу (для Write/Edit/Read)
CLAUDE_TOOL_INPUT_CONTENTСодержимое (для Write)
CLAUDE_TOOL_INPUT_COMMANDКоманда (для Bash)

Шаг 3: Post-tool хук — автоформатирование после записи

PostToolUse идеален для форматирования: файл уже записан, теперь приводим его к стандарту:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'FILE=\"$CLAUDE_TOOL_INPUT_FILE_PATH\"; case \"$FILE\" in *.py) black \"$FILE\" --quiet 2>/dev/null ;; *.js|*.ts|*.jsx|*.tsx) npx prettier --write \"$FILE\" --log-level silent 2>/dev/null ;; *.go) gofmt -w \"$FILE\" 2>/dev/null ;; esac'"
          }
        ]
      }
    ]
  }
}

Этот хук автоматически:

  • Запускает black для Python файлов
  • Запускает prettier для JS/TS файлов
  • Запускает gofmt для Go файлов

Если нужный форматтер не установлен — 2>/dev/null подавляет ошибку, хук молча пропускает шаг.


Примеры хуков

Уведомление при завершении задачи

json
{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "curl -s -X POST 'https://api.telegram.org/bot<TOKEN>/sendMessage' -d 'chat_id=<CHAT_ID>&text=Claude+Code+завершил+задачу+✅'"
          }
        ]
      }
    ]
  }
}

Аудит-лог всех Bash команд

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') CMD: $CLAUDE_TOOL_INPUT_COMMAND\" >> /tmp/claude-audit.log"
          }
        ]
      }
    ]
  }
}

Запрет на изменение production конфигов

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'if [[ \"$CLAUDE_TOOL_INPUT_FILE_PATH\" == *prod* || \"$CLAUDE_TOOL_INPUT_FILE_PATH\" == *.env.production ]]; then echo \"Изменение production-файлов заблокировано\" && exit 2; fi'"
          }
        ]
      }
    ]
  }
}

Полный пример settings.json с несколькими хуками:

json
{
  "permissions": {
    "allow": ["Bash", "Write", "Edit", "Read"]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date '+%H:%M:%S') $ $CLAUDE_TOOL_INPUT_COMMAND\" >> /tmp/claude-session.log"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'FILE=\"$CLAUDE_TOOL_INPUT_FILE_PATH\"; case \"$FILE\" in *.py) black \"$FILE\" --quiet 2>/dev/null ;; *.js|*.ts) npx prettier --write \"$FILE\" --log-level silent 2>/dev/null ;; esac'"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"Claude Code session ended at $(date)\" >> /tmp/claude-sessions.log"
          }
        ]
      }
    ]
  }
}

Отладка

Если хук не работает как ожидается:

1. Проверь синтаксис JSON

bash
cat .claude/settings.json | python3 -m json.tool

2. Проверь переменные окружения вручную Временно добавь хук, который печатает все переменные:

json
{
  "type": "command",
  "command": "env | grep CLAUDE >> /tmp/claude-env-debug.log"
}

3. Смотри вывод хука Claude Code показывает stdout/stderr хуков в консоли — если хук падает с ошибкой, ты увидишь её там.

4. Тестируй команды отдельно Запусти команду из хука вручную в терминале с нужными переменными:

bash
CLAUDE_TOOL_INPUT_FILE_PATH="test.py" bash -c 'black "$CLAUDE_TOOL_INPUT_FILE_PATH" --quiet'

5. Используй абсолютные пути В хуках лучше использовать абсолютные пути к бинарникам (/usr/local/bin/black вместо black) — окружение может отличаться от интерактивного терминала.

Хуки — это небольшая инвестиция в настройку, которая окупается на каждой сессии. Форматтер, который ты больше не забываешь запустить, или уведомление, которое само приходит — именно так выглядит Claude Code в режиме силы.

Понравился гайд?

Новые гайды, скиллы и разборы кейсов — каждую неделю в Telegram

@afterintelligence →