Вайбкодинг2026-11-0510 минАвтор:

Хуки Claude Code: настройка, примеры и разбор ошибок

Хуки Claude Code: настройка, примеры и разбор ошибок

Вы дали Claude Code задачу, отвлеклись, а он собирается выполнить rm -rf в проекте. Хук запускает вашу проверку перед командой и может остановить её без решения модели. Так же можно включить форматирование после правки или сообщение после ответа. Для примеров нужны работающий Claude Code, Bash и jq; простой фильтр ловит только заданные шаблоны.

В приложении Claude для Windows и macOS хуки читаются из ~/.claude/settings.json: документация советует подключить там Stop, чтобы получать сообщение об окончании ответа. Скрипты удобнее проверять в терминале, а для приведённых примеров на Windows понадобится Git Bash.

Если вы ещё не настроили доступ, начните с установки Claude Code и оплаты из России: России нет в списке поддерживаемых стран. За нарушение региональных правил Anthropic может ограничить аккаунт.

Когда нужен хук, а когда достаточно CLAUDE.md?

А разве нельзя просто написать «не удаляй папки» в CLAUDE.md с правилами проекта? Написать можно, и обычно модель правило выполняет, но в длинной сессии она может о нём забыть или решить, что сейчас оно неуместно. Хук так не умеет: если он подключён к событию, Claude Code запускает его каждый раз сам, и решать модели тут нечего. По смыслу это те же git-хуки, только срабатывают они на действия агента.

Запреты задавайте в permissions.deny, а хук подключайте, когда нужна своя проверка команды. По правилам разрешений ответ allow от хука не отменяет запреты; deny у PreToolUse блокирует вызов даже при bypassPermissions.

Шесть шагов к вайбкодингу с нуля, без кода и английского, покажут завтра в 12:00 МСК на бесплатном мастер-классе. После эфира понятно, с чего начать уже на следующий день.

Записаться бесплатно

Где записать хук и какое событие выбрать?

Для одного проекта запишите хук в .claude/settings.json, для всех своих проектов используйте ~/.claude/settings.json. Личные настройки проекта положите в .claude/settings.local.json. Новое событие добавляйте в существующий объект hooks, сохраняя прежние ключи, чтобы вместе с новой проверкой случайно не убрать из файла уже подключённые уведомления и другие действия.

Выберите событие по моменту запуска: проверка до действия или реакция на результат? Поле matcher отберёт вызовы, вложенный массив hooks задаст команды.

  • PreToolUse проверяет вызов до выполнения и позволяет заранее запретить опасную команду.
  • PostToolUse подходит для форматирования после успешной правки; отменять её уже поздно.
  • UserPromptSubmit проверяет запрос до передачи модели, чтобы при необходимости отклонить его.
  • Notification отправляет сигнал, когда Claude требует внимания, но ничего не блокирует.
  • Stop реагирует на окончание ответа; блокировка заставляет Claude продолжить работу.
  • SessionStart добавляет контекст при старте, в том числе после сжатия; блокировки нет.
  • PreCompact запускает действие перед сжатием контекста и позволяет заблокировать сжатие.

По теме: Claude Code: как включить уведомление после ответа

Как заблокировать опасную команду до запуска?

Подключите PreToolUse к Bash: скрипт получит команду в JSON до выполнения и вернёт решение. Начните в тестовой папке, чтобы проверить настройку до подключения к рабочему проекту. В руководстве по хукам описаны входные данные и способы сообщить решение агенту.

  1. Подготовьте Bash и jq: на macOS выполните brew install jq, на Debian и Ubuntu используйте apt-get install jq; на Windows нужен Git Bash с доступным jq.
  2. Создайте в тестовом проекте папки .claude/hooks и сохраните приведённый ниже скрипт как .claude/hooks/block-danger.sh.
  3. После сохранения на macOS и Linux выполните chmod +x .claude/hooks/block-danger.sh, чтобы разрешить исполнение.

Скрипт для .claude/hooks/block-danger.sh прочитает команду из JSON и проверит её написание:

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$CMD" | grep -qE 'rm -rf|git push --force|DROP TABLE'; then
  echo "Заблокировано хуком: опасная команда ($CMD). Предложите безопасный вариант." >&2
  exit 2
fi
exit 0

Добавьте запись в .claude/settings.json, чтобы вызывать скрипт перед командами Bash, сохранив остальные настройки:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-danger.sh"
      }]
    }]
  }
}

Выполните эти проверки в терминале из корня проекта: строка удаления останется текстом внутри JSON, поэтому ничего не удалится.

echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf build"}}' | .claude/hooks/block-danger.sh; echo "exit=$?"
echo '{"tool_name":"Bash","tool_input":{"command":"ls -la"}}' | .claude/hooks/block-danger.sh; echo "exit=$?"

При проверке редакции 05.11.2026 первый ввод дал сообщение о блокировке и exit=2, второй вернул exit=0. Агент с хуком не запускался. Найдите запись в /hooks: меню проверяет регистрацию, но не работу скрипта. Если записи нет, перезапустите сессию.

Решение хук сообщает кодом выхода. Код 2 останавливает команду, а текст, который скрипт напечатал в stderr, Claude прочитает как объяснение и сможет предложить другой вариант. Значит ли код 0, что команда разрешена? Нет: она просто пойдёт дальше обычным путём, и если в настройках её заранее не разрешили, Claude Code спросит вас, как спросил бы без хука. Любой другой код без валидного JSON обычно считается неблокирующей ошибкой: команда выполнится, а в истории появится «hook error». Если нужен структурированный ответ, выберите вместо блокировки кодом выхода такой способ: скрипт выводит приведённый JSON в stdout и завершается кодом 0, сообщая запрет через поле решения:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Команда запрещена проверкой."
  }
}

Фильтр ловит rm -rf, но пропустит rm -r -f и find -delete, если агент запишет команду иначе. Он помогает заметить типовую ошибку; защиту файлов нельзя доверять ему одному.

Теория оживает, когда агент работает на ваших глазах. Завтра в 12:00 МСК на бесплатном мастер-классе ему ставят задачу голосом, он сам находит данные и сводит их в Google-таблицу, а в Claude Code за эфир проходят путь от идеи до сервиса.

Занять место

Как форматировать файл и вернуть напоминание после сжатия?

Для форматирования нужен PostToolUse после правки, для напоминания после сжатия подойдёт SessionStart. Добавляя эти примеры хуков рядом с PreToolUse в общий объект hooks, разделяйте события запятыми и сохраняйте прежние настройки, чтобы новое действие не вытеснило уже подключённое.

Для автоформата нужны jq, работающий npx и установленный в проекте Prettier: без локальной установки npx временно скачает последнюю версию. Команда с xargs подходит только для путей без пробелов и кавычек. Добавьте фрагмент в hooks файла .claude/settings.json, чтобы форматировать файл после Edit или Write:

"PostToolUse": [{
  "matcher": "Edit|Write",
  "hooks": [{
    "type": "command",
    "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
  }]
}]

Попросите Claude изменить тестовый JavaScript-файл через Edit или Write и проверьте оформление. Успешный хук молчит. Правку через Bash этот фильтр не увидит.

После сжатия контекста SessionStart с фильтром compact добавит вывод команды в контекст. Поместите фрагмент в тот же объект hooks файла .claude/settings.json, заменив напоминание своим:

"SessionStart": [{
  "matcher": "compact",
  "hooks": [{
    "type": "command",
    "command": "echo 'Не меняйте файлы с секретами.'"
  }]
}]

Выполните /compact в тестовой сессии и проверьте запуск хука в журнале. Постоянные правила храните в CLAUDE.md: само напоминание не гарантирует их соблюдения.

По теме: Папка Claude: что хранится в .claude и что можно менять

Как получить сообщение в Telegram после ответа?

Для сообщения в телефон подключите Stop с async: true, чтобы хук работал в фоне после каждого ответа Claude и вам не приходилось следить за ним у компьютера. Это ещё не означает завершения задачи. Ручное прерывание не вызывает Stop. Для сигнала на компьютере подойдёт уведомление после ответа.

Создайте отдельного бота через BotFather, напишите ему и получите chat.id из ответа getUpdates. При настроенном вебхуке метод не работает. Откройте адрес в браузере, подставив токен, чтобы получить данные чата:

https://api.telegram.org/bot<токен>/getUpdates

Токен держите вне репозитория, иначе он уедет в git вместе с проектом: создайте файл ~/.claude/tg.env со строками TG_TOKEN=... и TG_CHAT=..., подставив свои значения. Затем создайте папку ~/.claude/hooks и сохраните в неё скрипт ниже как tg-done.sh, а на macOS и Linux разрешите ему запуск командой chmod +x ~/.claude/hooks/tg-done.sh. Через sendMessage скрипт отправляет только имя папки проекта, без текста переписки.

#!/bin/bash
source ~/.claude/tg.env
INPUT=$(cat)
DIR=$(echo "$INPUT" | jq -r '.cwd // empty')
curl -s -m 10 "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
  --data-urlencode "chat_id=${TG_CHAT}" \
  --data-urlencode "text=Claude Code закончил ответ: ${DIR##*/}" > /dev/null
exit 0

Добавьте событие в объект hooks файла ~/.claude/settings.json, чтобы запускать скрипт после ответа:

"Stop": [{
  "hooks": [{
    "type": "command",
    "command": "~/.claude/hooks/tg-done.sh",
    "async": true
  }]
}]

С настоящим ботом рецепт не проверен: доставку подтвердит сообщение в чате. Если оно не пришло, временно уберите > /dev/null именно в скрипте и попросите Claude ответить снова, чтобы хук получил входные данные и показал ответ сервиса. Код 0 не подтверждает отправку: скрипт возвращает его и при сбое.

Почему хук не появился или пишет hook error?

Первым делом откройте меню /hooks. Хука там нет: значит, Claude Code не прочитал файл, и чаще всего виновата лишняя запятая или комментарий в JSON (этот формат их не прощает) либо файл лежит не по тому пути. Хук в списке есть, но молчит: сравните matcher с именем инструмента буква в букву, потому что bash с маленькой буквы не совпадёт с Bash. В разборе ошибок отмечено, что поле if применимо только к инструментальным событиям.

При «hook error» проверьте скрипт подставным JSON, путь к команде и право исполнения. «jq: command not found» означает отсутствие jq; на Windows ошибка «blocking because Git Bash wasn't found» требует настроить Git Bash или переписать команду под PowerShell.

Если JSON не действует, проверьте вложенность hookSpecificOutput и лишний вывод профиля оболочки в stdout: он может помешать Claude Code прочитать ответ скрипта как JSON и применить решение. Историю открывает Ctrl+O, а команда claude --debug-file /tmp/claude.log пишет журнал. Ищите «Hook output does not start with {» или «Hook JSON output had unrecognized keys».

По теме: Claude Code compact: как сжать контекст без потери задачи

Можно ли включать хуки из чужого проекта?

Сначала прочитайте команды: хук выполняется с правами вашего пользователя. В интерактивной сессии настройки проекта ждут согласия доверять папке, но при запуске claude -p диалога нет и хуки чужого репозитория могут выполниться без подтверждения. Учитывайте эти правила доверия до запуска агента.

Частые вопросы

Почему PostToolUse не отменил правку?

Инструмент уже выполнил действие, поэтому для запрета заранее используйте PreToolUse.

Что делать, если Stop заставляет Claude отвечать снова?

Проверьте stop_hook_active во входном JSON: при true прекращайте повторную блокировку. После 8 блокировок подряд без вызова инструмента Claude Code перестаёт слушать такой хук.

Можно ли написать хук на Python?

Да, команда может запускать скрипт на Python, и у Anthropic есть пример валидатора Bash-команд.

Как временно выключить хуки?

Добавьте "disableAllHooks": true в настройки. Корпоративные хуки из managed settings продолжат работать, если их не отключили там же, поэтому при проверке чужого проекта учитывайте источник каждой записи, которую вы видите в /hooks.

С какого хука начать в своём проекте?

Начните с блокировщика в тестовой папке. Переносите его в рабочий проект и подключайте остальные события по одному только после того, как оба ввода покажут, что скрипт различает разрешённую и запрещённую строку.

Хуки помогают задать границы действий агента. На бесплатном мастер-классе «Вайбкодинг и AI-агенты» завтра в 12:00 МСК покажем, как ИИ-агент находит данные, сравнивает их и сводит в таблицу.

Записаться бесплатно
Разборы, кейсы и фишки вайбкодинга каждую неделю в телеграм-канале «Яков вайбкодит».
Смотрите ИИ-агента в деле: завтра в 12:00 МСК, бесплатно Записаться