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

Для справочной документации по хукам см. Справочник по хукам.

Примеры случаев использования хуков включают:

  • Уведомления: Настройте способ получения уведомлений, когда Claude Code ожидает ваш ввод или разрешение на выполнение чего-либо.
  • Автоматическое форматирование: Запускайте prettier для .ts файлов, gofmt для .go файлов и т.д. после каждого редактирования файла.
  • Логирование: Отслеживайте и подсчитывайте все выполненные команды для соответствия требованиям или отладки.
  • Обратная связь: Предоставляйте автоматическую обратную связь, когда Claude Code создает код, который не соответствует соглашениям вашей кодовой базы.
  • Пользовательские разрешения: Блокируйте изменения в производственных файлах или чувствительных каталогах.

Кодируя эти правила как хуки, а не инструкции в промптах, вы превращаете предложения в код уровня приложения, который выполняется каждый раз, когда ожидается его запуск.

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

Для полных рекомендаций по безопасности см. Соображения безопасности в справочной документации по хукам.

Обзор событий хуков

Claude Code предоставляет несколько событий хуков, которые запускаются в разных точках рабочего процесса:

  • PreToolUse: Запускается перед вызовами инструментов (может их блокировать)
  • PostToolUse: Запускается после завершения вызовов инструментов
  • UserPromptSubmit: Запускается, когда пользователь отправляет промпт, до того как Claude его обработает
  • Notification: Запускается, когда Claude Code отправляет уведомления
  • Stop: Запускается, когда Claude Code завершает ответ
  • SubagentStop: Запускается, когда завершаются задачи подагента
  • PreCompact: Запускается перед тем, как Claude Code собирается выполнить операцию сжатия
  • SessionStart: Запускается, когда Claude Code начинает новую сессию или возобновляет существующую сессию
  • SessionEnd: Запускается, когда сессия Claude Code завершается

Каждое событие получает разные данные и может контролировать поведение Claude разными способами.

Быстрый старт

В этом быстром старте вы добавите хук, который логирует команды оболочки, которые выполняет Claude Code.

Предварительные требования

Установите jq для обработки JSON в командной строке.

Шаг 1: Откройте конфигурацию хуков

Выполните слэш-команду /hooks и выберите событие хука PreToolUse.

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

Шаг 2: Добавьте сопоставитель

Выберите + Add new matcher…, чтобы запускать ваш хук только для вызовов инструмента Bash.

Введите Bash для сопоставителя.

Вы можете использовать * для сопоставления всех инструментов.

Шаг 3: Добавьте хук

Выберите + Add new hook… и введите эту команду:

jq -r '"\(.tool_input.command) - \(.tool_input.description // "No description")"' >> ~/.claude/bash-command-log.txt

Шаг 4: Сохраните вашу конфигурацию

Для места хранения выберите User settings, поскольку вы логируете в ваш домашний каталог. Этот хук будет применяться ко всем проектам, а не только к вашему текущему проекту.

Затем нажмите Esc, пока не вернетесь к REPL. Ваш хук теперь зарегистрирован!

Шаг 5: Проверьте ваш хук

Выполните /hooks снова или проверьте ~/.claude/settings.json, чтобы увидеть вашу конфигурацию:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

Шаг 6: Протестируйте ваш хук

Попросите Claude выполнить простую команду, например ls, и проверьте ваш файл логов:

cat ~/.claude/bash-command-log.txt

Вы должны увидеть записи вроде:

ls - Lists files and directories

Больше примеров

Для полного примера реализации см. пример валидатора bash команд в нашей публичной кодовой базе.

Хук форматирования кода

Автоматически форматируйте файлы TypeScript после редактирования:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|MultiEdit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | { read file_path; if echo \"$file_path\" | grep -q '\\.ts$'; then npx prettier --write \"$file_path\"; fi; }"
          }
        ]
      }
    ]
  }
}

Хук форматирования Markdown

Автоматически исправляйте отсутствующие языковые теги и проблемы форматирования в markdown файлах:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|MultiEdit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/markdown_formatter.py"
          }
        ]
      }
    ]
  }
}

Создайте .claude/hooks/markdown_formatter.py с этим содержимым:

#!/usr/bin/env python3
"""
Форматировщик Markdown для вывода Claude Code.
Исправляет отсутствующие языковые теги и проблемы с интервалами, сохраняя содержимое кода.
"""
import json
import sys
import re
import os

def detect_language(code):
    """Определение языка из содержимого кода с максимальными усилиями."""
    s = code.strip()
    
    # Определение JSON
    if re.search(r'^\s*[{\[]', s):
        try:
            json.loads(s)
            return 'json'
        except:
            pass
    
    # Определение Python
    if re.search(r'^\s*def\s+\w+\s*\(', s, re.M) or \
       re.search(r'^\s*(import|from)\s+\w+', s, re.M):
        return 'python'
    
    # Определение JavaScript  
    if re.search(r'\b(function\s+\w+\s*\(|const\s+\w+\s*=)', s) or \
       re.search(r'=>|console\.(log|error)', s):
        return 'javascript'
    
    # Определение Bash
    if re.search(r'^#!.*\b(bash|sh)\b', s, re.M) or \
       re.search(r'\b(if|then|fi|for|in|do|done)\b', s):
        return 'bash'
    
    # Определение SQL
    if re.search(r'\b(SELECT|INSERT|UPDATE|DELETE|CREATE)\s+', s, re.I):
        return 'sql'
        
    return 'text'

def format_markdown(content):
    """Форматирование содержимого markdown с определением языка."""
    # Исправление неподписанных блоков кода
    def add_lang_to_fence(match):
        indent, info, body, closing = match.groups()
        if not info.strip():
            lang = detect_language(body)
            return f"{indent}```{lang}\n{body}{closing}\n"
        return match.group(0)
    
    fence_pattern = r'(?ms)^([ \t]{0,3})```([^\n]*)\n(.*?)(\n\1```)\s*$'
    content = re.sub(fence_pattern, add_lang_to_fence, content)
    
    # Исправление избыточных пустых строк (только вне блоков кода)
    content = re.sub(r'\n{3,}', '\n\n', content)
    
    return content.rstrip() + '\n'

# Основное выполнение
try:
    input_data = json.load(sys.stdin)
    file_path = input_data.get('tool_input', {}).get('file_path', '')
    
    if not file_path.endswith(('.md', '.mdx')):
        sys.exit(0)  # Не markdown файл
    
    if os.path.exists(file_path):
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        formatted = format_markdown(content)
        
        if formatted != content:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(formatted)
            print(f"✓ Исправлено форматирование markdown в {file_path}")
    
except Exception as e:
    print(f"Ошибка форматирования markdown: {e}", file=sys.stderr)
    sys.exit(1)

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

chmod +x .claude/hooks/markdown_formatter.py

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

  • Определяет языки программирования в неподписанных блоках кода
  • Добавляет соответствующие языковые теги для подсветки синтаксиса
  • Исправляет избыточные пустые строки, сохраняя содержимое кода
  • Обрабатывает только markdown файлы (.md, .mdx)

Хук пользовательских уведомлений

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

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Ожидается ваш ввод'"
          }
        ]
      }
    ]
  }
}

Хук защиты файлов

Блокируйте редактирование чувствительных файлов:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|MultiEdit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"import json, sys; data=json.load(sys.stdin); path=data.get('tool_input',{}).get('file_path',''); sys.exit(2 if any(p in path for p in ['.env', 'package-lock.json', '.git/']) else 0)\""
          }
        ]
      }
    ]
  }
}

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

  • Для справочной документации по хукам см. Справочник по хукам.
  • Для комплексных рекомендаций по безопасности и руководящих принципов безопасности см. Соображения безопасности в справочной документации по хукам.
  • Для шагов по устранению неполадок и техник отладки см. Отладка в справочной документации по хукам.