# Хуки в Claude Code в 2026: как настроить блокировку опасных команд за 5 шагов

> Хук Claude Code запускает локальную проверку до или после действия агента. Показываю, как настроить PreToolUse для блокировки опасных команд и где заканчивается его защита.

Источник: https://vibeceh.ru/guides/huki-ostanovit-opasnye-izmeneniya-claude-code
Автор: Сергей Мазур · опубликовано 2026-08-08

Хук автоматически запускает локальный скрипт до или после действия Claude Code. Такой хук получает данные о событии, проверяет команду или путь к файлу и может остановить опасное изменение до выполнения. Такой контроль работает независимо от обещания модели «будь осторожнее»: отдельная проверка стоит между решением агента и запуском инструмента.

## Что такое хуки в Claude Code?

Хук в Claude Code - локальная shell-команда, которую система запускает до или после определённого события. Она получает данные через `stdin`, сообщает результат кодом выхода и `stdout`. Событие `PreToolUse` срабатывает до запуска инструмента. Поэтому такой хук может проверить команду и заблокировать опасное действие.

Если ты ищешь «хук что это», представь шлагбаум перед командой. Claude выбрал инструмент. До его запуска Claude Code передаёт событие локальному скрипту. Скрипт смотрит на параметры и решает, пропустить действие или остановить его.

`PreToolUse` работает до инструмента. Это главное для защиты. Если Claude собирается выполнить Bash-команду, хук может проверить поле `tool_input.command`. Если команда попала под запрет, скрипт возвращает отказ.

`PostToolUse` работает после инструмента. Для журнала, форматирования или проверки результата это подходит. Запись к этому моменту уже произошла, поэтому отменить её нельзя: файл мог измениться.

Ты можешь блокировать опасные команды до их выполнения» *(пер. с англ.)*

Хук отличается от обычной инструкции для модели. В [`CLAUDE.md`](/guides/claude-md-udalit-ili-perepisat) можно написать правило: не удаляй файлы, не трогай секреты, сначала покажи план. Но это текст для модели. Она может понять его неправильно, забыть о нём или выбрать обходной путь.

Локальный скрипт проверяет событие независимо от формулировки ответа Claude. Поэтому я бы ставил эти механизмы рядом: инструкция объясняет намерение, хук ставит техническую проверку.

## Хук Claude Code и веб-хук: в чём разница?

Локальный хук Claude Code запускает обработчик внутри рабочего процесса и реагирует на события инструментов. Веб-хук отправляет данные или уведомление во внешнюю систему по наступлении события. Для блокировки Bash-команды нужен локальный `PreToolUse`, потому что веб-хук не стоит между решением Claude и запуском локального инструмента.

![Кот сравнивает локальный хук Claude Code и веб-хук на двух карточках.](https://s3.regru.cloud/crossmark/statejnik/images/guides/huki-ostanovit-opasnye-izmeneniya-claude-code/kadr-1.webp)

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

Хук Claude Code живёт внутри процесса работы с проектом. Он запускает локальную shell-команду, получает входные данные через `stdin` и отвечает кодом выхода и `stdout`. Внешний сервер для такой проверки не нужен.

Разница видна в таблице:

| Характеристика | Локальный хук Claude Code | Веб-хук |
|---|---|---|
| Место работы | Внутри процесса Claude Code | Внешний сервер |
| Входные данные | stdin (JSON события) | HTTP-запрос |
| Может остановить инструмент до запуска | Да (PreToolUse + exit 2) | Нет |
| Требует внешний сервер | Нет | Да |

Веб-хук может отправить уведомление о событии во внешний сервис, но не остановит локальный инструмент до запуска.

Для блокировки опасных действий я выбираю локальный `PreToolUse`. Уведомления и интеграции с внешними системами отправляй через веб-хук. Название одинаковое, место работы разное.

## Какие опасные действия можно остановить хуком?

Хук может остановить выбранные опасные действия до выполнения, но только если проверяет нужную поверхность и правильно понимает последствия команды. Простое совпадение с `rm -rf` не даёт полной защиты: опасная операция может быть спрятана в оболочке, интерпретаторе, скрипте, Git-команде или другом инструменте.

Проблема начинается не только с ошибки Claude. Anthropic описывает approval fatigue: после большого числа запросов человек перестаёт внимательно читать каждое подтверждение и нажимает разрешение почти автоматически.

Со временем это приводит к усталости от подтверждений, когда люди перестают внимательно следить за тем, что именно они разрешают» *(пер. с англ.)*

Локальный хук снижает зависимость от такого внимания. Фильтр надо строить вокруг последствий, учитывая, что опасная команда может быть спрятана внутри одной строки. Команда может вызвать оболочку, интерпретатор или готовый скрипт, внутри которого находится опасное действие.

При проверке я бы держал несколько направлений:

- опасные shell-команды и цепочки команд;
- `python -c`, `node -e` и `bash -c`;
- package-manager scripts;
- удаление или перезапись файлов;
- команды Git, включая операции с удалённым репозиторием;
- обращения к секретам и чувствительным файлам;
- другие инструменты, через которые действие может попасть в файловую систему.

Я бы не давал широкие разрешения на весь Bash, Python, Node или `npm run` только ради удобства. В таком случае проверка теряет команды, которые способны причинить ущерб.

Я бы начинал с одного узкого правила. Например, блокировал бы конкретные операции с рабочей директорией, `.env`, базой или Git. Потом добавлял бы тесты на обходы. Большой regex, который никто не понимает, создаёт ложное чувство защиты.

У хука есть и собственный риск. Скрипт запускается с правами пользователя. Изменённый hook или `settings.json` может стать частью атаки. Конфигурацию из чужого репозитория нельзя считать безопасной только потому, что она лежит локально.

## Как сделать локальный хук для блокировки?

Лучший хук для блокировки это `PreToolUse`. Выбери это событие, подключи локальный скрипт, прочитай JSON события из `stdin` и проверь `tool_input.command`. Опасный результат сообщи в `stderr` и заверши скрипт с кодом `exit 2`. Для безопасных команд не возвращай `permissionDecision: "allow"`, иначе штатная система разрешений может перестать спрашивать подтверждение.

![Собака показывает лапой вверх на схеме из пяти шагов настройки локального хука.](https://s3.regru.cloud/crossmark/statejnik/images/guides/huki-ostanovit-opasnye-izmeneniya-claude-code/kadr-2.webp)

Нужен `PreToolUse`. Он получает параметры инструмента до выполнения. Для Bash matcher должен выбирать Bash-вызовы, а сам скрипт должен работать с полем `tool_input.command`.

Создай в проекте файл `.claude/settings.json`. Подключи в нём локальный обработчик. Точная конфигурация зависит от актуального синтаксиса Claude Code, поэтому перед публикацией сверься с официальной документацией [Claude Code Hooks](https://docs.anthropic.com/en/docs/claude-code/hooks): там полный перечень событий.

   ```json
   {
     "hooks": {
       "PreToolUse": [
         {
           "matcher": "Bash",
           "hooks": [
             {
               "type": "command",
               "command": ".claude/hooks/block-dangerous.sh"
             }
           ]
         }
       ]
     }
   }
   ```

Сделай файл `.claude/hooks/block-dangerous.sh`. Он получает JSON через стандартный ввод. Из него надо достать фактическое значение `tool_input.command`, а не проверять только текст запроса Claude.

В следующем шаблоне опасными считаются несколько очевидных направлений. Это стартовая точка для собственных проверок, а sandbox решает более широкую задачу.

   ```bash
   #!/usr/bin/env bash

   set -euo pipefail

   event_json="$(cat)"

   command_text="$(
     printf '%s' "$event_json" |
       python -c 'import json, sys; print(json.load(sys.stdin).get("tool_input", {}).get("command", ""))'
   )"

   if printf '%s' "$command_text" | grep -Eiq \
     '(^|[;&|()[:space:]])rm([[:space:]]|$)|rm[[:space:]]+-rf|python[[:space:]]+-c|node[[:space:]]+-e|bash[[:space:]]+-c|(^|[[:space:]])tee([[:space:]]|$)|(^|[[:space:]])dd([[:space:]]|$)|git[[:space:]]+push[[:space:]]+--force|\.env'; then
     printf '%s\n' \
       'Команда заблокирована локальным PreToolUse-хуком: проверь последствия и выбери безопасный способ.' \
       >&2
     exit 2
   fi

   exit 0
   ```

Код `exit 2` здесь обязателен. Обычный ненулевой код не равен блокировке: в практических наблюдениях именно `exit 2` останавливает действие.

В безопасной ветке скрипт не должен возвращать `permissionDecision: "allow"`. Не надо автоматически разрешать всё, что не совпало с фильтром.

Такая логика сохраняет обычные запросы разрешений Claude Code:

- опасное совпало - вывести причину в `stderr` и вернуть `exit 2`;
- опасное не совпало - не выносить отдельное разрешение;
- дальше решение принимает штатная система разрешений.

`permissionDecision: "allow"` выглядит удобно, но может отключить стандартные подтверждения для остальных команд. Такой режим оставит всё остальное без вопроса и обойдёт ожидаемую защиту от опасных действий.

Сначала проверь, что скрипт действительно читает событие из `stdin` и достаёт `tool_input.command`. Потом вызови его с тестовым JSON, не запуская разрушительную команду.

   ```bash
   printf '%s\n' '{"tool_input":{"command":"rm -rf test-directory"}}' |
     .claude/hooks/block-dangerous.sh

   printf 'exit code: %s\n' "$?"
   ```

Для заблокированной команды ожидается `exit 2`. Причина должна попасть в `stderr`. Реальное удаление в этом тесте не запускается: скрипту передаётся только JSON-текст.

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

   ```bash
   chmod +x .claude/hooks/block-dangerous.sh
   test -x .claude/hooks/block-dangerous.sh
   ```

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

Практикум полезен именно на этом переходе: там ты собираешь рабочие ограничения руками, а не просто просишь агента «не ломать проект». Хуки, разрешения и проверки становятся частью одной схемы. Пройти практикум

## Как установить и проверить хук?

Подключи скрипт в проектной конфигурации Claude Code, проверь права доступа и отдельно протестируй опасную и безопасную команды. Опасная должна остановиться до выполнения. Безопасная не должна получать автоматический `allow`, чтобы штатная система разрешений продолжила работать в обычном режиме без обхода и лишних разрешений.

Если ты ищешь «установить хук», начни с пути к скрипту и `.claude/settings.json`. Настройка может включать событие, matcher и команду обработчика. Проверь, что путь указывает на существующий исполняемый файл.

Дальше проведи пять проверок:

1. Передай тестовое событие с опасной командой. Скрипт должен вывести причину в `stderr` и вернуть `exit 2`.
2. Передай тестовое событие с безопасной командой. Скрипт не должен возвращать `permissionDecision: "allow"`.
3. Запусти Claude Code и убедись, что опасное действие останавливается до Bash.
4. Проверь, что безопасная команда передаётся штатной системе разрешений.
5. Убедись, что `PostToolUse` не используется как предохранитель: после записи он уже не отменит изменение.

Есть неприятная особенность. `exit 2` точно останавливает инструмент, но Claude не всегда продолжает сценарий сам. Иногда он прекращает ответ и ждёт ручного ввода. В такой ситуации придётся самому решить, что делать дальше, или написать Claude команду продолжить после исправления.

Правильный запуск скрипта тоже не означает автоматическое продолжение работы. Хук отвечает за остановку действия. Он не обязан чинить план агента и выбирать безопасную замену.

Рабочий файл и правильный `exit 2` ещё не доказывают, что защита закрывает нужную поверхность. Проверь опасную команду, безопасную команду, оболочки и другие инструменты, через которые может пройти то же действие.

## Что делать, если хук пропускает опасную команду?

Если хук пропускает опасную команду, ищи другой путь выполнения, а не только ошибку в регулярном выражении. Действие может пройти через `python -c`, `node -e`, `bash -c`, `tee`, `dd`, `cp`, `mv`, Git, MCP, фоновую задачу, симлинк или изменённый hook-скрипт.

Совпадение по одной строке не даёт полной защиты. Команда `rm -rf` может исчезнуть из видимого текста и оказаться внутри интерпретатора или другого скрипта. Запись файла можно выполнить через `tee`, `cp`, `mv` или Git. Чтение секрета через `Read` не закрывает чтение через Bash.

Проверь несколько поверхностей выполнения:

- Bash-команды и цепочки с `;`, `&&`, `||`;
- `python -c`, `node -e`, `bash -c`;
- `tee`, `dd`, `cp`, `mv`;
- Git-операции;
- MCP-серверы;
- subagents;
- фоновые задачи;
- симлинки и переименованные копии;
- сам `.claude/settings.json`;
- сам hook-скрипт.

В сообществе Claude Code на Reddit отмечают, что хуки не являются границей безопасности: [Any way for Claude Code to circumvent hooks?](https://www.reddit.com/r/ClaudeCode/comments/1sgcp4c/any_way_for_claude_code_to_circumvent_hooks/)

Отдельно проверь конфигурацию. Если агент может изменить hook или `settings.json`, он способен ослабить собственную проверку. Для таких изменений нужен отдельный контроль, включая просмотр diff и подтверждение человеком.

Секреты лучше не держать в рабочей папке открытым текстом. Хук для `Read` контролирует конкретный вызов `Read`, но не все способы прочитать тот же файл. Для Bash нужна отдельная проверка.

Я бы не пытался закрыть все обходы одним regex. Сначала выбери последствия, которые нельзя допустить. Потом проверь каждый способ их вызвать. Если риск высокий, добавь sandbox и ручной контроль.

## Почему хук не заменяет sandbox и обычные разрешения?

Хук останавливает выбранные события, sandbox ограничивает последствия разрешённых действий, а система разрешений и проверка человеком решают отдельные задачи. Хук не изолирует компьютер и не даёт полной границы безопасности. Для опасных сценариев нужны несколько перекрывающихся слоёв: локальная проверка, sandbox, права, version control и просмотр изменений.

![Задумчивый мужчина смотрит на пять слоёв защиты вокруг опасной команды.](https://s3.regru.cloud/crossmark/statejnik/images/guides/huki-ostanovit-opasnye-izmeneniya-claude-code/kadr-3.webp)

`PreToolUse` полезен как точечный предохранитель. Он может запретить конкретную Bash-команду до запуска. Но он не контролирует автоматически все инструменты, MCP, фоновые процессы и способы обойти строковый фильтр.

Sandbox работает иначе. Он ограничивает доступ к файлам, возможность записи за пределами рабочего каталога и сетевой доступ. Его ограничения распространяются также на программы и subprocesses, запущенные командой.

Обычная система разрешений остаётся отдельным слоем. Без `permissionDecision: "allow"` безопасная команда может пройти через штатное подтверждение. Человек видит действие и решает, пропускать его или нет.

Version control нужен для восстановления и проверки изменений. Он не отменяет необходимость остановить опасную команду, но помогает увидеть, что реально изменилось. Если проект уже пострадал от неосторожной правки, воспользуйся схемой из статьи [Как починить проект после вайб-кодинга](/guides/vajb-koding-chinim-razvalivshijsya-proekt).

Собери слои так:

- узкий `PreToolUse` для известных опасных действий;
- sandbox для уменьшения последствий;
- обычные разрешения без широкого blanket-доступа;
- version control для diff и отката;
- проверка человеком перед важными изменениями.

Anthropic формулирует этот принцип прямо:

The deterministic boundary is what gets hit when everything probabilistic misses» *(пер. с англ.: «Детерминированная граница: то, что срабатывает, когда всё вероятностное промахивается»)*

Хук не делает Claude Code безопасным вообще. Он закрывает выбранный риск. На этом месте я останавливаюсь: если нужна полноценная изоляция, одного скрипта недостаточно.

## Вопросы и ответы

Хук Claude Code - это локальный обработчик события, который может проверить действие до или после запуска. Для блокировки опасной команды нужен `PreToolUse`, проверка параметров инструмента и `exit 2`. Настройки и ограничения надо сверять с актуальной официальной документацией, потому что API hooks продолжает расширяться.

Хук - локальная shell-команда, которую Claude Code запускает до или после события. Она получает данные через `stdin`, отвечает через код выхода и `stdout`. Для блокировки опасной команды используется `PreToolUse`. Похожим образом ИИ-агент получает доступ к внешним инструментам через MCP.

Система состоит из событий, matcher-правил и локальных обработчиков. Обработчик получает параметры инструмента, выполняет проверку и возвращает результат. В Claude Code появились также события `PermissionRequest`, `PermissionDenied`, `ConfigChange` и другие расширения. Подробнее о протоколе интеграций читай в статье [MCP или Skills в Claude Code: где хранить инструкцию для повторяемой задачи в 2026](/guides/mcp-protiv-skills-gde-khranit-instruktsiyu-dlya-claude-code).

Создай локальный скрипт, подключи его в `.claude/settings.json`, укажи событие `PreToolUse`, matcher инструмента и путь к обработчику. После этого проверь права доступа и тестовое событие через `stdin`.

Для блокировки до выполнения лучший хук: `PreToolUse`. `PostToolUse` подходит для проверки результата или логирования, но не отменяет уже выполненную запись. Для более широкой защиты добавь sandbox и оставь обычные разрешения включёнными.

Проектный файл `.claude/settings.json`: основной уровень конфигурации. Полный перечень уровней конфигурации и точные расположения пользовательских файлов надо сверять на официальной reference-странице Claude Code Hooks.

Для первого блокировщика подходит локальный Bash-скрипт без внешних разрешений и сетевых вызовов. Он читает JSON из `stdin`, проверяет `tool_input.command`, пишет причину в `stderr` и возвращает `exit 2` при отказе.

Отдельная версия скрипта не нужна: это локальный файл в проекте. Важно, чтобы Claude Code поддерживал нужное событие и формат решения. Самое раннее найденное упоминание Hooks в changelog относится к версии `1.0.54`; актуальная зафиксированная версия: `2.1.223`.

Веб-хук отправляет уведомление или данные во внешнюю систему. Локальный хук Claude Code работает внутри жизненного цикла инструмента. Название похоже, но веб-хук не заменяет `PreToolUse` для блокировки локальной команды.

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

Проверяй актуальную страницу [Claude Code Hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) и changelog Claude Code - это официальный источник. Там сверяй структуру конфигурации, matcher, формат входного JSON и поддерживаемые решения.

Можно начать с регулярного выражения для выбранных паттернов, но полной защиты оно не даёт. Команда может пройти через интерпретатор, другую оболочку, Git, MCP, фоновые задачи или изменённую конфигурацию. Проверяй последствия и несколько поверхностей выполнения.

- [Claude Code power user customization: How to configure hooks](https://claude.com/blog/how-to-configure-hooks)
- [Claude Code Hooks documentation](https://docs.anthropic.com/en/docs/claude-code/hooks)
- [How Claude Code auto mode works](https://www.anthropic.com/engineering/claude-code-auto-mode)
- [Making Claude Code more secure and autonomous with sandboxing](https://www.anthropic.com/engineering/claude-code-sandboxing)
- [How we contain Claude across products](https://www.anthropic.com/engineering/how-we-contain-claude)
- [Any way for Claude Code to circumvent hooks?](https://www.reddit.com/r/ClaudeCode/comments/1sgcp4c/any_way_for_claude_code_to_circumvent_hooks/)
- [When a PreToolUse hook blocks a tool call](https://github.com/anthropics/claude-code/issues/24327)
- [PostToolUse hook returns exit code 2](https://github.com/anthropics/claude-code/issues/46468)
- [PermissionDecision allow disables permission prompts](https://github.com/anthropics/claude-code/issues/28812)
- [Claude Code changelog](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md)
