Zum Hauptinhalt springen
Eine Schnellstartanleitung mit Beispielen finden Sie unter Erste Schritte mit Claude Code Hooks.

Konfiguration

Claude Code Hooks werden in Ihren Einstellungsdateien konfiguriert:
  • ~/.claude/settings.json - Benutzereinstellungen
  • .claude/settings.json - Projekteinstellungen
  • .claude/settings.local.json - Lokale Projekteinstellungen (nicht committed)
  • Von Unternehmen 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 Abgleich von Toolnamen, Groß-/Kleinschreibung beachtet (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.*
    • Verwenden Sie * um alle Tools abzugleichen. Sie können auch eine leere Zeichenkette ("") verwenden oder matcher leer lassen.
  • hooks: Array von Hooks, die ausgeführt werden, wenn das Muster übereinstimmt
    • type: Hook-Ausführungstyp - "command" für Bash-Befehle oder "prompt" für LLM-basierte Evaluierung
    • command: (Für type: "command") Der auszuführende Bash-Befehl (kann die Umgebungsvariable $CLAUDE_PROJECT_DIR verwenden)
    • prompt: (Für type: "prompt") Der Prompt, der an das LLM zur Evaluierung gesendet wird
    • timeout: (Optional) Wie lange ein Hook ausgeführt werden soll, in Sekunden, bevor dieser spezifische Hook abgebrochen wird
Für Ereignisse wie UserPromptSubmit, Notification, Stop und SubagentStop die keine Matcher verwenden, können Sie das Matcher-Feld weglassen:
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/prompt-validator.py"
          }
        ]
      }
    ]
  }
}

Projektspezifische Hook-Skripte

Sie können die Umgebungsvariable CLAUDE_PROJECT_DIR (nur verfügbar, wenn Claude Code den Hook-Befehl startet) verwenden, um auf Skripte zu verweisen, die in Ihrem Projekt gespeichert sind, um sicherzustellen, dass sie unabhängig vom aktuellen Verzeichnis von Claude funktionieren:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
          }
        ]
      }
    ]
  }
}

Plugin-Hooks

Plugins können Hooks bereitstellen, die sich nahtlos mit Ihren Benutzer- und Projekt-Hooks integrieren. Plugin-Hooks werden automatisch mit Ihrer Konfiguration zusammengeführt, wenn Plugins aktiviert sind. Wie Plugin-Hooks funktionieren:
  • Plugin-Hooks werden in der Datei hooks/hooks.json des Plugins oder in einer Datei definiert, die durch einen benutzerdefinierten Pfad zum Feld hooks angegeben wird.
  • Wenn ein Plugin aktiviert ist, werden seine Hooks mit Benutzer- und Projekt-Hooks zusammengeführt
  • Mehrere Hooks aus verschiedenen Quellen können auf dasselbe Ereignis reagieren
  • Plugin-Hooks verwenden die Umgebungsvariable ${CLAUDE_PLUGIN_ROOT} um auf Plugin-Dateien zu verweisen
Beispiel-Plugin-Hook-Konfiguration:
{
  "description": "Automatische Code-Formatierung",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
Plugin-Hooks verwenden das gleiche Format wie reguläre Hooks mit einem optionalen Feld description zur Erklärung des Zwecks des Hooks.
Plugin-Hooks werden zusammen mit Ihren benutzerdefinierten Hooks ausgeführt. Wenn mehrere Hooks ein Ereignis abgleichen, werden sie alle parallel ausgeführt.
Umgebungsvariablen für Plugins:
  • ${CLAUDE_PLUGIN_ROOT}: Absoluter Pfad zum Plugin-Verzeichnis
  • ${CLAUDE_PROJECT_DIR}: Projektroot-Verzeichnis (gleich wie für Projekt-Hooks)
  • Alle Standard-Umgebungsvariablen sind verfügbar
Weitere Informationen zum Erstellen von Plugin-Hooks finden Sie in der Plugin-Komponenten-Referenz.

Prompt-basierte Hooks

Zusätzlich zu Bash-Befehls-Hooks (type: "command") unterstützt Claude Code prompt-basierte Hooks (type: "prompt"), die ein LLM verwenden, um zu evaluieren, ob eine Aktion erlaubt oder blockiert werden soll. Prompt-basierte Hooks werden derzeit nur für Stop und SubagentStop Hooks unterstützt, wo sie intelligente, kontextabhängige Entscheidungen ermöglichen.

Wie prompt-basierte Hooks funktionieren

Anstatt einen Bash-Befehl auszuführen, prompt-basierte Hooks:
  1. Senden die Hook-Eingabe und Ihren Prompt an ein schnelles LLM (Haiku)
  2. Das LLM antwortet mit strukturiertem JSON, das eine Entscheidung enthält
  3. Claude Code verarbeitet die Entscheidung automatisch

Konfiguration

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluieren Sie, ob Claude stoppen sollte: $ARGUMENTS. Überprüfen Sie, ob alle Aufgaben abgeschlossen sind."
          }
        ]
      }
    ]
  }
}
Felder:
  • type: Muss "prompt" sein
  • prompt: Der Prompt-Text, der an das LLM gesendet wird
    • Verwenden Sie $ARGUMENTS als Platzhalter für die Hook-Eingabe JSON
    • Wenn $ARGUMENTS nicht vorhanden ist, wird die Eingabe JSON an den Prompt angehängt
  • timeout: (Optional) Timeout in Sekunden (Standard: 30 Sekunden)

Antwortschema

Das LLM muss mit JSON antworten, das Folgendes enthält:
{
  "decision": "approve" | "block",
  "reason": "Erklärung für die Entscheidung",
  "continue": false,  // Optional: stoppt Claude vollständig
  "stopReason": "Nachricht für den Benutzer",  // Optional: benutzerdefinierte Stoppnachricht
  "systemMessage": "Warnung oder Kontext"  // Optional: wird dem Benutzer angezeigt
}
Antwortfelder:
  • decision: "approve" erlaubt die Aktion, "block" verhindert sie
  • reason: Erklärung, die Claude angezeigt wird, wenn die Entscheidung "block" ist
  • continue: (Optional) Wenn false, stoppt die Ausführung von Claude vollständig
  • stopReason: (Optional) Nachricht, die angezeigt wird, wenn continue false ist
  • systemMessage: (Optional) Zusätzliche Nachricht, die dem Benutzer angezeigt wird

Unterstützte Hook-Ereignisse

Prompt-basierte Hooks funktionieren mit jedem Hook-Ereignis, sind aber am nützlichsten für:
  • Stop: Intelligente Entscheidung, ob Claude weiterarbeiten sollte
  • SubagentStop: Evaluieren Sie, ob ein Subagent seine Aufgabe abgeschlossen hat
  • UserPromptSubmit: Validieren Sie Benutzer-Prompts mit LLM-Unterstützung
  • PreToolUse: Treffen Sie kontextabhängige Berechtigungsentscheidungen

Beispiel: Intelligenter Stop-Hook

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Sie evaluieren, ob Claude die Arbeit beenden sollte. Kontext: $ARGUMENTS\n\nAnalysieren Sie das Gespräch und bestimmen Sie, ob:\n1. Alle vom Benutzer angeforderten Aufgaben abgeschlossen sind\n2. Fehler behoben werden müssen\n3. Weitere Arbeiten erforderlich sind\n\nAntworten Sie mit JSON: {\"decision\": \"approve\" oder \"block\", \"reason\": \"Ihre Erklärung\"}",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Beispiel: SubagentStop mit benutzerdefinierter Logik

{
  "hooks": {
    "SubagentStop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluieren Sie, ob dieser Subagent stoppen sollte. Eingabe: $ARGUMENTS\n\nÜberprüfen Sie, ob:\n- Der Subagent seine zugewiesene Aufgabe abgeschlossen hat\n- Fehler aufgetreten sind, die behoben werden müssen\n- Zusätzliche Kontexterfassung erforderlich ist\n\nRückgabe: {\"decision\": \"approve\" oder \"block\", \"reason\": \"Erklärung\"}"
          }
        ]
      }
    ]
  }
}

Vergleich mit Bash-Befehls-Hooks

FunktionBash-Befehls-HooksPrompt-basierte Hooks
AusführungFührt Bash-Skript ausFragt LLM ab
EntscheidungslogikSie implementieren im CodeLLM evaluiert Kontext
Setup-KomplexitätErfordert SkriptdateiNur Prompt konfigurieren
KontextbewusstseinBegrenzt auf Skript-LogikNatürlichsprachliches Verständnis
LeistungSchnell (lokale Ausführung)Langsamer (API-Aufruf)
AnwendungsfallDeterministische RegelnKontextabhängige Entscheidungen

Best Practices

  • Seien Sie spezifisch in Prompts: Geben Sie klar an, was das LLM evaluieren soll
  • Entscheidungskriterien einbeziehen: Listen Sie die Faktoren auf, die das LLM berücksichtigen sollte
  • Testen Sie Ihre Prompts: Überprüfen Sie, dass das LLM korrekte Entscheidungen für Ihre Anwendungsfälle trifft
  • Legen Sie angemessene Timeouts fest: Standard ist 30 Sekunden, passen Sie bei Bedarf an
  • Verwenden Sie für komplexe Entscheidungen: Bash-Hooks sind besser für einfache, deterministische Regeln
Weitere Informationen zum Erstellen von Plugin-Hooks finden Sie in der Plugin-Komponenten-Referenz.

Hook-Ereignisse

PreToolUse

Wird ausgeführt, nachdem Claude Tool-Parameter erstellt hat und bevor der Tool-Aufruf verarbeitet wird. Häufige Matcher:
  • Task - Subagent-Aufgaben (siehe Subagents-Dokumentation)
  • Bash - Shell-Befehle
  • Glob - Dateimuster-Abgleich
  • Grep - Inhaltssuche
  • Read - Dateilesevorgänge
  • Edit - Dateibearbeitung
  • Write - Dateischreiben
  • WebFetch, WebSearch - Web-Operationen

PostToolUse

Wird unmittelbar nach erfolgreichem Abschluss eines Tools ausgeführt. Erkennt die gleichen Matcher-Werte wie PreToolUse.

Notification

Wird ausgeführt, wenn Claude Code Benachrichtigungen sendet. Benachrichtigungen werden gesendet, wenn:
  1. Claude Ihre Berechtigung benötigt, um ein Tool zu verwenden. Beispiel: “Claude benötigt Ihre Berechtigung, um Bash zu verwenden”
  2. Die Prompt-Eingabe mindestens 60 Sekunden untätig war. “Claude wartet auf Ihre Eingabe”

UserPromptSubmit

Wird ausgeführt, wenn der Benutzer einen Prompt einreicht, bevor Claude ihn verarbeitet. Dies ermöglicht es Ihnen, zusätzlichen Kontext basierend auf dem Prompt/Gespräch hinzuzufügen, Prompts zu validieren oder bestimmte Arten von Prompts zu blockieren.

Stop

Wird ausgeführt, wenn der Haupt-Claude Code-Agent die Antwort beendet hat. Wird nicht ausgeführt, wenn die Beendigung aufgrund einer Benutzerunterbrechung erfolgt ist.

SubagentStop

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

PreCompact

Wird ausgeführt, bevor Claude Code einen Kompaktierungsvorgang ausführen wird. Matcher:
  • manual - Aufgerufen von /compact
  • auto - Aufgerufen von Auto-Kompaktierung (aufgrund eines vollen Kontextfensters)

SessionStart

Wird ausgeführt, wenn Claude Code eine neue Sitzung startet oder eine bestehende Sitzung fortsetzt (die derzeit unter der Haube eine neue Sitzung startet). Nützlich zum Laden von Entwicklungskontext wie vorhandene Probleme oder kürzliche Änderungen an Ihrer Codebasis, Installation von Abhängigkeiten oder Einrichten von Umgebungsvariablen. Matcher:
  • startup - Aufgerufen beim Startup
  • resume - Aufgerufen von --resume, --continue oder /resume
  • clear - Aufgerufen von /clear
  • compact - Aufgerufen von Auto- oder manueller Kompaktierung.

Persistieren von Umgebungsvariablen

SessionStart-Hooks haben Zugriff auf die Umgebungsvariable CLAUDE_ENV_FILE, die einen Dateipfad bereitstellt, wo Sie Umgebungsvariablen für nachfolgende Bash-Befehle persistieren können. Beispiel: Einzelne Umgebungsvariablen setzen
#!/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
Beispiel: Alle Umgebungsänderungen aus dem Hook persistieren Wenn Ihr Setup die Umgebung ändert (z.B. nvm use), erfassen und persistieren Sie alle Änderungen durch Vergleich der Umgebung:
#!/bin/bash

ENV_BEFORE=$(export -p | sort)

# Führen Sie Ihre Setup-Befehle aus, die die Umgebung ändern
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
Alle Variablen, die in diese Datei geschrieben werden, sind in allen nachfolgenden Bash-Befehlen verfügbar, die Claude Code während der Sitzung ausführt.
CLAUDE_ENV_FILE ist nur für SessionStart-Hooks verfügbar. Andere Hook-Typen haben keinen Zugriff auf diese Variable.

SessionEnd

Wird ausgeführt, wenn eine Claude Code-Sitzung endet. Nützlich für Cleanup-Aufgaben, Protokollierung von Sitzungsstatistiken oder Speicherung des Sitzungszustands. Das Feld reason in der Hook-Eingabe ist eines von:
  • clear - Sitzung mit /clear-Befehl gelöscht
  • logout - Benutzer abgemeldet
  • prompt_input_exit - Benutzer beendet, während die Prompt-Eingabe sichtbar war
  • other - Andere Beendigungsgründe

Hook-Eingabe

Hooks erhalten JSON-Daten über stdin, die Sitzungsinformationen und ereignisspezifische Daten enthalten:
{
  // Gemeinsame Felder
  session_id: string
  transcript_path: string  // Pfad zur Gesprächs-JSON
  cwd: string              // Das aktuelle Arbeitsverzeichnis, wenn der Hook aufgerufen wird
  permission_mode: string  // Aktueller Berechtigungsmodus: "default", "plan", "acceptEdits" oder "bypassPermissions"

  // Ereignisspezifische Felder
  hook_event_name: string
  ...
}

PreToolUse-Eingabe

Das genaue Schema für tool_input hängt vom Tool ab.
{
  "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-Eingabe

Das genaue Schema für tool_input und tool_response hängt vom Tool ab.
{
  "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-Eingabe

{
  "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-Eingabe

{
  "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 und SubagentStop-Eingabe

stop_hook_active ist true, wenn Claude Code bereits als Ergebnis eines Stop-Hooks fortgesetzt wird. Überprüfen Sie diesen Wert oder verarbeiten Sie das Transkript, um zu verhindern, dass Claude Code unbegrenzt ausgeführt wird.
{
  "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-Eingabe

Für manual kommt custom_instructions von dem, was der Benutzer in /compact übergibt. Für auto ist custom_instructions leer.
{
  "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-Eingabe

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

SessionEnd-Eingabe

{
  "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-Ausgabe

Es gibt zwei Möglichkeiten, wie Hooks Ausgaben an Claude Code zurückgeben können. Die Ausgabe kommuniziert, ob blockiert werden soll und welches Feedback Claude und dem Benutzer angezeigt werden soll.

Einfach: Exit-Code

Hooks kommunizieren den Status durch Exit-Codes, stdout und stderr:
  • Exit-Code 0: Erfolg. stdout wird dem Benutzer im Transkriptmodus angezeigt (CTRL-R), außer für UserPromptSubmit und SessionStart, wo stdout zum Kontext hinzugefügt wird.
  • Exit-Code 2: Blockierungsfehler. stderr wird an Claude zurückgesendet, um automatisch verarbeitet zu werden. Siehe verhaltensweisen pro Hook-Ereignis unten.
  • Andere Exit-Codes: Nicht blockierender Fehler. stderr wird dem Benutzer angezeigt und die Ausführung wird fortgesetzt.
Erinnerung: Claude Code sieht stdout nicht, wenn der Exit-Code 0 ist, außer für den UserPromptSubmit-Hook, wo stdout als Kontext eingefügt wird.

Exit-Code 2-Verhalten

Hook-EreignisVerhalten
PreToolUseBlockiert den Tool-Aufruf, zeigt stderr Claude
PostToolUseZeigt stderr Claude (Tool wurde bereits ausgeführt)
NotificationN/A, zeigt stderr nur dem Benutzer
UserPromptSubmitBlockiert die Prompt-Verarbeitung, löscht Prompt, zeigt stderr nur dem Benutzer
StopBlockiert die Beendigung, zeigt stderr Claude
SubagentStopBlockiert die Beendigung, zeigt stderr Claude-Subagent
PreCompactN/A, zeigt stderr nur dem Benutzer
SessionStartN/A, zeigt stderr nur dem Benutzer
SessionEndN/A, zeigt stderr nur dem Benutzer

Erweitert: JSON-Ausgabe

Hooks können strukturiertes JSON in stdout zurückgeben, um eine anspruchsvollere Kontrolle zu ermöglichen:

Gemeinsame JSON-Felder

Alle Hook-Typen können diese optionalen Felder einschließen:
{
  "continue": true, // Ob Claude nach der Hook-Ausführung fortfahren sollte (Standard: true)
  "stopReason": "string", // Nachricht, die angezeigt wird, wenn continue false ist

  "suppressOutput": true, // Verstecken Sie stdout vom Transkriptmodus (Standard: false)
  "systemMessage": "string" // Optionale Warnmeldung für den Benutzer
}
Wenn continue false ist, stoppt Claude die Verarbeitung nach der Hook-Ausführung.
  • Für PreToolUse unterscheidet sich dies von "permissionDecision": "deny", das nur einen bestimmten Tool-Aufruf blockiert und automatisches Feedback an Claude bietet.
  • Für PostToolUse unterscheidet sich dies von "decision": "block", das automatisiertes Feedback an Claude bietet.
  • Für UserPromptSubmit verhindert dies die Verarbeitung des Prompts.
  • Für Stop und SubagentStop hat dies Vorrang vor jedem "decision": "block"-Ausgabe.
  • In allen Fällen hat "continue" = false Vorrang vor jedem "decision": "block"-Ausgabe.
stopReason begleitet continue mit einem Grund, der dem Benutzer angezeigt wird, nicht Claude.

PreToolUse-Entscheidungskontrolle

PreToolUse-Hooks können steuern, ob ein Tool-Aufruf fortgesetzt wird.
  • "allow" umgeht das Berechtigungssystem. permissionDecisionReason wird dem Benutzer angezeigt, aber nicht Claude.
  • "deny" verhindert die Ausführung des Tool-Aufrufs. permissionDecisionReason wird Claude angezeigt.
  • "ask" fragt den Benutzer, um den Tool-Aufruf in der Benutzeroberfläche zu bestätigen. permissionDecisionReason wird dem Benutzer angezeigt, aber nicht Claude.
Zusätzlich können Hooks Tool-Eingaben vor der Ausführung mit updatedInput ändern:
  • updatedInput ermöglicht es Ihnen, die Eingabeparameter des Tools vor der Ausführung zu ändern. Dies ist ein Record<string, unknown>-Objekt, das die Felder enthält, die Sie ändern oder hinzufügen möchten.
  • Dies ist am nützlichsten mit "permissionDecision": "allow" um Tool-Aufrufe zu ändern und zu genehmigen.
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow"
    "permissionDecisionReason": "My reason here",
    "updatedInput": {
      "field_to_modify": "new value"
    }
  }
}
Die Felder decision und reason sind für PreToolUse-Hooks veraltet. Verwenden Sie stattdessen hookSpecificOutput.permissionDecision und hookSpecificOutput.permissionDecisionReason. Die veralteten Felder "approve" und "block" werden auf "allow" und "deny" abgebildet.

PostToolUse-Entscheidungskontrolle

PostToolUse-Hooks können Feedback an Claude nach der Tool-Ausführung geben.
  • "block" fordert Claude automatisch mit reason auf.
  • undefined macht nichts. reason wird ignoriert.
  • "hookSpecificOutput.additionalContext" fügt Kontext für Claude hinzu, um zu berücksichtigen.
{
  "decision": "block" | undefined,
  "reason": "Erklärung für die Entscheidung",
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "Zusätzliche Informationen für Claude"
  }
}

UserPromptSubmit-Entscheidungskontrolle

UserPromptSubmit-Hooks können steuern, ob ein Benutzer-Prompt verarbeitet wird.
  • "block" verhindert die Verarbeitung des Prompts. Der eingereichte Prompt wird aus dem Kontext gelöscht. "reason" wird dem Benutzer angezeigt, aber nicht zum Kontext hinzugefügt.
  • undefined erlaubt dem Prompt, normal fortzufahren. "reason" wird ignoriert.
  • "hookSpecificOutput.additionalContext" fügt die Zeichenkette zum Kontext hinzu, wenn nicht blockiert.
{
  "decision": "block" | undefined,
  "reason": "Erklärung für die Entscheidung",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "Mein zusätzlicher Kontext hier"
  }
}

Stop/SubagentStop-Entscheidungskontrolle

Stop und SubagentStop-Hooks können steuern, ob Claude fortfahren muss.
  • "block" verhindert, dass Claude stoppt. Sie müssen reason ausfüllen, damit Claude weiß, wie vorzugehen ist.
  • undefined erlaubt Claude zu stoppen. reason wird ignoriert.
{
  "decision": "block" | undefined,
  "reason": "Muss bereitgestellt werden, wenn Claude am Stoppen gehindert wird"
}

SessionStart-Entscheidungskontrolle

SessionStart-Hooks ermöglichen es Ihnen, Kontext beim Start einer Sitzung zu laden.
  • "hookSpecificOutput.additionalContext" fügt die Zeichenkette zum Kontext hinzu.
  • Mehrere Hooks’ additionalContext-Werte werden verkettet.
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Mein zusätzlicher Kontext hier"
  }
}

SessionEnd-Entscheidungskontrolle

SessionEnd-Hooks werden ausgeführt, wenn eine Sitzung endet. Sie können die Sitzungsbeendigung nicht blockieren, können aber Cleanup-Aufgaben ausführen.

Exit-Code-Beispiel: Bash-Befehls-Validierung

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

# Definieren Sie Validierungsregeln als Liste von (Regex-Muster, Nachricht) Tupeln
VALIDATION_RULES = [
    (
        r"\bgrep\b(?!.*\|)",
        "Verwenden Sie 'rg' (ripgrep) statt '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' statt '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"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)

# Validieren Sie 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 Claude
    sys.exit(2)

JSON-Ausgabe-Beispiel: UserPromptSubmit zum Hinzufügen von Kontext und Validierung

Für UserPromptSubmit-Hooks können Sie Kontext mit einer der beiden Methoden injizieren:
  • Exit-Code 0 mit stdout: Claude sieht den Kontext (Spezialfall für UserPromptSubmit)
  • JSON-Ausgabe: Bietet mehr Kontrolle über das Verhalten
#!/usr/bin/env python3
import json
import sys
import re
import datetime

# Laden Sie die Eingabe von 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", "")

# Überprüfen Sie auf sensible Muster
sensitive_patterns = [
    (r"(?i)\b(password|secret|key|token)\s*[:=]", "Prompt enthält potenzielle Geheimnisse"),
]

for pattern, message in sensitive_patterns:
    if re.search(pattern, prompt):
        # Verwenden Sie JSON-Ausgabe zum Blockieren mit einem bestimmten Grund
        output = {
            "decision": "block",
            "reason": f"Sicherheitsrichtlinienverletzung: {message}. Bitte formulieren Sie Ihre Anfrage ohne sensible Informationen um."
        }
        print(json.dumps(output))
        sys.exit(0)

# Fügen Sie die aktuelle Zeit zum Kontext hinzu
context = f"Current time: {datetime.datetime.now()}"
print(context)

"""
Das Folgende ist auch gleichwertig:
print(json.dumps({
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": context,
  },
}))
"""

# Erlauben Sie dem Prompt, mit dem zusätzlichen Kontext fortzufahren
sys.exit(0)

JSON-Ausgabe-Beispiel: PreToolUse mit Genehmigung

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

# Laden Sie die Eingabe von 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", {})

# Beispiel: Auto-Genehmigung von Dateilesevorgängen für Dokumentationsdateien
if tool_name == "Read":
    file_path = tool_input.get("file_path", "")
    if file_path.endswith((".md", ".mdx", ".txt", ".json")):
        # Verwenden Sie JSON-Ausgabe zum Auto-Genehmigen des Tool-Aufrufs
        output = {
            "decision": "approve",
            "reason": "Dokumentationsdatei auto-genehmigt",
            "suppressOutput": True  # Nicht im Transkriptmodus anzeigen
        }
        print(json.dumps(output))
        sys.exit(0)

# Für andere Fälle lassen Sie den normalen Berechtigungsfluss fortfahren
sys.exit(0)

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 Namensmuster, 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

Konfigurieren von Hooks für MCP-Tools

Sie können spezifische MCP-Tools oder ganze MCP-Server als Ziel festlegen:
{
  "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

Praktische Beispiele einschließlich Code-Formatierung, Benachrichtigungen und Dateischutz finden Sie unter Weitere Beispiele im Leitfaden für erste Schritte.

Sicherheitsüberlegungen

Haftungsausschluss

VERWENDUNG AUF EIGENES RISIKO: Claude Code Hooks führen automatisch beliebige Shell-Befehle auf Ihrem System aus. Durch die Verwendung von Hooks bestätigen Sie, dass:
  • Sie allein verantwortlich für die Befehle sind, die Sie konfigurieren
  • Hooks können alle Dateien ändern, löschen oder auf die Ihr Benutzerkonto zugreifen kann
  • Böswillige oder schlecht geschriebene Hooks können Datenverlust oder Systemschäden verursachen
  • Anthropic bietet keine Garantie und übernimmt keine Haftung für Schäden die sich aus der Verwendung von Hooks ergeben
  • Sie sollten Hooks in einer sicheren Umgebung gründlich testen, 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 zum Schreiben sichererer Hooks:
  1. Validieren und bereinigen Sie Eingaben - Vertrauen Sie Eingabedaten nie blind
  2. Zitieren Sie immer Shell-Variablen - Verwenden Sie "$VAR" nicht $VAR
  3. Blockieren Sie Pfad-Traversal - Überprüfen Sie auf .. in Dateipfaden
  4. Verwenden Sie absolute Pfade - Geben Sie vollständige Pfade für Skripte an (verwenden Sie “$CLAUDE_PROJECT_DIR” für den Projektpfad)
  5. Überspringen Sie sensible Dateien - Vermeiden Sie .env, .git/, Schlüssel, etc.

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 Überprüfung im /hooks-Menü, damit Änderungen wirksam werden
Dies verhindert, dass böswillige Hook-Änderungen Ihre aktuelle Sitzung beeinflussen.

Hook-Ausführungsdetails

  • Timeout: 60-Sekunden-Ausführungslimit standardmäßig, konfigurierbar pro Befehl.
    • Ein Timeout für einen einzelnen Befehl beeinflusst nicht die anderen Befehle.
  • Parallelisierung: Alle übereinstimmenden Hooks werden parallel ausgeführt
  • Deduplizierung: Mehrere identische Hook-Befehle werden automatisch dedupliziert
  • Umgebung: Wird im aktuellen Verzeichnis mit Claude Codes Umgebung ausgeführt
    • Die Umgebungsvariable CLAUDE_PROJECT_DIR ist verfügbar und enthält den absoluten Pfad zum Projekt-Root-Verzeichnis (wo Claude Code gestartet wurde)
    • Die Umgebungsvariable CLAUDE_CODE_REMOTE gibt an, ob der Hook in einer Remote- (Web-) Umgebung ("true") oder lokalen CLI-Umgebung (nicht gesetzt oder leer) ausgeführt wird. Verwenden Sie dies, um verschiedene Logik basierend auf dem Ausführungskontext auszuführen.
  • Eingabe: JSON über stdin
  • Ausgabe:
    • PreToolUse/PostToolUse/Stop/SubagentStop: Fortschritt im Transkript angezeigt (Ctrl-R)
    • Notification/SessionEnd: Nur in Debug protokolliert (--debug)
    • UserPromptSubmit/SessionStart: stdout als Kontext für Claude hinzugefügt

Debugging

Grundlegende Fehlerbehebung

Wenn Ihre Hooks nicht funktionieren:
  1. Überprüfen Sie die Konfiguration - Führen Sie /hooks aus, um zu sehen, ob Ihr Hook registriert ist
  2. Überprüfen Sie die Syntax - Stellen Sie sicher, dass Ihre JSON-Einstellungen gültig sind
  3. Testen Sie Befehle - Führen Sie Hook-Befehle zuerst manuell aus
  4. Überprüfen Sie Berechtigungen - Stellen Sie sicher, dass Skripte ausführbar sind
  5. Überprüfen Sie Protokolle - Verwenden Sie claude --debug, um Hook-Ausführungsdetails zu sehen
Häufige Probleme:
  • Nicht entgangene Anführungszeichen - Verwenden Sie \" in JSON-Strings
  • Falscher Matcher - Überprüfen Sie, dass Toolnamen genau übereinstimmen (Groß-/Kleinschreibung beachtet)
  • Befehl nicht gefunden - Verwenden Sie vollständige Pfade für Skripte

Erweitertes Debugging

Für komplexe Hook-Probleme:
  1. Inspizieren Sie die Hook-Ausführung - Verwenden Sie claude --debug, um detaillierte Hook- Ausführung zu sehen
  2. Validieren Sie JSON-Schemas - Testen Sie Hook-Eingabe/Ausgabe mit externen Tools
  3. Überprüfen Sie Umgebungsvariablen - Überprüfen Sie, dass Claude Codes Umgebung korrekt ist
  4. Testen Sie Grenzfälle - Versuchen Sie Hooks mit ungewöhnlichen Dateipfaden oder Eingaben
  5. Überwachen Sie Systemressourcen - Überprüfen Sie auf Ressourcenerschöpfung während der Hook- Ausführung
  6. Verwenden Sie strukturiertes Logging - Implementieren Sie Logging in Ihren Hook-Skripten

Debug-Ausgabe-Beispiel

Verwenden Sie claude --debug, um Hook-Ausführungsdetails zu sehen:
[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>
Fortschrittsmeldungen erscheinen im Transkriptmodus (Ctrl-R) und zeigen:
  • Welcher Hook ausgeführt wird
  • Befehl wird ausgeführt
  • Erfolgs-/Fehlerstatus
  • Ausgabe- oder Fehlermeldungen