Einführung

Claude Code Hooks sind benutzerdefinierte Shell-Befehle, die an verschiedenen Punkten im Lebenszyklus von Claude Code ausgeführt werden. Hooks bieten deterministische Kontrolle über das Verhalten von Claude Code und stellen sicher, dass bestimmte Aktionen immer ausgeführt werden, anstatt sich darauf zu verlassen, dass das LLM sie ausführt.

Beispiele für Anwendungsfälle sind:

  • Benachrichtigungen: Passen Sie an, wie Sie benachrichtigt werden, wenn Claude Code auf Ihre Eingabe oder Berechtigung wartet, 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: Bieten Sie automatisiertes Feedback, wenn Claude Code Code produziert, der nicht Ihren Codebase-Konventionen folgt.
  • Benutzerdefinierte Berechtigungen: Blockieren Sie Änderungen an Produktionsdateien oder sensiblen Verzeichnissen.

Indem Sie diese Regeln als Hooks anstatt als Prompt-Anweisungen kodieren, verwandeln Sie Vorschläge in App-Level-Code, der jedes Mal ausgeführt wird, wenn er ausgeführt werden soll.

Hooks führen Shell-Befehle mit Ihren vollen Benutzerberechtigungen ohne Bestätigung aus. Sie sind dafür verantwortlich, sicherzustellen, dass Ihre Hooks sicher und geschützt sind. Anthropic ist nicht haftbar für Datenverlust oder Systemschäden, die durch die Verwendung von Hooks entstehen. Überprüfen Sie Sicherheitsüberlegungen.

Schnellstart

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

Schnellstart-Voraussetzung: Installieren Sie jq für JSON-Verarbeitung in der Befehlszeile.

Schritt 1: Hooks-Konfiguration öffnen

Führen Sie den /hooks Slash-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: Einen Matcher hinzufügen

Wählen Sie + Add new matcher…, um Ihren Hook nur bei Bash-Tool-Aufrufen auszuführen.

Geben Sie Bash für den Matcher ein.

Schritt 3: Den Hook hinzufügen

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: Ihre Konfiguration speichern

Wählen Sie für den Speicherort User settings, da Sie in Ihr 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: Ihren Hook überprüfen

Führen Sie /hooks erneut aus oder überprüfen Sie ~/.claude/settings.json, um Ihre Konfiguration zu sehen:

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

Konfiguration

Claude Code Hooks werden in Ihren Einstellungsdateien konfiguriert:

  • ~/.claude/settings.json - Benutzereinstellungen
  • .claude/settings.json - Projekteinstellungen
  • .claude/settings.local.json - Lokale Projekteinstellungen (nicht committet)
  • Enterprise-verwaltete Richtlinieneinstellungen

Struktur

Hooks sind nach Matchern organisiert, wobei jeder Matcher mehrere Hooks haben kann:

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here"
          }
        ]
      }
    ]
  }
}
  • matcher: Muster zum Abgleichen von Tool-Namen (nur anwendbar für PreToolUse und PostToolUse)
    • Einfache Strings stimmen genau überein: Write stimmt nur mit dem Write-Tool überein
    • Unterstützt Regex: Edit|Write oder Notebook.*
    • Wenn weggelassen oder leerer String, werden Hooks für alle übereinstimmenden Ereignisse ausgeführt
  • hooks: Array von Befehlen, die ausgeführt werden, wenn das Muster übereinstimmt
    • type: Derzeit wird nur "command" unterstützt
    • command: Der auszuführende Bash-Befehl
    • timeout: (Optional) Wie lange ein Befehl laufen soll, in Sekunden, bevor alle laufenden Hooks abgebrochen werden.

Hook-Ereignisse

PreToolUse

Wird ausgeführt, nachdem Claude Tool-Parameter erstellt hat und bevor der Tool-Aufruf verarbeitet wird.

Häufige Matcher:

  • Task - Agent-Aufgaben
  • Bash - Shell-Befehle
  • Glob - Dateimuster-Abgleich
  • Grep - Inhaltssuche
  • Read - Datei lesen
  • Edit, MultiEdit - Dateibearbeitung
  • Write - Datei schreiben
  • WebFetch, WebSearch - Web-Operationen

PostToolUse

Wird unmittelbar nach erfolgreichem Abschluss eines Tools ausgeführt.

Erkennt dieselben Matcher-Werte wie PreToolUse.

Notification

Wird ausgeführt, wenn Claude Code Benachrichtigungen sendet.

Stop

Wird ausgeführt, wenn der Haupt-Claude Code Agent seine Antwort beendet hat.

SubagentStop

Wird ausgeführt, wenn ein Claude Code Subagent (Task-Tool-Aufruf) seine Antwort beendet hat.

Hook-Eingabe

Hooks erhalten JSON-Daten über stdin, die Sitzungsinformationen und ereignisspezifische Daten enthalten:

{
  // Gemeinsame Felder
  session_id: string
  transcript_path: string  // Pfad zur Konversations-JSON

  // Ereignisspezifische Felder
  ...
}

PreToolUse-Eingabe

Das genaue Schema für tool_input hängt vom Tool ab.

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  }
}

PostToolUse-Eingabe

Das genaue Schema für tool_input und tool_response hängt vom Tool ab.

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_response": {
    "filePath": "/path/to/file.txt",
    "success": true
  }
}

Notification-Eingabe

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "message": "Task completed successfully",
  "title": "Claude Code"
}

Stop- und SubagentStop-Eingabe

stop_hook_active ist true, wenn Claude Code bereits als Ergebnis eines Stop-Hooks fortfährt. Überprüfen Sie diesen Wert oder verarbeiten Sie das Transkript, um zu verhindern, dass Claude Code unendlich läuft.

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "stop_hook_active": true
}

Hook-Ausgabe

Es gibt zwei Möglichkeiten für Hooks, Ausgaben an Claude Code zurückzugeben. Die Ausgabe kommuniziert, ob blockiert werden soll und welches Feedback Claude und dem Benutzer gezeigt werden soll.

Einfach: Exit-Code

Hooks kommunizieren den Status über Exit-Codes, stdout und stderr:

  • Exit-Code 0: Erfolg. stdout wird dem Benutzer im Transkript-Modus gezeigt (CTRL-R).
  • Exit-Code 2: Blockierender Fehler. stderr wird an Claude zurückgegeben, um automatisch verarbeitet zu werden. Siehe Verhalten pro Hook-Ereignis unten.
  • Andere Exit-Codes: Nicht-blockierender Fehler. stderr wird dem Benutzer gezeigt und die Ausführung wird fortgesetzt.

Erinnerung: Claude Code sieht stdout nicht, wenn der Exit-Code 0 ist.

Exit-Code 2 Verhalten

Hook-EreignisVerhalten
PreToolUseBlockiert den Tool-Aufruf, zeigt Fehler an Claude
PostToolUseZeigt Fehler an Claude (Tool wurde bereits ausgeführt)
NotificationN/A, zeigt stderr nur dem Benutzer
StopBlockiert das Stoppen, zeigt Fehler an Claude
SubagentStopBlockiert das Stoppen, zeigt Fehler an Claude-Subagent

Erweitert: JSON-Ausgabe

Hooks können strukturiertes JSON in stdout für anspruchsvollere Kontrolle zurückgeben:

Gemeinsame JSON-Felder

Alle Hook-Typen können diese optionalen Felder enthalten:

{
  "continue": true, // Ob Claude nach der Hook-Ausführung fortfahren soll (Standard: true)
  "stopReason": "string" // Nachricht, die angezeigt wird, wenn continue false ist
  "suppressOutput": true, // stdout vom Transkript-Modus ausblenden (Standard: false)
}

Wenn continue false ist, stoppt Claude die Verarbeitung nach der Ausführung der Hooks.

  • Für PreToolUse ist dies anders als "decision": "block", was nur einen spezifischen Tool-Aufruf blockiert und automatisches Feedback an Claude liefert.
  • Für PostToolUse ist dies anders als "decision": "block", was automatisiertes Feedback an Claude liefert.
  • Für Stop und SubagentStop hat dies Vorrang vor jeder "decision": "block" Ausgabe.
  • In allen Fällen hat "continue" = false Vorrang vor jeder "decision": "block" Ausgabe.

stopReason begleitet continue mit einem Grund, der dem Benutzer gezeigt wird, nicht Claude.

PreToolUse Entscheidungskontrolle

PreToolUse Hooks können kontrollieren, ob ein Tool-Aufruf fortgesetzt wird.

  • “approve” umgeht das Berechtigungssystem. reason wird dem Benutzer gezeigt, aber nicht Claude.
  • “block” verhindert, dass der Tool-Aufruf ausgeführt wird. reason wird Claude gezeigt.
  • undefined führt zum bestehenden Berechtigungsablauf. reason wird ignoriert.
{
  "decision": "approve" | "block" | undefined,
  "reason": "Erklärung für die Entscheidung"
}

PostToolUse Entscheidungskontrolle

PostToolUse Hooks können kontrollieren, ob ein Tool-Aufruf fortgesetzt wird.

  • “block” fordert Claude automatisch mit reason auf.
  • undefined tut nichts. reason wird ignoriert.
{
  "decision": "block" | undefined,
  "reason": "Erklärung für die Entscheidung"
}

Stop/SubagentStop Entscheidungskontrolle

Stop und SubagentStop Hooks können kontrollieren, ob Claude fortfahren muss.

  • “block” verhindert, dass Claude stoppt. Sie müssen reason ausfüllen, damit Claude weiß, wie es weitergehen soll.
  • undefined erlaubt Claude zu stoppen. reason wird ignoriert.
{
  "decision": "block" | undefined,
  "reason": "Muss bereitgestellt werden, wenn Claude am Stoppen gehindert wird"
}

JSON-Ausgabe-Beispiel: Bash-Befehl-Bearbeitung

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

# Definiere Validierungsregeln als Liste von (Regex-Muster, Nachricht) Tupeln
VALIDATION_RULES = [
    (
        r"\bgrep\b(?!.*\|)",
        "Verwenden Sie 'rg' (ripgrep) anstelle von 'grep' für bessere Leistung und Funktionen",
    ),
    (
        r"\bfind\s+\S+\s+-name\b",
        "Verwenden Sie 'rg --files | rg pattern' oder 'rg --files -g pattern' anstelle von 'find -name' für bessere Leistung",
    ),
]


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"Fehler: Ungültige JSON-Eingabe: {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)

# Validiere den Befehl
issues = validate_command(command)

if issues:
    for message in issues:
        print(f"• {message}", file=sys.stderr)
    # Exit-Code 2 blockiert Tool-Aufruf und zeigt stderr an Claude
    sys.exit(2)

Arbeiten mit MCP-Tools

Claude Code Hooks funktionieren nahtlos mit Model Context Protocol (MCP) Tools. Wenn MCP-Server Tools bereitstellen, erscheinen sie mit einem speziellen Benennungsmuster, das Sie in Ihren Hooks abgleichen können.

MCP-Tool-Benennung

MCP-Tools folgen dem Muster mcp__<server>__<tool>, zum Beispiel:

  • mcp__memory__create_entities - Memory-Server’s create entities Tool
  • mcp__filesystem__read_file - Filesystem-Server’s read file Tool
  • mcp__github__search_repositories - GitHub-Server’s search Tool

Konfiguration von Hooks für MCP-Tools

Sie können spezifische MCP-Tools oder ganze MCP-Server ansprechen:

{
  "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"
          }
        ]
      }
    ]
  }
}

Beispiele

Code-Formatierung

Automatische Formatierung von Code nach Dateiänderungen:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "/home/user/scripts/format-code.sh"
          }
        ]
      }
    ]
  }
}

Benachrichtigung

Passen Sie die Benachrichtigung an, die gesendet wird, wenn Claude Code eine Berechtigung anfordert oder wenn die Prompt-Eingabe inaktiv geworden ist.

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/my_custom_notifier.py"
          }
        ]
      }
    ]
  }
}

Sicherheitsüberlegungen

Haftungsausschluss

VERWENDUNG AUF EIGENE GEFAHR: Claude Code Hooks führen beliebige Shell-Befehle auf Ihrem System automatisch aus. Durch die Verwendung von Hooks erkennen Sie an, dass:

  • Sie allein verantwortlich für die Befehle sind, die Sie konfigurieren
  • Hooks alle Dateien ändern, löschen oder darauf zugreifen können, auf die Ihr Benutzerkonto zugreifen kann
  • Bösartige oder schlecht geschriebene Hooks Datenverlust oder Systemschäden verursachen können
  • Anthropic keine Garantie bietet und keine Haftung für Schäden übernimmt, die durch die Verwendung von Hooks entstehen
  • Sie Hooks gründlich in einer sicheren Umgebung testen sollten, bevor Sie sie in der Produktion verwenden

Überprüfen und verstehen Sie immer alle Hook-Befehle, bevor Sie sie zu Ihrer Konfiguration hinzufügen.

Sicherheits-Best-Practices

Hier sind einige wichtige Praktiken für das Schreiben sichererer Hooks:

  1. Eingaben validieren und bereinigen - Vertrauen Sie Eingabedaten niemals blind
  2. Shell-Variablen immer in Anführungszeichen setzen - Verwenden Sie "$VAR" nicht $VAR
  3. Pfad-Traversierung blockieren - Prüfen Sie auf .. in Dateipfaden
  4. Absolute Pfade verwenden - Geben Sie vollständige Pfade für Skripte an
  5. Sensible Dateien überspringen - Vermeiden Sie .env, .git/, Schlüssel usw.

Konfigurationssicherheit

Direkte Bearbeitungen von Hooks in Einstellungsdateien werden nicht sofort wirksam. Claude Code:

  1. Erfasst einen Snapshot von Hooks beim Start
  2. Verwendet diesen Snapshot während der gesamten Sitzung
  3. Warnt, wenn Hooks extern geändert werden
  4. Erfordert eine Überprüfung im /hooks Menü, damit Änderungen angewendet werden

Dies verhindert, dass bösartige Hook-Änderungen Ihre aktuelle Sitzung beeinträchtigen.

Hook-Ausführungsdetails

  • Timeout: 60-Sekunden-Ausführungslimit standardmäßig, pro Befehl konfigurierbar.
    • Wenn ein einzelner Befehl das Timeout erreicht, werden alle laufenden Hooks abgebrochen.
  • Parallelisierung: Alle übereinstimmenden Hooks laufen parallel
  • Umgebung: Läuft im aktuellen Verzeichnis mit Claude Code’s Umgebung
  • Eingabe: JSON über stdin
  • Ausgabe:
    • PreToolUse/PostToolUse/Stop: Fortschritt im Transkript gezeigt (Ctrl-R)
    • Notification: Nur im Debug protokolliert (--debug)

Debugging

Zur Fehlerbehebung bei Hooks:

  1. Überprüfen Sie, ob das /hooks Menü Ihre Konfiguration anzeigt
  2. Stellen Sie sicher, dass Ihre Einstellungsdateien gültiges JSON sind
  3. Testen Sie Befehle manuell
  4. Überprüfen Sie Exit-Codes
  5. Überprüfen Sie stdout- und stderr-Formaterwartungen
  6. Stellen Sie ordnungsgemäße Anführungszeichen-Escaping sicher
  7. Verw enden Sie claude --debug, um Ihre Hooks zu debuggen. Die Ausgabe eines erfolgreichen Hooks erscheint wie unten.
[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>

Fortschrittsnachrichten erscheinen im Transkript-Modus (Ctrl-R) und zeigen:

  • Welcher Hook läuft
  • Befehl, der ausgeführt wird
  • Erfolg-/Fehlerstatus
  • Ausgabe- oder Fehlermeldungen