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 einen leeren String ("") verwenden oder matcher leer lassen.
  • 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 (kann die Umgebungsvariable $CLAUDE_PROJECT_DIR verwenden)
    • timeout: (Optional) Wie lange ein Befehl ausgeführt werden soll, in Sekunden, bevor dieser spezifische Befehl 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 in Ihre 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 description-Feld, um den Zweck des Hooks zu erklären.
Plugin-Hooks werden zusammen mit Ihren benutzerdefinierten Hooks ausgeführt. Wenn mehrere Hooks auf ein Ereignis passen, 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.

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-Matching
  • 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 zur Verwendung eines Tools benötigt. Beispiel: “Claude benötigt Ihre Berechtigung zur Verwendung von Bash”
  2. Die Eingabeaufforderung mindestens 60 Sekunden lang untätig war. “Claude wartet auf Ihre Eingabe”

UserPromptSubmit

Wird ausgeführt, wenn der Benutzer eine Eingabeaufforderung sendet, bevor Claude diese verarbeitet. Dies ermöglicht es Ihnen, zusätzlichen Kontext basierend auf der Eingabeaufforderung/dem Gespräch hinzuzufügen, Eingabeaufforderungen zu validieren oder bestimmte Arten von Eingabeaufforderungen 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 erfolgte.

SubagentStop

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

PreCompact

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

SessionStart

Wird ausgeführt, wenn Claude Code eine neue Sitzung startet oder eine vorhandene 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 Einrichtung von Umgebungsvariablen. Matcher:
  • startup - Aufgerufen beim Starten
  • resume - Aufgerufen von --resume, --continue oder /resume
  • clear - Aufgerufen von /clear
  • compact - Aufgerufen von Auto- oder manuellem Compact.

Persistieren von Umgebungsvariablen

SessionStart-Hooks haben Zugriff auf die Umgebungsvariable CLAUDE_ENV_FILE, die einen Dateipfad bereitstellt, in dem Sie Umgebungsvariablen für nachfolgende Bash-Befehle persistieren können. Beispiel: Festlegen einzelner Umgebungsvariablen
#!/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: Persistieren aller Umgebungsänderungen aus dem Hook 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 Sitzungsstatus. Das Feld reason in der Hook-Eingabe ist eines der folgenden:
  • clear - Sitzung mit dem Befehl /clear gelöscht
  • logout - Benutzer hat sich abgemeldet
  • prompt_input_exit - Benutzer hat beendet, während die Eingabeaufforderung 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 für Hooks, Ausgaben an Claude Code zurückzugeben. Die Ausgabe teilt mit, ob blockiert werden soll und welches Feedback Claude und dem Benutzer angezeigt werden soll.

Einfach: Exit-Code

Hooks teilen den Status über Exit-Codes, stdout und stderr mit:
  • Exit-Code 0: Erfolg. stdout wird dem Benutzer im Transkriptmodus angezeigt (STRG+R), außer für UserPromptSubmit und SessionStart, wobei stdout zum Kontext hinzugefügt wird.
  • Exit-Code 2: Blockierender Fehler. stderr wird an Claude zurückgegeben, um automatisch verarbeitet zu werden. Siehe das Verhalten 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, bei dem stdout als Kontext eingefügt wird.

Exit-Code-2-Verhalten

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

Erweitert: JSON-Ausgabe

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

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 aus dem Transkriptmodus ausblenden (Standard: false)
  "systemMessage": "string" // Optionale Warnmeldung, die dem Benutzer angezeigt wird
}
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 der Eingabeaufforderung.
  • 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 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" fordert den Benutzer auf, den Tool-Aufruf in der Benutzeroberfläche zu bestätigen. permissionDecisionReason wird dem Benutzer angezeigt, aber nicht Claude.
Darüber hinaus 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" bzw. "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 tut nichts. reason wird ignoriert.
  • "hookSpecificOutput.additionalContext" fügt Kontext hinzu, den Claude berücksichtigen soll.
{
  "decision": "block" | undefined,
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "Additional information for Claude"
  }
}

UserPromptSubmit-Entscheidungskontrolle

UserPromptSubmit-Hooks können steuern, ob eine Benutzereingabeaufforderung verarbeitet wird.
  • "block" verhindert die Verarbeitung der Eingabeaufforderung. Die eingereichte Eingabeaufforderung wird aus dem Kontext gelöscht. "reason" wird dem Benutzer angezeigt, aber nicht zum Kontext hinzugefügt.
  • undefined ermöglicht der Eingabeaufforderung, normal fortzufahren. "reason" wird ignoriert.
  • "hookSpecificOutput.additionalContext" fügt den String zum Kontext hinzu, wenn nicht blockiert.
{
  "decision": "block" | undefined,
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "My additional context here"
  }
}

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 es fortfahren soll.
  • undefined ermöglicht Claude zu stoppen. reason wird ignoriert.
{
  "decision": "block" | undefined,
  "reason": "Must be provided when Claude is blocked from stopping"
}

SessionStart-Entscheidungskontrolle

SessionStart-Hooks ermöglichen es Ihnen, Kontext zu Beginn einer Sitzung zu laden.
  • "hookSpecificOutput.additionalContext" fügt den String zum Kontext hinzu.
  • Mehrere additionalContext-Werte von Hooks werden verkettet.
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "My additional context here"
  }
}

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-Befehl-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(?!.*\|)",
        "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)

# 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 an
    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 contains potential secrets"),
]

for pattern, message in sensitive_patterns:
    if re.search(pattern, prompt):
        # Verwenden Sie JSON-Ausgabe, um mit einem bestimmten Grund zu blockieren
        output = {
            "decision": "block",
            "reason": f"Security policy violation: {message}. Please rephrase your request without sensitive information."
        }
        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,
  },
}))
"""

# Ermöglichen Sie der Eingabeaufforderung, 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: Automatische 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, um den Tool-Aufruf automatisch zu genehmigen
        output = {
            "decision": "approve",
            "reason": "Documentation file auto-approved",
            "suppressOutput": True  # Nicht im Transkriptmodus anzeigen
        }
        print(json.dumps(output))
        sys.exit(0)

# Für andere Fälle den normalen Berechtigungsfluss fortfahren lassen
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-Tool zum Erstellen von Entitäten
  • mcp__filesystem__read_file - Filesystem-Server-Tool zum Lesen von Dateien
  • mcp__github__search_repositories - GitHub-Server-Suchtool

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 den Einstieg.

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 von Ihnen konfigurierten Befehle sind
  • Hooks alle Dateien ändern, löschen oder darauf zugreifen können, auf die Ihr Benutzerkonto zugreifen kann
  • Bösartige oder schlecht geschriebene Hooks können zu Datenverlust oder Systemschäden führen
  • 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.

Best Practices für Sicherheit

Hier sind einige wichtige Praktiken zum Schreiben sicherer Hooks:
  1. Validieren und bereinigen Sie Eingaben - Vertrauen Sie Eingabedaten nie blind
  2. Zitieren Sie Shell-Variablen immer - Verwenden Sie "$VAR" nicht $VAR
  3. Blockieren Sie Pfadtraversal - Ü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 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 Menü /hooks, damit Änderungen wirksam werden
Dies verhindert, dass bösartige 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 beeinträchtigt 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 der Umgebung von Claude Code ausgeführt
    • Die Umgebungsvariable CLAUDE_PROJECT_DIR ist verfügbar und enthält den absoluten Pfad zum Projektroot-Verzeichnis (wo Claude Code gestartet wurde)
    • Die Umgebungsvariable CLAUDE_CODE_REMOTE gibt an, ob der Hook in einer Remote- (Web-) Umgebung ("true") oder einer lokalen CLI-Umgebung (nicht gesetzt oder leer) ausgeführt wird. Verwenden Sie dies, um unterschiedliche Logik basierend auf dem Ausführungskontext auszuführen.
  • Eingabe: JSON über stdin
  • Ausgabe:
    • PreToolUse/PostToolUse/Stop/SubagentStop: Fortschritt im Transkript angezeigt (Strg+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 anzuzeigen
Häufige Probleme:
  • Nicht entgangene Anführungszeichen - Verwenden Sie \" in JSON-Strings
  • Falscher Matcher - Überprüfen Sie, ob 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. Überprüfen Sie die Hook-Ausführung - Verwenden Sie claude --debug, um detaillierte Hook- Ausführung anzuzeigen
  2. Validieren Sie JSON-Schemas - Testen Sie Hook-Eingabe/Ausgabe mit externen Tools
  3. Überprüfen Sie Umgebungsvariablen - Überprüfen Sie, ob die Umgebung von Claude Code 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 Protokollierung in Ihren Hook-Skripten

Debug-Ausgabe-Beispiel

Verwenden Sie claude --debug, um Hook-Ausführungsdetails anzuzeigen:
[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 (Strg+R) und zeigen:
  • Welcher Hook ausgeführt wird
  • Befehl wird ausgeführt
  • Erfolgs-/Fehlerstatus
  • Ausgabe- oder Fehlermeldungen