Zum Hauptinhalt springen
Claude Code Hooks sind benutzerdefinierte Shell-Befehle, die an verschiedenen Punkten im Lebenszyklus von Claude Code ausgeführt werden. Hooks bieten deterministische Kontrolle über Claude Codes Verhalten und stellen sicher, dass bestimmte Aktionen immer ausgeführt werden, anstatt sich darauf zu verlassen, dass das LLM sich dafür entscheidet, sie auszuführen.
Referenzdokumentation zu Hooks finden Sie unter Hooks-Referenz.
Beispiele für Anwendungsfälle für Hooks sind:
  • Benachrichtigungen: Passen Sie an, wie Sie benachrichtigt werden, wenn Claude Code auf Ihre Eingabe oder Genehmigung wartet, um etwas auszuführen.
  • Automatische Formatierung: Führen Sie prettier auf .ts-Dateien, gofmt auf .go-Dateien usw. nach jeder Dateibearbeitung aus.
  • Protokollierung: Verfolgen und zählen Sie alle ausgeführten Befehle für Compliance oder Debugging.
  • Feedback: Geben Sie automatisches Feedback, wenn Claude Code Code erzeugt, der nicht Ihren Codebase-Konventionen entspricht.
  • Benutzerdefinierte Berechtigungen: Blockieren Sie Änderungen an Produktionsdateien oder sensiblen Verzeichnissen.
Durch die Codierung dieser Regeln als Hooks anstelle von Eingabeaufforderungsinstruktionen verwandeln Sie Vorschläge in Code auf Anwendungsebene, der jedes Mal ausgeführt wird, wenn er ausgeführt werden soll.
Sie müssen die Sicherheitsauswirkungen von Hooks berücksichtigen, wenn Sie diese hinzufügen, da Hooks automatisch während der Agent-Schleife mit den Anmeldedaten Ihrer aktuellen Umgebung ausgeführt werden. Beispielsweise kann bösartiger Hook-Code Ihre Daten exfiltrieren. Überprüfen Sie immer Ihre Hook-Implementierung, bevor Sie sie registrieren.Für vollständige Sicherheitsbestpraktiken siehe Sicherheitsüberlegungen in der Hooks-Referenzdokumentation.

Übersicht der Hook-Ereignisse

Claude Code bietet mehrere Hook-Ereignisse, die an verschiedenen Punkten im Workflow ausgeführt werden:
  • PreToolUse: Wird vor Tool-Aufrufen ausgeführt (kann diese blockieren)
  • PostToolUse: Wird nach Abschluss von Tool-Aufrufen ausgeführt
  • UserPromptSubmit: Wird ausgeführt, wenn der Benutzer eine Eingabeaufforderung einreicht, bevor Claude sie verarbeitet
  • Notification: Wird ausgeführt, wenn Claude Code Benachrichtigungen sendet
  • Stop: Wird ausgeführt, wenn Claude Code die Antwort beendet
  • SubagentStop: Wird ausgeführt, wenn Subagent-Aufgaben abgeschlossen sind
  • PreCompact: Wird ausgeführt, bevor Claude Code eine Kompaktoperation ausführen soll
  • SessionStart: Wird ausgeführt, wenn Claude Code eine neue Sitzung startet oder eine vorhandene Sitzung fortsetzt
  • SessionEnd: Wird ausgeführt, wenn die Claude Code-Sitzung endet
Jedes Ereignis empfängt unterschiedliche Daten und kann Claudes Verhalten auf unterschiedliche Weise steuern.

Schnellstart

In diesem Schnellstart fügen Sie einen Hook hinzu, der die Shell-Befehle protokolliert, die Claude Code ausführt.

Voraussetzungen

Installieren Sie jq zur JSON-Verarbeitung in der Befehlszeile.

Schritt 1: Öffnen Sie die Hooks-Konfiguration

Führen Sie den /hooks Schrägstrich-Befehl aus und wählen Sie das PreToolUse Hook-Ereignis. PreToolUse Hooks werden vor Tool-Aufrufen ausgeführt und können diese blockieren, während sie Claude Feedback darüber geben, was anders zu tun ist.

Schritt 2: Fügen Sie einen Matcher hinzu

Wählen Sie + Add new matcher… aus, um Ihren Hook nur auf Bash-Tool-Aufrufe auszuführen. Geben Sie Bash für den Matcher ein.
Sie können * verwenden, um alle Tools zu entsprechen.

Schritt 3: Fügen Sie den Hook hinzu

Wählen Sie + Add new hook… und geben Sie diesen Befehl ein:
jq -r '"\(.tool_input.command) - \(.tool_input.description // "No description")"' >> ~/.claude/bash-command-log.txt

Schritt 4: Speichern Sie Ihre Konfiguration

Wählen Sie für den Speicherort User settings, da Sie in Ihrem Home-Verzeichnis protokollieren. Dieser Hook wird dann auf alle Projekte angewendet, nicht nur auf Ihr aktuelles Projekt. Drücken Sie dann Esc, bis Sie zur REPL zurückkehren. Ihr Hook ist jetzt registriert!

Schritt 5: Überprüfen Sie Ihren Hook

Führen Sie /hooks erneut aus oder überprüfen Sie ~/.claude/settings.json, um Ihre Konfiguration anzuzeigen:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

Schritt 6: Testen Sie Ihren Hook

Bitten Sie Claude, einen einfachen Befehl wie ls auszuführen, und überprüfen Sie Ihre Protokolldatei:
cat ~/.claude/bash-command-log.txt
Sie sollten Einträge wie diese sehen:
ls - Lists files and directories

Weitere Beispiele

Ein vollständiges Beispiel für eine Implementierung finden Sie im Bash-Befehlsvalidator-Beispiel in unserer öffentlichen Codebasis.

Code-Formatierungs-Hook

Formatieren Sie TypeScript-Dateien automatisch nach der Bearbeitung:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|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-Formatierungs-Hook

Beheben Sie automatisch fehlende Sprach-Tags und Formatierungsprobleme in Markdown-Dateien:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/markdown_formatter.py"
          }
        ]
      }
    ]
  }
}
Erstellen Sie .claude/hooks/markdown_formatter.py mit diesem Inhalt:
#!/usr/bin/env python3
"""
Markdown formatter for Claude Code output.
Fixes missing language tags and spacing issues while preserving code content.
"""
import json
import sys
import re
import os

def detect_language(code):
    """Best-effort language detection from code content."""
    s = code.strip()
    
    # JSON detection
    if re.search(r'^\s*[{\[]', s):
        try:
            json.loads(s)
            return 'json'
        except:
            pass
    
    # Python detection
    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 detection  
    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 detection
    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 detection
    if re.search(r'\b(SELECT|INSERT|UPDATE|DELETE|CREATE)\s+', s, re.I):
        return 'sql'
        
    return 'text'

def format_markdown(content):
    """Format markdown content with language detection."""
    # Fix unlabeled code fences
    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)
    
    # Fix excessive blank lines (only outside code fences)
    content = re.sub(r'\n{3,}', '\n\n', content)
    
    return content.rstrip() + '\n'

# Main execution
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)  # Not a markdown file
    
    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"✓ Fixed markdown formatting in {file_path}")
    
except Exception as e:
    print(f"Error formatting markdown: {e}", file=sys.stderr)
    sys.exit(1)
Machen Sie das Skript ausführbar:
chmod +x .claude/hooks/markdown_formatter.py
Dieser Hook führt automatisch folgende Aktionen aus:
  • Erkennt Programmiersprachen in nicht gekennzeichneten Code-Blöcken
  • Fügt geeignete Sprach-Tags für Syntax-Hervorhebung hinzu
  • Behebt übermäßige Leerzeilen, während Code-Inhalte erhalten bleiben
  • Verarbeitet nur Markdown-Dateien (.md, .mdx)

Benutzerdefinierter Benachrichtigungs-Hook

Erhalten Sie Desktop-Benachrichtigungen, wenn Claude Eingaben benötigt:
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Awaiting your input'"
          }
        ]
      }
    ]
  }
}

Dateischutz-Hook

Blockieren Sie Bearbeitungen an sensiblen Dateien:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|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)\""
          }
        ]
      }
    ]
  }
}

Weitere Informationen

  • Referenzdokumentation zu Hooks finden Sie unter Hooks-Referenz.
  • Umfassende Sicherheitsbestpraktiken und Sicherheitsrichtlinien finden Sie unter Sicherheitsüberlegungen in der Hooks-Referenzdokumentation.
  • Schritte zur Fehlerbehebung und Debugging-Techniken finden Sie unter Debugging in der Hooks-Referenzdokumentation.