Skip to main content
Hooks — это определяемые пользователем команды оболочки. Claude Code запускает их в определённых точках своего жизненного цикла, что даёт вам детерминированное управление: определённые действия всегда происходят, а не полагаются на то, что LLM выберет их запуск. Используйте hooks для применения правил проекта, автоматизации повторяющихся задач и интеграции Claude Code с вашими существующими инструментами. Для решений, требующих суждения, а не детерминированных правил, вы также можете использовать hooks на основе подсказок или hooks на основе агентов, которые используют модель Claude для оценки условий. Для других способов расширения Claude Code см. skills для предоставления Claude дополнительных инструкций и исполняемых команд, subagents для запуска задач в изолированных контекстах и plugins для упаковки расширений для совместного использования в проектах.
Это руководство охватывает распространённые варианты использования и как начать работу. Для полных схем событий, форматов JSON ввода/вывода и расширенных функций, таких как асинхронные hooks и MCP tool hooks, см. справочник Hooks.

Настройка вашего первого hook

Чтобы создать hook, добавьте блок hooks в файл параметров. Это пошаговое руководство создаёт hook для уведомлений на рабочем столе, чтобы вы получали оповещение всякий раз, когда Claude ждёт вашего ввода вместо того, чтобы смотреть на терминал.
1

Добавьте hook в ваши параметры

Откройте ~/.claude/settings.json и добавьте hook Notification. Если файл не существует, создайте его. Пример ниже использует osascript для macOS; см. Получайте уведомления, когда Claude требует ввода для команд Linux и Windows.
Если ваш файл параметров уже имеет ключ hooks, добавьте Notification как соседний элемент существующих ключей событий, а не заменяйте весь объект. Каждое имя события — это ключ внутри единственного объекта hooks:
Вы также можете попросить Claude написать хук за вас, описав то, что вы хотите, в CLI.
2

Проверьте конфигурацию

Введите /hooks в промпте Claude Code, чтобы открыть браузер хуков. Ваш новый хук появится в списке в разделе Notification.
3

Протестируйте хук

Нажмите Esc для возврата в CLI. Нажимайте Shift+Tab до тех пор, пока в строке состояния не появится ⏸ manual mode on, попросите Claude сделать что-то, требующее разрешения, затем переключитесь с терминала. Вы должны получить уведомление на рабочем столе.

Что вы можете автоматизировать

Hooks позволяют запускать код в ключевых точках жизненного цикла Claude Code: форматировать файлы после редактирования, блокировать команды перед их выполнением, отправлять уведомления, когда Claude требует ввода, внедрять контекст при запуске сеанса и многое другое. Для полного списка событий hook см. справочник Hooks. Каждый пример включает готовый к использованию блок конфигурации, который вы добавляете в файл параметров. Для примера использования в production с hooks, которые запускают отдельную проверку модели и передают результаты обратно в сеанс, см. как плагин security-guidance интегрируется с Claude Code.

Получайте уведомления, когда Claude требует ввода

Получайте уведомление на рабочем столе всякий раз, когда Claude завершает работу и требует вашего ввода, чтобы вы могли переключиться на другие задачи без проверки терминала. Этот хук использует событие Notification, которое Claude Code вызывает, когда Claude ждёт ввода или разрешения. Точное время см. в разделе когда срабатывает каждый тип уведомления. Каждая вкладка ниже использует собственную команду уведомлений платформы. Добавьте это в ~/.claude/settings.json:
osascript направляет уведомления через встроенное приложение Script Editor. Если у Script Editor нет разрешения на уведомления, команда молча завершается неудачей, и macOS не предложит вам предоставить его.Запустите это в Terminal один раз, чтобы Script Editor появился в ваших настройках уведомлений:
Ничего не появится пока. Откройте System Settings > Notifications, найдите Script Editor в списке и включите Allow Notifications. Запустите команду снова, чтобы подтвердить, что тестовое уведомление появляется.
Пустой matcher срабатывает на все типы уведомлений. Чтобы срабатывать только на определённые события, установите его на одно из этих значений: Claude Code по-разному рассчитывает время permission_prompt в терминале и в Claude Desktop, расширении VS Code и других хостах, которые отвечают на запросы разрешений через Agent SDK. См. когда срабатывает каждый тип уведомления для обоих времён. Matchers quota_auto_resume_fired, quota_auto_resume_stale и quota_auto_resume_disabled требуют Claude Code v2.1.234 или позже. В сеансах терминала permission_prompt для сетевого запроса изолированной команды требует Claude Code v2.1.246 или позже. agent_needs_input для вопроса о настройке терминала товарища требует Claude Code v2.1.248 или позже. Введите /hooks в промпте Claude Code и убедитесь, что хук отображается в разделе Notification.

Автоматическое форматирование кода после редактирования

Автоматически запускайте Prettier на каждом файле, который редактирует Claude, чтобы форматирование оставалось согласованным без ручного вмешательства. Этот hook использует событие PostToolUse с matcher Edit|Write, поэтому он запускается только после инструментов редактирования файлов. Команда извлекает путь отредактированного файла с помощью jq и передаёт его в Prettier. Добавьте это в .claude/settings.json в корне вашего проекта:
Чтобы протестировать hook, попросите Claude добавить строку с одинарными кавычками в файл JavaScript, затем откройте файл: с параметрами Prettier по умолчанию hook переписывает их на двойные кавычки. Когда хук выполняется успешно, Claude Code ничего не показывает в диалоге. Чтобы убедиться, что хук запустился, проверьте, что отредактированный файл переформатирован, или см. раздел Проверка того, что сделал хук. Чтобы переформатировать определённый файл при любом его изменении, включая когда команда Bash переписывает его, используйте hook FileChanged вместо этого.
Примеры Bash на этой странице используют jq для анализа JSON. Установите его с помощью brew install jq на macOS, apt-get install jq на Debian и Ubuntu или см. загрузки jq.

Блокировка редактирования защищённых файлов

Предотвратите изменение Claude чувствительных файлов, таких как .env, package-lock.json или что-либо в .git/. Claude получает обратную связь, объясняющую, почему редактирование было заблокировано, чтобы он мог скорректировать свой подход. Этот пример использует отдельный файл скрипта, который вызывает hook. Скрипт проверяет путь целевого файла против списка защищённых шаблонов и выходит с кодом 2 для блокировки редактирования.
1

Создайте скрипт hook

Сохраните это в .claude/hooks/protect-files.sh:
2

Сделайте скрипт исполняемым на macOS и Linux

Скрипты hook должны быть исполняемыми для запуска Claude Code:
3

Зарегистрируйте hook

Добавьте hook PreToolUse в .claude/settings.json, который запускает скрипт перед любым вызовом инструмента Edit или Write:
4

Протестируйте hook

Попросите Claude добавить комментарий в ваш файл .env. Claude Code блокирует редактирование перед его выполнением и передаёт сообщение Blocked: скрипта Claude как обратную связь.

Повторное внедрение контекста после компактирования

Когда контекстное окно Claude заполняется, компактирование суммирует разговор для освобождения места. Это может привести к потере важных деталей. Используйте hook SessionStart с matcher compact для повторного внедрения критического контекста после каждого компактирования. Claude Code добавляет простой текст, который ваша команда выводит в stdout, в контекст Claude. Этот пример напоминает Claude о соглашениях проекта и недавней работе. Добавьте это в .claude/settings.json в корне вашего проекта:
Вы можете заменить echo любой командой, которая производит динамический вывод, например git log --oneline -5 для отображения недавних коммитов. Для внедрения контекста при каждом запуске сеанса рассмотрите использование CLAUDE.md вместо этого. Для переменных окружения см. CLAUDE_ENV_FILE в справочнике.

Аудит изменений конфигурации

Отслеживайте, когда файлы параметров или skills изменяются во время сеанса. Событие ConfigChange срабатывает, когда внешний процесс или редактор изменяет файл конфигурации, поэтому вы можете регистрировать изменения для соответствия или блокировать несанкционированные изменения. Этот пример добавляет каждое изменение в журнал аудита. Добавьте это в ~/.claude/settings.json:
Matcher фильтрует по типу конфигурации: user_settings, project_settings, local_settings, policy_settings или skills. Для блокировки вступления изменения в силу выйдите с кодом 2 или верните {"decision": "block"}. См. справочник ConfigChange для полной схемы ввода. Чтобы подтвердить, что hook записывает изменения, отредактируйте файл параметров в другом редакторе, пока сеанс запущен, затем откройте ~/claude-config-audit.log: hook добавляет одну строку JSON на изменение с временной меткой, источником и путём файла.

Перезагрузка окружения при изменении каталога или файлов

Некоторые проекты устанавливают разные переменные окружения в зависимости от того, в каком каталоге вы находитесь. Инструменты, такие как direnv, делают это автоматически в вашей оболочке, но инструмент Bash Claude не подхватывает эти изменения самостоятельно. Сочетание hook SessionStart с hook CwdChanged исправляет это. SessionStart загружает переменные для каталога, в котором вы запускаетесь, а CwdChanged перезагружает их каждый раз, когда Claude меняет каталог. Оба записывают в CLAUDE_ENV_FILE, который Claude Code запускает как преамбулу скрипта перед каждой командой Bash. Добавьте это в ~/.claude/settings.json:
Запустите direnv allow один раз в каждом каталоге, который имеет .envrc, чтобы direnv был разрешён загружать его. Если вы используете devbox или nix вместо direnv, тот же шаблон работает с devbox shellenv или devbox global shellenv вместо direnv export bash. Чтобы реагировать на определённые файлы вместо каждого изменения каталога, используйте FileChanged с matcher, указывающим имена файлов для наблюдения, разделённые |. Для построения списка наблюдения это значение разбивается на буквальные имена файлов, а не оценивается как regex. См. FileChanged для того, как то же значение также фильтрует, какие группы hook запускаются при изменении файла. Этот пример наблюдает .envrc и .env в рабочем каталоге:
См. справочные записи CwdChanged и FileChanged для схем ввода, вывода watchPaths и деталей CLAUDE_ENV_FILE.

Автоматическое одобрение определённых запросов разрешений

Пропустите диалог одобрения для вызовов инструментов, которые вы всегда разрешаете. Этот пример автоматически одобряет ExitPlanMode, инструмент, который Claude вызывает, когда он завершает представление плана и просит продолжить, чтобы вас не спрашивали каждый раз, когда план готов. В отличие от примеров с кодом выхода выше, автоматическое одобрение требует, чтобы ваш hook написал решение JSON в stdout. Claude Code запускает hooks PermissionRequest, когда собирается попросить вас разрешение, и если ваш hook возвращает "behavior": "allow", Claude Code отвечает на запрос от вашего имени. Matcher ограничивает hook только ExitPlanMode, поэтому никакие другие запросы не затрагиваются. Добавьте это в ~/.claude/settings.json:
Когда hook одобряет, Claude Code выходит из режима плана и восстанавливает любой режим разрешения, который был активен перед входом в режим плана. Стенограмма показывает “Allowed by PermissionRequest hook” там, где появился бы диалог. Путь hook всегда сохраняет текущий разговор: он не может очистить контекст и начать свежий сеанс реализации так, как может диалог. Чтобы установить определённый режим разрешения вместо этого, вывод вашего hook может включать массив updatedPermissions с записью setMode. Значение mode — это любой режим разрешения, такой как default, acceptEdits или bypassPermissions, и destination: "session" применяет его только для текущего сеанса.
bypassPermissions применяется только если сеанс был запущен с уже доступным режимом обхода: --dangerously-skip-permissions, --permission-mode bypassPermissions, --allow-dangerously-skip-permissions или permissions.defaultMode: "bypassPermissions" в параметрах пользователя, --settings или управляемых параметрах. Это не применяется, если режим обхода отключён permissions.disableBypassPermissionsMode, или если вы запустили сеанс в ограниченном режиме.Claude Code никогда не сохраняет его как defaultMode.
Чтобы переключить сеанс на acceptEdits, ваш hook пишет этот JSON в stdout:
Держите matcher как можно более узким. Соответствие .* или оставление matcher пустым автоматически одобрит каждый запрос разрешения инструмента, включая записи файлов и команды оболочки. См. справочник PermissionRequest для полного набора полей решения.

Как работают hooks

Claude Code срабатывает события hook в определённых точках жизненного цикла. Когда событие срабатывает, Claude Code запускает все соответствующие hooks параллельно; см. Hook handler fields для того, как обрабатываются дублирующиеся обработчики. Таблица ниже показывает каждое событие и когда оно срабатывает: Каждый hook имеет type, который определяет, как он запускается. Большинство hooks используют "type": "command", который запускает команду оболочки. Доступны четыре других типа:
  • "type": "http": POST данные события на URL. См. HTTP hooks.
  • "type": "mcp_tool": вызвать инструмент на уже подключённом MCP сервере. См. MCP tool hooks.
  • "type": "prompt": однооборотная оценка LLM. См. Prompt-based hooks.
  • "type": "agent": многооборотная проверка с доступом к инструментам. Agent hooks являются экспериментальными и могут измениться. См. Agent-based hooks.

Объединение результатов из нескольких hooks

Когда несколько hooks совпадают с одним и тем же событием, каждая команда hook выполняется до завершения, прежде чем Claude Code объединит результаты. Один hook, возвращающий deny, не останавливает выполнение родственных hooks. Не полагайтесь на deny одного hook для подавления побочных эффектов в другом hook. После завершения всех соответствующих hooks Claude Code объединяет их выходные данные. Для решений о разрешениях PreToolUse побеждает наиболее ограничивающий ответ в порядке deny, defer, ask, allow. Текст из additionalContext сохраняется от каждого hook и передаётся Claude вместе. Пример ниже регистрирует два hook PreToolUse на Bash. Первый добавляет каждую команду в файл журнала и выходит с 0. Второй запускает скрипт, который выходит с 2, чтобы отклонить, когда команда содержит rm -rf:
Когда Claude пытается запустить rm -rf /tmp/build, оба hook выполняются параллельно. Hook логирования записывает команду в ~/.claude/bash.log и выходит с 0, что не сообщает никакого решения. Hook защиты выходит с 2, что отклоняет вызов инструмента. Отклонение побеждает, поэтому Claude Code блокирует команду и показывает Claude stderr защиты. Запись в журнал по-прежнему записывается, потому что hook логирования уже выполнился.

Чтение ввода и возврат вывода

Hooks взаимодействуют с Claude Code через stdin, stdout, stderr и коды выхода. Когда событие срабатывает, Claude Code передаёт данные, специфичные для события, в виде JSON в stdin вашего скрипта. Ваш скрипт читает эти данные, выполняет свою работу и сообщает Claude Code, что делать дальше, через код выхода.

Ввод hook

Каждое событие включает общие поля, такие как session_id, уникальный ID для сеанса, и cwd, рабочий каталог при срабатывании события, но каждый тип события добавляет разные данные. Когда Claude запускает команду Bash, hook PreToolUse получает эти поля на stdin:
  • hook_event_name: событие, которое запустило hook
  • tool_name: инструмент, который Claude собирается использовать
  • tool_input: аргументы, которые Claude передал инструменту. Для Bash его поле command содержит команду оболочки.
Например, ввод hook для команды npm test выглядит так:
Ваш скрипт может анализировать этот JSON и действовать на основе любого из этих полей. Hooks UserPromptSubmit получают текст prompt вместо этого, hooks SessionStart получают source (startup, resume, clear, compact или fork), и так далее. См. Common input fields в справочнике для общих полей и раздел каждого события для схем, специфичных для события.

Вывод hook

Ваш скрипт сообщает Claude Code, что делать дальше, записывая в stdout или stderr и выходя с определённым кодом. Следующий hook PreToolUse блокирует команду:
Код выхода определяет, что происходит дальше:
  • Exit 0: ваш hook не возражает через код выхода.
    • Для hook PreToolUse это не одобряет вызов инструмента: нормальный permission flow по-прежнему применяется.
    • Для hooks UserPromptSubmit, UserPromptExpansion, SessionStart и PostModelSwitch, Claude Code добавляет stdout, который он обрабатывает как простой текст, в контекст Claude.
  • Exit 2: Claude Code блокирует действие. Напишите причину в stderr. Где она попадает, зависит от события: некоторые события передают её Claude как обратную связь, чтобы он мог скорректировать, другие показывают её пользователю, а несколько, таких как ConfigChange и Elicitation, не выводят никакого сообщения. Некоторые события не могут быть заблокированы: для SessionStart и других, exit 2 показывает stderr пользователю и выполнение продолжается. См. exit code 2 behavior per event для полного списка.
  • Любой другой код выхода: для большинства событий результат зависит от того, что ваш hook вывел в stdout:
    • Разобранный объект, который проходит проверку схемы: Claude Code игнорирует код выхода, только JSON определяет результат, и hook не сообщается как ошибка. Исключения для каждого события, такие как WorktreeCreate, отказывающий при любом ненулевом выходе, перечислены в разделе Exit code output справочника.
    • Разобранный объект, который не проходит проверку схемы, или stdout, который Claude Code пытается разобрать как JSON, но это не является действительным JSON: неблокирующая ошибка; уведомление содержит сообщение проверки или разбора.
    • Stdout, который Claude Code обрабатывает как простой текст, или пустой stdout: действие продолжается как неблокирующая ошибка. Стенограмма показывает уведомление <hook name> hook error, затем первую строку stderr с префиксом Failed with non-blocking status code:. Чтобы захватить полный stderr, включите debug logging с claude --debug или запустив /debug во время сеанса.

Структурированный вывод JSON

Коды выхода дают вам только возможность заблокировать или остаться молчаливым. Для большего контроля выйдите с 0 и выведите объект JSON в stdout вместо этого.
Используйте exit 2 для блокировки с сообщением stderr или exit 0 с JSON для структурированного управления. Выберите один подход для каждого hook. Для того, что происходит, когда вы их смешиваете, см. Exit code output.
Например, hook PreToolUse может отклонить вызов инструмента и сказать Claude почему, или передать его пользователю на одобрение:
С "deny" Claude Code отменяет вызов инструмента и передаёт permissionDecisionReason обратно Claude. На PreToolUse Claude Code обрабатывает каждое значение permissionDecision следующим образом:
  • "allow": пропустить интерактивный запрос разрешения. Правила запрета и запроса, включая управляемые списки запретов предприятия, по-прежнему применяются, как и запросы на чтение из сетевых путей, для инструментов MCP, помеченных requiresUserInteraction, и для инструментов коннекторов, для которых ваша организация установила ask, в сессиях, где эта настройка доходит до Claude Code
  • "deny": отменить вызов инструмента и отправить причину Claude
  • "ask": показать запрос разрешения пользователю как обычно
Четвёртое значение, "defer", доступно в non-interactive mode с флагом -p. Оно выходит из процесса с сохранённым вызовом инструмента, чтобы обёртка Agent SDK могла собрать ввод и возобновить. См. Defer a tool call for later в справочнике. Hook PreModelSwitch возвращает то же поле permissionDecision: "allow" позволяет переключению модели продолжиться, а "deny" отменяет его. "ask" заставляет вас подтвердить переключение при запуске /model в интерактивном сеансе; везде в другом месте Claude Code обрабатывает "ask" как отказ. См. PreModelSwitch decision control. Другие события используют разные шаблоны решений. Например, hooks PostToolUse и Stop используют поле decision: "block" верхнего уровня, а PermissionRequest использует hookSpecificOutput.decision.behavior. См. summary table в справочнике для полного разбора по событиям. Для hooks UserPromptSubmit используйте hookSpecificOutput.additionalContext вместо этого для внедрения текста в контекст Claude. Вложите additionalContext внутри hookSpecificOutput; если вы поместите его на верхний уровень JSON, Claude Code молча его игнорирует. Например, этот вывод добавляет текущее состояние ветви к каждому запросу:
См. UserPromptSubmit decision control для полной формы вывода, включая блокировку запросов и установку заголовка сеанса. Hooks с type: "prompt" обрабатывают вывод иначе: см. Prompt-based hooks.

Фильтрация hooks с помощью matchers

Без matcher hook срабатывает при каждом возникновении его события. Matchers позволяют вам сузить это. Например, если вы хотите запустить форматер только после редактирования файлов, а не после каждого вызова инструмента, добавьте matcher к вашему hook PostToolUse:
Matcher "Edit|Write" срабатывает только, когда Claude использует инструмент Edit или Write, а не когда он использует Bash, Read или любой другой инструмент. Запятая разделяет альтернативы так же, поэтому "Edit, Write" эквивалентна. См. Matcher patterns для того, как простые имена и регулярные выражения оцениваются.
Claude может также создавать или изменять файлы, запуская команды оболочки. Если ваш hook должен видеть каждое изменение файла, например для сканирования соответствия или логирования аудита, добавьте hook Stop, который сканирует рабочее дерево один раз за ход. Для покрытия за вызов вместо этого также соответствуйте Bash|PowerShell и пусть ваш скрипт перечисляет изменённые и неотслеживаемые файлы с помощью git status --porcelain. Раздел PowerShell hook input объясняет, почему соответствие только Bash недостаточно. Чтобы запустить hook при изменении определённого файла на диске, независимо от того, что его записало, используйте hook FileChanged.
Каждый тип события соответствует определённому полю: Вкладки ниже показывают несколько дополнительных matchers на разных типах событий.
Соответствуйте только вызовам инструмента Bash и логируйте каждую команду в файл. Событие PostToolUse срабатывает после завершения команды, поэтому tool_input.command содержит то, что запустилось. Hook получает данные события в виде JSON на stdin, и jq -r '.tool_input.command' извлекает только строку команды, которую >> добавляет в файл журнала:

Фильтрация по имени инструмента и аргументам с помощью поля if

Поле if использует permission rule syntax для фильтрации hooks по имени инструмента и аргументам вместе, поэтому процесс hook порождается только когда вызов инструмента совпадает. Это выходит за рамки matcher, который фильтрует на уровне группы только по имени инструмента. Например, чтобы запустить hook только когда Claude использует команды git вместо всех команд Bash:
Запускается ли процесс hook команды зависит от формы вашего шаблона if и команды Bash, которую Claude вызывает: Когда Claude Code не может определить, какие команды запускает ввод Bash, он запускает ваш hook независимо от шаблона. Таблица соответствия Bash охватывает формы команд, которые Claude Code может и не может сузить по подкоманде. Поскольку фильтр работает по принципу лучшего усилия, используйте permission system вместо hook для обеспечения жёсткого разрешения или отказа. Поле if принимает те же шаблоны, что и правила разрешений: "Bash(git *)", "Edit(*.ts)" и так далее. Для соответствия нескольким именам инструментов используйте отдельные обработчики каждый со своим значением if, или соответствуйте на уровне matcher, где поддерживается чередование трубой. if работает только на событиях инструментов: PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest и PermissionDenied. Добавление его к любому другому событию предотвращает запуск hook.

Настройка местоположения hook

Где вы добавляете hook, определяет его область: Запустите /hooks в Claude Code для просмотра всех настроенных hooks, сгруппированных по событиям. Чтобы отключить hooks, установите "disableAllHooks": true в вашем файле параметров. Claude Code читает значение, оставшееся после применения settings precedence, поэтому файл параметров проекта может переопределить ваш. Hooks, настроенные в управляемых параметрах, по-прежнему запускаются, если disableAllHooks также не установлен там. Для полного охвата каждого уровня см. disableAllHooks. Если вы редактируете файлы параметров напрямую во время работы Claude Code, наблюдатель файлов обычно автоматически подхватывает изменения hook.

Hooks на основе подсказок

Для решений, требующих суждения, а не детерминированных правил, используйте hooks type: "prompt". Вместо запуска команды оболочки Claude Code отправляет вашу подсказку и данные ввода hook модели Claude для принятия решения. Вы можете указать другую модель с полем model, если вам нужна большая возможность. Единственная работа модели — вернуть решение в виде JSON:
  • "ok": true: действие продолжается
  • "ok": false: что происходит, зависит от события:
    • Stop и SubagentStop: значение reason передаётся обратно Claude, чтобы он продолжал работать, если только ответ также не устанавливает "impossible": true для обозначения условия, которое никогда не может быть выполнено, в этом случае Claude Code разрешает остановку и ход завершается
    • PreToolUse: вызов инструмента отклоняется; по умолчанию ход завершается и значение reason отказа появляется в чате как строка предупреждения. Установите continueOnBlock: true на hook, чтобы вместо этого вернуть значение reason Claude как ошибку инструмента, чтобы он мог скорректировать и продолжить. До версии 2.1.210 значение reason отказа возвращалось Claude как ошибка инструмента и ход продолжался
    • PostToolUse: по умолчанию ход завершается и значение reason появляется в чате как строка предупреждения. Установите continueOnBlock: true, чтобы передать значение reason обратно Claude и продолжить ход вместо этого
    • PostToolBatch, UserPromptSubmit и UserPromptExpansion: ход завершается и значение reason появляется в чате как строка предупреждения
Этот пример использует hook Stop для запроса модели, завершены ли все запрошенные задачи. Если модель возвращает "ok": false, потому что условие ещё не выполнено, Claude продолжает работать и использует значение reason как свою следующую инструкцию:
Для полных параметров конфигурации см. Hooks на основе подсказок в справочнике.

Hooks на основе агентов

Hooks агентов являются экспериментальными. Поведение и конфигурация могут измениться в будущих выпусках. Для производственных рабочих процессов предпочитайте command hooks.
Когда проверка требует проверки файлов или запуска команд, используйте hooks type: "agent". В отличие от hooks подсказок, которые делают один вызов LLM, hooks агентов порождают subagent, который может читать файлы, искать код и использовать другие инструменты для проверки условий перед возвратом решения. Hooks агентов используют формат ответа "ok" / "reason" с более длинным временем ожидания по умолчанию 60 секунд и до 50 оборотов использования инструмента. Они не поддерживают поле impossible из prompt hooks. При ok: false Claude Code обрабатывает hook агента так же, как он обрабатывает prompt hook с continueOnBlock: true на том же событии, поэтому на PreToolUse и PostToolUse ход продолжается; hooks агентов не имеют поля continueOnBlock. См. конфигурацию hooks агентов для полей, включая заполнитель $ARGUMENTS, который Claude Code заменяет входными данными JSON hook. Этот пример проверяет, что тесты проходят перед тем, как позволить Claude остановиться:
Используйте hooks подсказок, когда данных ввода hook достаточно для принятия решения. Используйте hooks агентов, когда вам нужно проверить что-то против фактического состояния кодовой базы. Для полных параметров конфигурации см. Hooks на основе агентов в справочнике.

HTTP hooks

Используйте hooks type: "http" для POST данных события на HTTP конечную точку вместо запуска команды оболочки. Конечная точка получает тот же JSON, который hook команды получил бы на stdin, и возвращает результаты через тело ответа HTTP, используя тот же формат JSON. HTTP hooks полезны, когда вы хотите, чтобы веб-сервер, облачная функция или внешний сервис обрабатывали логику hook: например, общий сервис аудита, который регистрирует события использования инструмента в команде. Этот пример отправляет каждое использование инструмента на локальный сервис логирования:
Ваш эндпоинт отвечает телом JSON в том же формате вывода, что и командные хуки, а Claude Code также проверяет код состояния ответа:
  • Код состояния 2xx: чтобы заблокировать вызов инструмента, верните в теле ответа соответствующие поля hookSpecificOutput.
  • Любой другой код состояния или сбой запроса: Claude Code сообщает о неблокирующей ошибке и позволяет действию продолжиться. Чтобы сбой эндпоинта блокировал действие, задайте для хука onFailure: "block".
Значения заголовков поддерживают интерполяцию переменных окружения, используя синтаксис $VAR_NAME или ${VAR_NAME}. Разрешены только переменные, указанные в массиве allowedEnvVars; все остальные ссылки $VAR остаются пустыми. Для полных параметров конфигурации и обработки ответов см. HTTP hooks в справочнике.

Ограничения и устранение неполадок

Ограничения

Помните об этих ограничениях при разработке hooks:
  • Command hooks взаимодействуют только через stdout, stderr и коды выхода. Они не могут запускать команды / или вызовы инструментов. Текст, возвращённый через additionalContext, внедряется как системное напоминание, которое Claude читает как простой текст. HTTP hooks взаимодействуют через тело ответа вместо этого.
  • Время ожидания hook варьируется в зависимости от типа. Переопределите для каждого hook с помощью поля timeout в секундах.
    • command, http, mcp_tool: 10 минут. Claude Code снижает это значение по умолчанию до 30 секунд для hooks UserPromptSubmit, PreModelSwitch и PostModelSwitch, и до 10 секунд для MessageDisplay.
    • prompt: 30 секунд.
    • agent: 60 секунд.
    • Hooks SessionEnd любого типа совместно используют бюджет в 1,5 секунды. Если ваши параметры устанавливают более длительный timeout для каждого hook, Claude Code увеличивает бюджет в соответствии с этим, до 60 секунд.
  • Hooks PostToolUse не могут отменить действия, так как инструмент уже выполнен.
  • Хуки PermissionRequest срабатывают, когда Claude Code собирается запросить у вас разрешение или когда он в противном случае автоматически отклонил бы вызов, для которого невозможно показать запрос. В неинтерактивном режиме с флагом -p они по-прежнему запускаются вне режима dontAsk, а вызов, по которому ни один хук не принял решение и на который больше ничто не может ответить, отклоняется.
  • Hooks Stop срабатывают всякий раз, когда Claude завершает ответ, а не только при завершении задачи. Они не срабатывают при прерывании пользователем. Ошибки API срабатывают StopFailure вместо этого.
  • Когда несколько hooks PreToolUse возвращают updatedInput для переписания аргументов инструмента, последний завершённый побеждает. Поскольку hooks запускаются параллельно, порядок недетерминирован. Избегайте наличия более одного hook, изменяющего ввод одного и того же инструмента.

Hooks и режимы разрешений

Hooks PreToolUse срабатывают перед любой проверкой режима разрешений в каждом режиме разрешений, включая dontAsk. Hook, возвращающий permissionDecision: "deny", блокирует инструмент даже в режиме bypassPermissions или с --dangerously-skip-permissions. Это позволяет вам применять политику, которую пользователи не могут обойти, изменив свой режим разрешений. Обратное неверно: хук, возвращающий "allow", не обходит правила запрета из настроек и не может подавить запрос для чтения из сетевых путей, для инструментов MCP, отмеченных requiresUserInteraction, или для инструментов коннекторов, которые ваша организация установила на ask, в сессиях, где эта настройка достигает Claude Code. Хуки в файлах настроек и в hooks/hooks.json плагина могут ужесточить ограничения, но не ослабить их сверх того, что разрешают правила разрешений. Установленный вами mod, который обрабатывает tool.check, может одобрить вызов, заблокированный вашим хуком PreToolUse, если только этот хук не находится в управляемых настройках. В разделе Расширение разрешений с помощью хуков перечислено, какие правила имеют приоритет над mod.

Hook не срабатывает

Hook настроен, но никогда не выполняется.
  • Запустите /hooks и подтвердите, что hook появляется под правильным событием
  • Проверьте, что шаблон matcher точно соответствует имени инструмента. Matchers чувствительны к регистру
  • Убедитесь, что вы запускаете правильный тип события: PreToolUse срабатывает перед выполнением инструмента, PostToolUse срабатывает после. Hook PermissionRequest срабатывает, когда Claude Code собирается попросить у вас разрешение; см. ограничения для неинтерактивных случаев

Ошибка hook в выводе

Вы видите сообщение вроде “PreToolUse hook error: …” в стенограмме.
  • Ваш скрипт неожиданно вышел с ненулевым кодом. Протестируйте его вручную, передав образец JSON:
  • Если вы видите “command not found”, используйте абсолютные пути или ${CLAUDE_PROJECT_DIR} для ссылки на скрипты. Чтобы полностью избежать экранирования оболочки, добавьте "args": [] для переключения на exec form, который порождает скрипт напрямую без оболочки
  • Если вы видите “jq: command not found”, установите jq или используйте Python/Node.js для анализа JSON
  • Если уведомление показывает сообщение о валидации JSON, stdout вашего hook был проанализирован как JSON, но не прошёл валидацию схемы. Если оно показывает сообщение об анализе JSON, stdout выглядел как объект JSON, но не был действительным JSON. Оба случая происходят даже при выходе 0. Чтобы исправить ошибку анализа, создайте полезную нагрузку с помощью кодировщика JSON, такого как jq, вместо конкатенации строк, чтобы кавычки и обратные слэши внутри значений были экранированы. Раздел Exit code output справочника охватывает комбинации кодов выхода и JSON
  • Если скрипт вообще не запускается, сделайте его исполняемым: chmod +x ./my-hook.sh

/hooks показывает, что hooks не настроены

Вы отредактировали файл параметров, но hooks не появляются в меню.
  • Редактирования файлов обычно подхватываются автоматически. Если они не появились через несколько секунд, наблюдатель файлов мог пропустить изменение: перезагрузите сеанс для принудительной перезагрузки.
  • Убедитесь, что ваш JSON действителен: конечные запятые и комментарии не допускаются
  • Подтвердите, что файл параметров находится в правильном месте: .claude/settings.json для hooks проекта, ~/.claude/settings.json для глобальных hooks
  • Если в меню отображается Only hooks from managed settings run here, ваша организация установила allowManagedHooksOnly. Хуки в ваших пользовательских, проектных и локальных файлах настроек не запускаются и не отображаются в списке

Stop hook достигает предела блокировки

Claude продолжает работать вместо остановки, а затем завершает ход с предупреждением о том, что Stop hook заблокировал слишком много раз подряд без прогресса. Claude Code переопределяет Stop-хук после того, как он блокирует восемь раз подряд без единого вызова инструмента со стороны Claude между блокировками. Ваш скрипт хука должен проверять, не инициировал ли он уже продолжение работы. Разберите поле stop_hook_active из входного JSON и завершитесь досрочно, если оно равно true:
Если ваш hook законно нуждается в более чем восьми итерациях для сходимости, повысьте предел с помощью CLAUDE_CODE_STOP_HOOK_BLOCK_CAP.

Hook JSON не имеет эффекта

Ваш hook выводит действительный JSON, но решение не вступает в силу и в стенограмме не появляется никакой ошибки. Проверьте, какая причина применима:
  • Дополнительный вывод перед JSON: что-то ещё записывает в stdout раньше, обычно безусловный echo в вашем профиле оболочки, поэтому вывод больше не начинается с {. См. Вывод профиля оболочки перед JSON.
  • Поле на неправильном уровне: сравните размещение каждого поля с форматом JSON output. Например, permissionDecision должен находиться внутри hookSpecificOutput, а не на верхнем уровне. См. Поля на неправильном уровне.

Вывод профиля оболочки перед JSON

Хуки запускаются в неинтерактивных оболочках, но Git Bash и некоторые конфигурации, например BASH_ENV, указывающий на ~/.bashrc, всё равно загружают ваш профиль, и всё, что профиль выводит, попадает в stdout раньше JSON вашего хука:
Если хук не является асинхронным, Claude Code воспринимает вывод, который не начинается с {, как простой текст, поэтому ваш JSON игнорируется. Поскольку хук завершился с кодом 0, в транскрипте тоже не отображается никакой ошибки. Чтобы проверить эту причину, запустите Claude Code с claude --debug, вызовите срабатывание хука и найдите в логе отладки строку Hook output does not start with {. Чтобы исправить это, оберните операторы echo в вашем профиле так, чтобы они выполнялись только в интерактивных оболочках:
Переменная $- содержит флаги оболочки, и i означает интерактивный. Hooks запускаются в неинтерактивных оболочках, поэтому echo пропускается.

Поля на неправильном уровне

Когда ваш hook возвращает permissionDecision или additionalContext на верхнем уровне вместо внутри hookSpecificOutput, JSON всё ещё анализируется, и Claude Code игнорирует неправильно размещённые поля без сообщения об ошибке. Чтобы увидеть, какие поля он игнорировал, запустите Claude Code с claude --debug и найдите в журнале отладки Hook JSON output had unrecognized keys.

Проверка того, что сделал хук

Нажмите Ctrl+O, чтобы открыть представление транскрипта, и найдите результат работы хука:
  • Успех: вы ничего не видите, если только JSON хука не выводит что-либо, например systemMessage или обратную связь Stop-хука.
    • Чтобы убедиться, что хук запустился, проверьте его эффект, например переформатированный файл
  • Блокирующая ошибка: для большинства событий вы видите сообщение, сопровождавшее блокировку, например Blocked: rm commands are not allowed. Для нескольких событий, таких как ConfigChange и Elicitation, сообщение не отображается. Откуда берётся сообщение, описано в разделе Exit code 2.
  • Неблокирующая ошибка: вы видите уведомление <hook name> hook error с кратким объяснением, например первой строкой stderr после Failed with non-blocking status code:, или сообщением о валидации либо разборе JSON. Действие было выполнено.
Чтобы узнать результат для конкретного кода выхода и stdout, включая исключения для отдельных событий, см. раздел Exit code output справочника. Для получения полных сведений о выполнении, включая коды выхода хуков, stdout и stderr, прочитайте лог отладки. Запустите Claude Code с claude --debug-file /tmp/claude.log, чтобы записывать лог по известному пути, затем выполните tail -f /tmp/claude.log в другом терминале. Если вы запустили Claude Code без этого флага, выполните /debug во время сессии, чтобы включить логирование и узнать путь к логу.

Узнайте больше