Перейти к основному содержанию
Для краткого руководства с примерами см. Начало работы с Claude Code hooks.

Конфигурация

Hooks Claude Code настраиваются в ваших файлах настроек:
  • ~/.claude/settings.json - Пользовательские настройки
  • .claude/settings.json - Настройки проекта
  • .claude/settings.local.json - Локальные настройки проекта (не коммитятся)
  • Параметры политики, управляемые предприятием

Структура

Hooks организованы по матчерам, где каждый матчер может иметь несколько hooks:
{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here"
          }
        ]
      }
    ]
  }
}
  • matcher: Шаблон для сопоставления имён инструментов, чувствителен к регистру (применяется только для PreToolUse и PostToolUse)
    • Простые строки совпадают точно: Write совпадает только с инструментом Write
    • Поддерживает regex: Edit|Write или Notebook.*
    • Используйте * для сопоставления всех инструментов. Вы также можете использовать пустую строку ("") или оставить matcher пустым.
  • hooks: Массив hooks для выполнения при совпадении шаблона
    • type: Тип выполнения hook - "command" для bash команд или "prompt" для оценки на основе LLM
    • command: (Для type: "command") Bash команда для выполнения (может использовать переменную окружения $CLAUDE_PROJECT_DIR)
    • prompt: (Для type: "prompt") Промпт для отправки LLM для оценки
    • timeout: (Опционально) Как долго hook должен работать в секундах перед отменой этого конкретного hook
Для событий типа UserPromptSubmit, Notification, Stop и SubagentStop которые не используют матчеры, вы можете опустить поле matcher:
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/prompt-validator.py"
          }
        ]
      }
    ]
  }
}

Скрипты Hook для конкретного проекта

Вы можете использовать переменную окружения CLAUDE_PROJECT_DIR (доступна только когда Claude Code запускает команду hook) для ссылки на скрипты, хранящиеся в вашем проекте, обеспечивая их работу независимо от текущей директории Claude:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
          }
        ]
      }
    ]
  }
}

Hooks плагинов

Плагины могут предоставлять hooks, которые беспрепятственно интегрируются с вашими пользовательскими и проектными hooks. Hooks плагинов автоматически объединяются с вашей конфигурацией при включении плагинов. Как работают hooks плагинов:
  • Hooks плагинов определены в файле hooks/hooks.json плагина или в файле, указанном пользовательским путём к полю hooks.
  • Когда плагин включен, его hooks объединяются с пользовательскими и проектными hooks
  • Несколько hooks из разных источников могут реагировать на одно и то же событие
  • Hooks плагинов используют переменную окружения ${CLAUDE_PLUGIN_ROOT} для ссылки на файлы плагина
Пример конфигурации hook плагина:
{
  "description": "Automatic code formatting",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
Hooks плагинов используют тот же формат, что и обычные hooks с опциональным полем description для объяснения назначения hook.
Hooks плагинов работают вместе с вашими пользовательскими hooks. Если несколько hooks совпадают с событием, они все выполняются параллельно.
Переменные окружения для плагинов:
  • ${CLAUDE_PLUGIN_ROOT}: Абсолютный путь к директории плагина
  • ${CLAUDE_PROJECT_DIR}: Корневая директория проекта (то же самое, что и для проектных hooks)
  • Все стандартные переменные окружения доступны
См. справочник компонентов плагинов для деталей по созданию hooks плагинов.

Hooks на основе промптов

В дополнение к bash command hooks (type: "command"), Claude Code поддерживает hooks на основе промптов (type: "prompt"), которые используют LLM для оценки того, разрешить или заблокировать действие. Hooks на основе промптов в настоящее время поддерживаются только для Stop и SubagentStop hooks, где они позволяют принимать интеллектуальные, контекстно-зависимые решения.

Как работают hooks на основе промптов

Вместо выполнения bash команды, hooks на основе промптов:
  1. Отправляют входные данные hook и ваш промпт быстрому LLM (Haiku)
  2. LLM отвечает структурированным JSON с решением
  3. Claude Code автоматически обрабатывает решение

Конфигурация

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete."
          }
        ]
      }
    ]
  }
}
Поля:
  • type: Должно быть "prompt"
  • prompt: Текст промпта для отправки LLM
    • Используйте $ARGUMENTS как заполнитель для входного JSON hook
    • Если $ARGUMENTS отсутствует, входной JSON добавляется к промпту
  • timeout: (Опционально) Timeout в секундах (по умолчанию: 30 секунд)

Схема ответа

LLM должен ответить JSON, содержащим:
{
  "decision": "approve" | "block",
  "reason": "Explanation for the decision",
  "continue": false,  // Optional: stops Claude entirely
  "stopReason": "Message shown to user",  // Optional: custom stop message
  "systemMessage": "Warning or context"  // Optional: shown to user
}
Поля ответа:
  • decision: "approve" разрешает действие, "block" предотвращает его
  • reason: Объяснение, показываемое Claude при решении "block"
  • continue: (Опционально) Если false, полностью останавливает выполнение Claude
  • stopReason: (Опционально) Сообщение, показываемое при continue равном false
  • systemMessage: (Опционально) Дополнительное сообщение, показываемое пользователю

Поддерживаемые события hook

Hooks на основе промптов работают с любым событием hook, но наиболее полезны для:
  • Stop: Интеллектуально решить, должен ли Claude продолжать работу
  • SubagentStop: Оценить, завершил ли subagent свою задачу
  • UserPromptSubmit: Валидировать пользовательские промпты с помощью LLM
  • PreToolUse: Принимать контекстно-зависимые решения о разрешениях

Пример: Интеллектуальный Stop hook

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "You are evaluating whether Claude should stop working. Context: $ARGUMENTS\n\nAnalyze the conversation and determine if:\n1. All user-requested tasks are complete\n2. Any errors need to be addressed\n3. Follow-up work is needed\n\nRespond with JSON: {\"decision\": \"approve\" or \"block\", \"reason\": \"your explanation\"}",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Пример: SubagentStop с пользовательской логикой

{
  "hooks": {
    "SubagentStop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluate if this subagent should stop. Input: $ARGUMENTS\n\nCheck if:\n- The subagent completed its assigned task\n- Any errors occurred that need fixing\n- Additional context gathering is needed\n\nReturn: {\"decision\": \"approve\" or \"block\", \"reason\": \"explanation\"}"
          }
        ]
      }
    ]
  }
}

Сравнение с bash command hooks

ФункцияBash Command HooksHooks на основе промптов
ВыполнениеЗапускает bash скриптЗапрашивает LLM
Логика решенияВы реализуете в кодеLLM оценивает контекст
Сложность настройкиТребует файл скриптаПросто настройте промпт
Осведомлённость о контекстеОграничена логикой скриптаПонимание естественного языка
ПроизводительностьБыстро (локальное выполнение)Медленнее (вызов API)
Случай использованияДетерминированные правилаКонтекстно-зависимые решения

Лучшие практики

  • Будьте конкретны в промптах: Ясно укажите, что вы хотите, чтобы LLM оценил
  • Включите критерии решения: Перечислите факторы, которые LLM должен рассмотреть
  • Тестируйте ваши промпты: Проверьте, что LLM принимает правильные решения для ваших случаев использования
  • Установите подходящие timeouts: По умолчанию 30 секунд, отрегулируйте при необходимости
  • Используйте для сложных решений: Bash hooks лучше для простых, детерминированных правил
См. справочник компонентов плагинов для деталей по созданию hooks плагинов.

События Hook

PreToolUse

Запускается после того, как Claude создаёт параметры инструмента и перед обработкой вызова инструмента. Общие матчеры:
  • Task - Задачи subagent (см. документацию subagents)
  • Bash - Команды оболочки
  • Glob - Сопоставление шаблонов файлов
  • Grep - Поиск содержимого
  • Read - Чтение файлов
  • Edit - Редактирование файлов
  • Write - Запись файлов
  • WebFetch, WebSearch - Веб-операции

PostToolUse

Запускается сразу после успешного завершения инструмента. Распознаёт те же значения матчеров, что и PreToolUse.

Notification

Запускается, когда Claude Code отправляет уведомления. Уведомления отправляются, когда:
  1. Claude нуждается в вашем разрешении для использования инструмента. Пример: “Claude needs your permission to use Bash”
  2. Входной промпт был неактивен в течение как минимум 60 секунд. “Claude is waiting for your input”

UserPromptSubmit

Запускается, когда пользователь отправляет промпт, перед обработкой Claude. Это позволяет вам добавить дополнительный контекст на основе промпта/разговора, валидировать промпты или заблокировать определённые типы промптов.

Stop

Запускается, когда основной агент Claude Code завершил ответ. Не запускается, если остановка произошла из-за прерывания пользователем.

SubagentStop

Запускается, когда subagent Claude Code (вызов инструмента Task) завершил ответ.

PreCompact

Запускается перед тем, как Claude Code собирается выполнить операцию компактирования. Матчеры:
  • manual - Вызвано из /compact
  • auto - Вызвано из auto-compact (из-за полного окна контекста)

SessionStart

Запускается, когда Claude Code запускает новую сессию или возобновляет существующую сессию (которая в настоящее время запускает новую сессию под капотом). Полезно для загрузки контекста разработки, такого как существующие проблемы или недавние изменения в вашей кодовой базе, установка зависимостей или настройка переменных окружения. Матчеры:
  • startup - Вызвано при запуске
  • resume - Вызвано из --resume, --continue или /resume
  • clear - Вызвано из /clear
  • compact - Вызвано из auto или manual compact.

Сохранение переменных окружения

SessionStart hooks имеют доступ к переменной окружения CLAUDE_ENV_FILE, которая предоставляет путь к файлу, где вы можете сохранить переменные окружения для последующих bash команд. Пример: Установка отдельных переменных окружения
#!/bin/bash

if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
  echo 'export API_KEY=your-api-key' >> "$CLAUDE_ENV_FILE"
  echo 'export PATH="$PATH:./node_modules/.bin"' >> "$CLAUDE_ENV_FILE"
fi

exit 0
Пример: Сохранение всех изменений окружения из hook Когда ваша настройка изменяет окружение (например, nvm use), захватите и сохраните все изменения, сравнив окружение:
#!/bin/bash

ENV_BEFORE=$(export -p | sort)

# Run your setup commands that modify the environment
source ~/.nvm/nvm.sh
nvm use 20

if [ -n "$CLAUDE_ENV_FILE" ]; then
  ENV_AFTER=$(export -p | sort)
  comm -13 <(echo "$ENV_BEFORE") <(echo "$ENV_AFTER") >> "$CLAUDE_ENV_FILE"
fi

exit 0
Любые переменные, записанные в этот файл, будут доступны во всех последующих bash командах, которые Claude Code выполняет во время сессии.
CLAUDE_ENV_FILE доступна только для SessionStart hooks. Другие типы hooks не имеют доступа к этой переменной.

SessionEnd

Запускается, когда сессия Claude Code заканчивается. Полезно для задач очистки, логирования статистики сессии или сохранения состояния сессии. Поле reason во входных данных hook будет одним из:
  • clear - Сессия очищена командой /clear
  • logout - Пользователь вышел
  • prompt_input_exit - Пользователь вышел, пока был виден входной промпт
  • other - Другие причины выхода

Входные данные Hook

Hooks получают JSON данные через stdin, содержащие информацию о сессии и данные, специфичные для события:
{
  // Common fields
  session_id: string
  transcript_path: string  // Path to conversation JSON
  cwd: string              // The current working directory when the hook is invoked
  permission_mode: string  // Current permission mode: "default", "plan", "acceptEdits", or "bypassPermissions"

  // Event-specific fields
  hook_event_name: string
  ...
}

Входные данные PreToolUse

Точная схема для tool_input зависит от инструмента.
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  }
}

Входные данные PostToolUse

Точная схема для tool_input и tool_response зависит от инструмента.
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PostToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_response": {
    "filePath": "/path/to/file.txt",
    "success": true
  }
}

Входные данные Notification

{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "Notification",
  "message": "Task completed successfully"
}

Входные данные UserPromptSubmit

{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "UserPromptSubmit",
  "prompt": "Write a function to calculate the factorial of a number"
}

Входные данные Stop и SubagentStop

stop_hook_active имеет значение true, когда Claude Code уже продолжает работу в результате stop hook. Проверьте это значение или обработайте транскрипт, чтобы предотвратить Claude Code от бесконечного выполнения.
{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "permission_mode": "default",
  "hook_event_name": "Stop",
  "stop_hook_active": true
}

Входные данные PreCompact

Для manual, custom_instructions поступает из того, что пользователь передаёт в /compact. Для auto, custom_instructions пуста.
{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "permission_mode": "default",
  "hook_event_name": "PreCompact",
  "trigger": "manual",
  "custom_instructions": ""
}

Входные данные SessionStart

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "permission_mode": "default",
  "hook_event_name": "SessionStart",
  "source": "startup"
}

Входные данные SessionEnd

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "SessionEnd",
  "reason": "exit"
}

Выходные данные Hook

Есть два способа для hooks возвращать выходные данные обратно в Claude Code. Выходные данные сообщают, нужно ли блокировать и любую обратную связь, которая должна быть показана Claude и пользователю.

Простой: Код выхода

Hooks сообщают статус через коды выхода, stdout и stderr:
  • Код выхода 0: Успех. stdout показывается пользователю в режиме транскрипта (CTRL-R), за исключением UserPromptSubmit и SessionStart, где stdout добавляется в контекст.
  • Код выхода 2: Ошибка блокирования. stderr передаётся Claude для автоматической обработки. См. поведение для каждого события hook ниже.
  • Другие коды выхода: Ошибка без блокирования. stderr показывается пользователю и выполнение продолжается.
Напоминание: Claude Code не видит stdout, если код выхода равен 0, за исключением hook UserPromptSubmit, где stdout внедряется как контекст.

Поведение кода выхода 2

Событие HookПоведение
PreToolUseБлокирует вызов инструмента, показывает stderr Claude
PostToolUseПоказывает stderr Claude (инструмент уже запущен)
NotificationN/A, показывает stderr только пользователю
UserPromptSubmitБлокирует обработку промпта, стирает промпт, показывает stderr только пользователю
StopБлокирует остановку, показывает stderr Claude
SubagentStopБлокирует остановку, показывает stderr subagent Claude
PreCompactN/A, показывает stderr только пользователю
SessionStartN/A, показывает stderr только пользователю
SessionEndN/A, показывает stderr только пользователю

Продвинутый: JSON выходные данные

Hooks могут возвращать структурированный JSON в stdout для более сложного управления:

Общие поля JSON

Все типы hooks могут включать эти опциональные поля:
{
  "continue": true, // Whether Claude should continue after hook execution (default: true)
  "stopReason": "string", // Message shown when continue is false

  "suppressOutput": true, // Hide stdout from transcript mode (default: false)
  "systemMessage": "string" // Optional warning message shown to the user
}
Если continue равен false, Claude останавливает обработку после выполнения hooks.
  • Для PreToolUse, это отличается от "permissionDecision": "deny", который только блокирует конкретный вызов инструмента и предоставляет автоматическую обратную связь Claude.
  • Для PostToolUse, это отличается от "decision": "block", который предоставляет автоматическую обратную связь Claude.
  • Для UserPromptSubmit, это предотвращает обработку промпта.
  • Для Stop и SubagentStop, это имеет приоритет над любым выходом "decision": "block".
  • Во всех случаях "continue" = false имеет приоритет над любым выходом "decision": "block".
stopReason сопровождает continue с причиной, показываемой пользователю, не показываемой Claude.

Управление решением PreToolUse

Hooks PreToolUse могут управлять тем, продолжится ли вызов инструмента.
  • "allow" обходит систему разрешений. permissionDecisionReason показывается пользователю, но не Claude.
  • "deny" предотвращает выполнение вызова инструмента. permissionDecisionReason показывается Claude.
  • "ask" просит пользователя подтвердить вызов инструмента в UI. permissionDecisionReason показывается пользователю, но не Claude.
Кроме того, hooks могут изменять входные данные инструмента перед выполнением, используя updatedInput:
  • updatedInput позволяет вам изменять параметры входных данных инструмента перед выполнением инструмента. Это объект Record<string, unknown>, содержащий поля, которые вы хотите изменить или добавить.
  • Это наиболее полезно с "permissionDecision": "allow" для изменения и одобрения вызовов инструментов.
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow"
    "permissionDecisionReason": "My reason here",
    "updatedInput": {
      "field_to_modify": "new value"
    }
  }
}
Поля decision и reason устарели для hooks PreToolUse. Используйте hookSpecificOutput.permissionDecision и hookSpecificOutput.permissionDecisionReason вместо этого. Устаревшие поля "approve" и "block" соответствуют "allow" и "deny" соответственно.

Управление решением PostToolUse

Hooks PostToolUse могут предоставлять обратную связь Claude после выполнения инструмента.
  • "block" автоматически запрашивает Claude с reason.
  • undefined ничего не делает. reason игнорируется.
  • "hookSpecificOutput.additionalContext" добавляет контекст для Claude для рассмотрения.
{
  "decision": "block" | undefined,
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "Additional information for Claude"
  }
}

Управление решением UserPromptSubmit

Hooks UserPromptSubmit могут управлять тем, обрабатывается ли пользовательский промпт.
  • "block" предотвращает обработку промпта. Отправленный промпт стирается из контекста. "reason" показывается пользователю, но не добавляется в контекст.
  • undefined позволяет промпту продолжаться нормально. "reason" игнорируется.
  • "hookSpecificOutput.additionalContext" добавляет строку в контекст, если не заблокирована.
{
  "decision": "block" | undefined,
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "My additional context here"
  }
}

Управление решением Stop/SubagentStop

Hooks Stop и SubagentStop могут управлять тем, должен ли Claude продолжить.
  • "block" предотвращает остановку Claude. Вы должны заполнить reason, чтобы Claude знал, как действовать дальше.
  • undefined позволяет Claude остановиться. reason игнорируется.
{
  "decision": "block" | undefined,
  "reason": "Must be provided when Claude is blocked from stopping"
}

Управление решением SessionStart

Hooks SessionStart позволяют вам загружать контекст в начале сессии.
  • "hookSpecificOutput.additionalContext" добавляет строку в контекст.
  • Значения additionalContext из нескольких hooks объединяются.
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "My additional context here"
  }
}

Управление решением SessionEnd

Hooks SessionEnd запускаются, когда сессия заканчивается. Они не могут блокировать завершение сессии но могут выполнять задачи очистки.

Пример кода выхода: Валидация Bash команды

#!/usr/bin/env python3
import json
import re
import sys

# Define validation rules as a list of (regex pattern, message) tuples
VALIDATION_RULES = [
    (
        r"\bgrep\b(?!.*\|)",
        "Use 'rg' (ripgrep) instead of 'grep' for better performance and features",
    ),
    (
        r"\bfind\s+\S+\s+-name\b",
        "Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance",
    ),
]


def validate_command(command: str) -> list[str]:
    issues = []
    for pattern, message in VALIDATION_RULES:
        if re.search(pattern, command):
            issues.append(message)
    return issues


try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
    sys.exit(1)

tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
command = tool_input.get("command", "")

if tool_name != "Bash" or not command:
    sys.exit(1)

# Validate the command
issues = validate_command(command)

if issues:
    for message in issues:
        print(f"• {message}", file=sys.stderr)
    # Exit code 2 blocks tool call and shows stderr to Claude
    sys.exit(2)

Пример JSON выходных данных: UserPromptSubmit для добавления контекста и валидации

Для hooks UserPromptSubmit, вы можете внедрить контекст, используя любой метод:
  • Код выхода 0 с stdout: Claude видит контекст (специальный случай для UserPromptSubmit)
  • JSON выходные данные: Предоставляет больше контроля над поведением
#!/usr/bin/env python3
import json
import sys
import re
import datetime

# Load input from stdin
try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
    sys.exit(1)

prompt = input_data.get("prompt", "")

# Check for sensitive patterns
sensitive_patterns = [
    (r"(?i)\b(password|secret|key|token)\s*[:=]", "Prompt contains potential secrets"),
]

for pattern, message in sensitive_patterns:
    if re.search(pattern, prompt):
        # Use JSON output to block with a specific reason
        output = {
            "decision": "block",
            "reason": f"Security policy violation: {message}. Please rephrase your request without sensitive information."
        }
        print(json.dumps(output))
        sys.exit(0)

# Add current time to context
context = f"Current time: {datetime.datetime.now()}"
print(context)

"""
The following is also equivalent:
print(json.dumps({
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": context,
  },
}))
"""

# Allow the prompt to proceed with the additional context
sys.exit(0)

Пример JSON выходных данных: PreToolUse с одобрением

#!/usr/bin/env python3
import json
import sys

# Load input from stdin
try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
    sys.exit(1)

tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})

# Example: Auto-approve file reads for documentation files
if tool_name == "Read":
    file_path = tool_input.get("file_path", "")
    if file_path.endswith((".md", ".mdx", ".txt", ".json")):
        # Use JSON output to auto-approve the tool call
        output = {
            "decision": "approve",
            "reason": "Documentation file auto-approved",
            "suppressOutput": True  # Don't show in transcript mode
        }
        print(json.dumps(output))
        sys.exit(0)

# For other cases, let the normal permission flow proceed
sys.exit(0)

Работа с MCP инструментами

Hooks Claude Code работают беспрепятственно с инструментами Model Context Protocol (MCP). Когда MCP серверы предоставляют инструменты, они появляются со специальным шаблоном имён, который вы можете сопоставить в ваших hooks.

Именование MCP инструментов

MCP инструменты следуют шаблону mcp__<server>__<tool>, например:
  • mcp__memory__create_entities - Инструмент create entities сервера Memory
  • mcp__filesystem__read_file - Инструмент read file сервера Filesystem
  • mcp__github__search_repositories - Инструмент search сервера GitHub

Конфигурирование Hooks для MCP инструментов

Вы можете нацеливаться на конкретные MCP инструменты или целые MCP серверы:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__memory__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
          }
        ]
      },
      {
        "matcher": "mcp__.*__write.*",
        "hooks": [
          {
            "type": "command",
            "command": "/home/user/scripts/validate-mcp-write.py"
          }
        ]
      }
    ]
  }
}

Примеры

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

Соображения безопасности

Отказ от ответственности

ИСПОЛЬЗУЙТЕ НА СВОЙ РИСК: Hooks Claude Code выполняют произвольные shell команды на вашей системе автоматически. Используя hooks, вы признаёте, что:
  • Вы несёте исключительную ответственность за команды, которые вы настраиваете
  • Hooks могут изменять, удалять или получать доступ к любым файлам, к которым может получить доступ ваша учётная запись пользователя
  • Вредоносные или плохо написанные hooks могут вызвать потерю данных или повреждение системы
  • Anthropic не предоставляет гарантию и не несёт ответственность за любые убытки в результате использования hooks
  • Вы должны тщательно тестировать hooks в безопасной среде перед использованием в производстве
Всегда проверяйте и понимайте любые команды hook перед добавлением их в вашу конфигурацию.

Лучшие практики безопасности

Вот некоторые ключевые практики для написания более безопасных hooks:
  1. Валидируйте и санитизируйте входные данные - Никогда не доверяйте входным данным вслепую
  2. Всегда заключайте переменные оболочки в кавычки - Используйте "$VAR" а не $VAR
  3. Блокируйте обход пути - Проверьте наличие .. в путях файлов
  4. Используйте абсолютные пути - Укажите полные пути для скриптов (используйте “$CLAUDE_PROJECT_DIR” для пути проекта)
  5. Пропускайте чувствительные файлы - Избегайте .env, .git/, ключей и т.д.

Безопасность конфигурации

Прямые редактирования hooks в файлах настроек не вступают в силу немедленно. Claude Code:
  1. Захватывает снимок hooks при запуске
  2. Использует этот снимок на протяжении всей сессии
  3. Предупреждает, если hooks изменены извне
  4. Требует проверки в меню /hooks для применения изменений
Это предотвращает вредоносные изменения hook от влияния на вашу текущую сессию.

Детали выполнения Hook

  • Timeout: Лимит выполнения 60 секунд по умолчанию, настраивается для каждой команды.
    • Timeout для отдельной команды не влияет на другие команды.
  • Параллелизация: Все совпадающие hooks запускаются параллельно
  • Дедупликация: Несколько идентичных команд hook автоматически дедублируются
  • Окружение: Запускается в текущей директории с окружением Claude Code
    • Переменная окружения CLAUDE_PROJECT_DIR доступна и содержит абсолютный путь к корневой директории проекта (где был запущен Claude Code)
    • Переменная окружения CLAUDE_CODE_REMOTE указывает, запущен ли hook в удалённом (веб) окружении ("true") или локальном CLI окружении (не установлена или пуста). Используйте это для запуска различной логики в зависимости от контекста выполнения.
  • Входные данные: JSON через stdin
  • Выходные данные:
    • PreToolUse/PostToolUse/Stop/SubagentStop: Прогресс показан в транскрипте (Ctrl-R)
    • Notification/SessionEnd: Логируется только в debug (--debug)
    • UserPromptSubmit/SessionStart: stdout добавлен как контекст для Claude

Отладка

Базовое устранение неполадок

Если ваши hooks не работают:
  1. Проверьте конфигурацию - Запустите /hooks чтобы увидеть, зарегистрирован ли ваш hook
  2. Проверьте синтаксис - Убедитесь, что ваш JSON в настройках действителен
  3. Тестируйте команды - Сначала запустите команды hook вручную
  4. Проверьте разрешения - Убедитесь, что скрипты исполняемы
  5. Проверьте логи - Используйте claude --debug чтобы увидеть детали выполнения hook
Общие проблемы:
  • Кавычки не экранированы - Используйте \" внутри JSON строк
  • Неправильный матчер - Проверьте, что имена инструментов совпадают точно (чувствительны к регистру)
  • Команда не найдена - Используйте полные пути для скриптов

Продвинутая отладка

Для сложных проблем с hooks:
  1. Проверьте выполнение hook - Используйте claude --debug чтобы увидеть детальное выполнение hook
  2. Валидируйте JSON схемы - Тестируйте входные/выходные данные hook с внешними инструментами
  3. Проверьте переменные окружения - Проверьте, что окружение Claude Code правильно
  4. Тестируйте граничные случаи - Попробуйте hooks с необычными путями файлов или входными данными
  5. Мониторьте ресурсы системы - Проверьте на истощение ресурсов во время выполнения hook
  6. Используйте структурированное логирование - Реализуйте логирование в ваших скриптах hook

Пример выходных данных отладки

Используйте claude --debug чтобы увидеть детали выполнения hook:
[DEBUG] Executing hooks for PostToolUse:Write
[DEBUG] Getting matching hook commands for PostToolUse with query: Write
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 hooks for query "Write"
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: <Your command> with timeout 60000ms
[DEBUG] Hook command completed with status 0: <Your stdout>
Сообщения о прогрессе появляются в режиме транскрипта (Ctrl-R) показывая:
  • Какой hook запущен
  • Выполняемая команда
  • Статус успеха/неудачи
  • Выходные данные или сообщения об ошибках