SpyBara
Go Premium

hooks-guide.md 2026-10-27 22:59 UTC to 2026-10-28 23:57 UTC

This page contains 74 additions and 74 deletions.

2026
Thu 1 23:59 Fri 2 22:59 Sat 3 23:57 Mon 5 23:58 Wed 7 23:59 Fri 9 23:02 Sat 10 23:01 Sat 17 23:57 Mon 19 23:58 Tue 20 23:00 Wed 21 23:02 Thu 22 22:58 Fri 23 22:59 Sun 25 23:58 Mon 26 22:57 Wed 28 23:57 Fri 30 23:01

Automatisieren Sie Aktionen mit Hooks

Führen Sie Shell-Befehle automatisch aus, wenn Claude Code Dateien bearbeitet, Aufgaben abschließt oder Eingaben benötigt. Formatieren Sie Code, senden Sie Benachrichtigungen, validieren Sie Befehle und erzwingen Sie Projektregeln.

Hooks sind benutzerdefinierte Shell-Befehle. Claude Code führt sie an bestimmten Punkten in seinem Lebenszyklus aus, was Ihnen deterministische Kontrolle gibt: Bestimmte Aktionen finden immer statt, anstatt sich darauf zu verlassen, dass das LLM sich dafür entscheidet, sie auszuführen. Verwenden Sie Hooks, um Projektregeln durchzusetzen, sich wiederholende Aufgaben zu automatisieren und Claude Code mit Ihren vorhandenen Tools zu integrieren.

Für Entscheidungen, die Urteilsvermögen erfordern, anstatt deterministischer Regeln, können Sie auch Prompt-basierte Hooks oder Agent-basierte Hooks verwenden, die ein Claude-Modell zur Bewertung von Bedingungen nutzen.

Für andere Möglichkeiten, Claude Code zu erweitern, siehe skills zum Bereitstellen zusätzlicher Anweisungen und ausführbarer Befehle, subagents zum Ausführen von Aufgaben in isolierten Kontexten und plugins zum Verpacken von Erweiterungen, die über Projekte hinweg freigegeben werden können.

[!TIP]

Dieser Leitfaden behandelt häufige Anwendungsfälle und wie Sie anfangen. Für vollständige Event-Schemas, JSON-Ein-/Ausgabeformate und erweiterte Funktionen wie asynchrone Hooks und MCP-Tool-Hooks siehe die Hooks-Referenz.

Richten Sie Ihren ersten Hook ein

Um einen Hook zu erstellen, fügen Sie einen hooks-Block zu einer Einstellungsdatei hinzu. Diese Anleitung erstellt einen Desktop-Benachrichtigungs-Hook, damit Sie benachrichtigt werden, wenn Claude auf Ihre Eingabe wartet, anstatt das Terminal zu beobachten.

1. Fügen Sie den Hook zu Ihren Einstellungen hinzu

Öffnen Sie ~/.claude/settings.json und fügen Sie einen Notification-Hook hinzu. Wenn die Datei nicht vorhanden ist, erstellen Sie sie. Das Beispiel unten verwendet osascript für macOS; siehe Benachrichtigung erhalten, wenn Claude Eingaben benötigt für Linux- und Windows-Befehle.

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Wenn Ihre Einstellungsdatei bereits einen hooks-Schlüssel hat, fügen Sie Notification als Geschwister der vorhandenen Event-Schlüssel hinzu, anstatt das ganze Objekt zu ersetzen. Jeder Event-Name ist ein Schlüssel innerhalb des einzelnen hooks-Objekts:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]
      }
    ],
    "Notification": [
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" }]
      }
    ]
  }
}

Sie können auch Claude bitten, den Hook für Sie zu schreiben, indem Sie beschreiben, was Sie in der CLI möchten.

2. Überprüfen Sie die Konfiguration

Geben Sie /hooks in der Eingabeaufforderung von Claude Code ein, um den Hooks-Browser zu öffnen. Ihr neuer Hook erscheint in der Liste unter Notification.

3. Testen Sie den Hook

Drücken Sie Esc, um zur CLI zurückzukehren. Drücken Sie Shift+Tab, bis die Statusleiste ⏸ manual mode on anzeigt, bitten Sie Claude, etwas zu tun, das eine Berechtigung erfordert, und wechseln Sie dann weg vom Terminal. Sie sollten eine Desktop-Benachrichtigung erhalten.

Was Sie automatisieren können

Mit Hooks können Sie an wichtigen Punkten im Lebenszyklus von Claude Code Code ausführen: Dateien nach Bearbeitungen formatieren, Befehle vor ihrer Ausführung blockieren, Benachrichtigungen senden, wenn Claude eine Eingabe benötigt, Kontext beim Sitzungsstart einfügen und mehr. Die vollständige Liste der Hook-Events finden Sie in der Hooks-Referenz.

Jedes Beispiel enthält einen sofort einsetzbaren Konfigurationsblock, den Sie zu einer Einstellungsdatei hinzufügen.

Ein Produktionsbeispiel für Hooks, die eine separate Modellprüfung ausführen und die Ergebnisse in die Sitzung zurückspielen, finden Sie unter Wie sich das Plugin security-guidance in Claude Code integriert.

Benachrichtigung erhalten, wenn Claude eine Eingabe benötigt

Erhalten Sie eine Desktop-Benachrichtigung, sobald Claude die Arbeit beendet hat und Ihre Eingabe benötigt, damit Sie sich anderen Aufgaben widmen können, ohne das Terminal im Auge behalten zu müssen.

Dieser Hook verwendet das Event Notification, das Claude Code auslöst, wenn Claude auf eine Eingabe oder eine Berechtigung wartet. Den genauen Zeitpunkt finden Sie unter Wann jeder Benachrichtigungstyp ausgelöst wird.

Jeder der folgenden Tabs verwendet den nativen Benachrichtigungsbefehl der jeweiligen Plattform. Fügen Sie Folgendes zu ~/.claude/settings.json hinzu:

macOS

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Wenn keine Benachrichtigung erscheint

osascript leitet Benachrichtigungen über die integrierte App Skripteditor weiter. Wenn der Skripteditor keine Berechtigung für Benachrichtigungen hat, schlägt der Befehl stillschweigend fehl, und macOS fordert Sie nicht auf, diese Berechtigung zu erteilen.

Führen Sie dies einmal im Terminal aus, damit der Skripteditor in Ihren Benachrichtigungseinstellungen erscheint:

osascript -e 'display notification "test"'

Es wird noch nichts angezeigt. Öffnen Sie Systemeinstellungen > Mitteilungen, suchen Sie Skripteditor in der Liste und aktivieren Sie Mitteilungen erlauben. Führen Sie den Befehl erneut aus, um zu bestätigen, dass die Testbenachrichtigung erscheint.

Linux

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
          }
        ]
      }
    ]
  }
}

Wenn keine Benachrichtigung erscheint

notify-send benötigt einen Desktop-Benachrichtigungsdaemon, den Headless-Server, SSH-Sitzungen und die meisten Container nicht haben. Testen Sie den Befehl zuerst direkt:

notify-send 'Claude Code' 'test'

Wenn der Befehl nicht gefunden wird, installieren Sie unter Debian und Ubuntu das Paket libnotify-bin oder das Äquivalent Ihrer Distribution.

Windows (PowerShell)

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
          }
        ]
      }
    ]
  }
}

Wenn kein Dialog erscheint

Dieser Befehl öffnet ein Dialogfeld statt einer Benachrichtigung in der Ecke Ihres Bildschirms, sodass sich der Dialog hinter Ihrem Terminalfenster öffnen kann. Testen Sie den Befehl zuerst direkt in PowerShell.

Wenn Sie Claude Code in WSL ausführen, muss powershell.exe über die Windows-Interoperabilität in Ihrem PATH verfügbar sein.

Der leere matcher wird bei allen Benachrichtigungstypen ausgelöst. Um nur bei bestimmten Events auszulösen, setzen Sie ihn auf einen dieser Werte:

Matcher Wird ausgelöst, wenn
permission_prompt Claude Ihre Genehmigung für eine Tool-Nutzung oder die Netzwerkanfrage eines Befehls in der Sandbox benötigt und die Abfrage etwa sechs Sekunden gewartet hat
idle_prompt Claude vor etwa 60 Sekunden mit der Antwort fertig war und Sie seitdem nichts eingegeben haben
auth_success Die Authentifizierung abgeschlossen ist
elicitation_dialog Ein MCP-Server ein Elicitation-Formular öffnet und Sie etwa sechs Sekunden lang nichts eingegeben haben
elicitation_url_dialog Ein MCP-Server Sie auffordert, eine URL im Browser zu öffnen, und Sie etwa sechs Sekunden lang nichts eingegeben haben
elicitation_complete Ein MCP-Server meldet, dass eine Elicitation im URL-Modus abgeschlossen ist
elicitation_response Eine MCP-Elicitation-Antwort an den Server zurückgesendet wird
agent_needs_input Eine Hintergrundsitzung beginnt, auf Ihre Eingabe zu warten, während die Agentenansicht geöffnet ist. Wird auch ausgelöst, wenn eine Terminalsitzung Ihnen die Frage eines Agent-Team-Mitglieds zur Terminal-Einrichtung oder den Hinweis des Auto-Modus zu Gebühren für Klassifikator-Anfragen anzeigt und Sie etwa sechs Sekunden lang nichts eingegeben haben
agent_completed Eine Hintergrundsitzung abgeschlossen wird oder fehlschlägt. Wird nur ausgelöst, während die Agentenansicht geöffnet ist
quota_auto_resume_fired Claude Code Ihre Aufgabe fortsetzt, nachdem ein claude.ai-Nutzungslimit sie pausiert hat: beim Zurücksetzen oder früher, wenn etwas, das Sie während der Wartezeit in Claude Code tun, etwa Nutzungsguthaben hinzufügen, Ihren Plan upgraden oder das Modell wechseln, die Nutzung wieder verfügbar macht, mit der Ausnahme für die Modelleinstellung
quota_auto_resume_stale Ein claude.ai-Nutzungslimit zurückgesetzt wurde, während Ihr Computer länger als etwa 30 Minuten im Ruhezustand war. Claude Code wartet, bis Sie Enter drücken, statt fortzufahren. Nach einem kürzeren Ruhezustand fährt es fort und löst stattdessen quota_auto_resume_fired aus
quota_auto_resume_disabled Claude Code das Warten auf ein claude.ai-Nutzungslimit beendet, ohne Ihre Aufgabe fortzusetzen: autoContinueAtUsageLimit wurde ausgeschaltet oder das Zurücksetzen hat sich während einer Wartezeit, die Claude Code selbst gestartet hat, um mehr als 24 Stunden verschoben, die fortgesetzte Aufgabe stieß wiederholt an das Limit, oder die Fortsetzung wurde blockiert, bevor sie das Modell erreichte. Wird nicht ausgelöst, wenn Sie Esc oder Ctrl+C drücken oder Don't continue automatically auswählen
plugin_notification Ein Mod mit $.ui.notify eine Benachrichtigung auslöst. Der title des Hooks ist der Name des Mods, sofern der Mod keinen festgelegt hat

Claude Code legt den Zeitpunkt von permission_prompt in einem Terminal anders fest als in Claude Desktop, der VS Code-Erweiterung und anderen Hosts, die Berechtigungsanfragen über das Agent SDK beantworten. Beide Zeitpunkte finden Sie unter Wann jeder Benachrichtigungstyp ausgelöst wird.

Die Matcher quota_auto_resume_fired, quota_auto_resume_stale und quota_auto_resume_disabled erfordern Claude Code v2.1.234 oder höher.

In Terminalsitzungen erfordert permission_prompt für die Netzwerkanfrage eines Befehls in der Sandbox Claude Code v2.1.246 oder höher.

agent_needs_input für die Frage eines Teammitglieds zur Terminal-Einrichtung erfordert Claude Code v2.1.248 oder höher.

Geben Sie /hooks am Claude Code-Prompt ein und prüfen Sie, ob der Hook unter Notification erscheint.

Code nach Bearbeitungen automatisch formatieren

Führen Sie Prettier automatisch für jede Datei aus, die Claude bearbeitet, damit die Formatierung ohne manuelles Eingreifen einheitlich bleibt.

Dieser Hook verwendet das Event PostToolUse mit einem Edit|Write-Matcher, sodass er nur nach Tools zur Dateibearbeitung ausgeführt wird. Der Befehl extrahiert den Pfad der bearbeiteten Datei mit jq und übergibt ihn an Prettier. Fügen Sie Folgendes zu .claude/settings.json im Stammverzeichnis Ihres Projekts hinzu:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

Um den Hook zu testen, bitten Sie Claude, einer JavaScript-Datei eine Zeile mit Strings in einfachen Anführungszeichen hinzuzufügen, und öffnen Sie dann die Datei: Mit den Standardeinstellungen von Prettier schreibt der Hook sie in doppelte Anführungszeichen um.

Wenn der Hook erfolgreich ist, zeigt Claude Code in der Konversation nichts an. Um zu bestätigen, dass der Hook ausgeführt wurde, prüfen Sie, ob die bearbeitete Datei neu formatiert wurde, oder lesen Sie Prüfen, was ein Hook getan hat.

Um eine bestimmte Datei unabhängig davon neu zu formatieren, wie sie sich ändert, auch wenn ein Bash-Befehl sie umschreibt, verwenden Sie stattdessen einen FileChanged-Hook.

[!NOTE]

Die Bash-Beispiele auf dieser Seite verwenden jq zum Parsen von JSON. Installieren Sie es unter macOS mit brew install jq, unter Debian und Ubuntu mit apt-get install jq, oder siehe jq-Downloads.

Bearbeitungen an geschützten Dateien blockieren

Verhindern Sie, dass Claude sensible Dateien wie .env, package-lock.json oder alles in .git/ ändert. Claude erhält Feedback, das erklärt, warum die Bearbeitung blockiert wurde, sodass es seine Vorgehensweise anpassen kann.

Dieses Beispiel verwendet eine separate Skriptdatei, die der Hook aufruft. Das Skript prüft den Zieldateipfad anhand einer Liste geschützter Muster und beendet sich mit Exit-Code 2, um die Bearbeitung zu blockieren.

1. Hook-Skript erstellen

Speichern Sie dies unter .claude/hooks/protect-files.sh:

#!/bin/bash
# protect-files.sh

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# Normalize Windows backslash separators so the patterns below match
FILE_PATH="${FILE_PATH//\\//}"

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
    exit 2
  fi
done

exit 0

2. Skript unter macOS und Linux ausführbar machen

Hook-Skripte müssen ausführbar sein, damit Claude Code sie ausführen kann:

chmod +x .claude/hooks/protect-files.sh

3. Hook registrieren

Fügen Sie .claude/settings.json einen PreToolUse-Hook hinzu, der das Skript vor jedem Edit- oder Write-Tool-Aufruf ausführt:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

4. Hook testen

Bitten Sie Claude, Ihrer .env-Datei einen Kommentar hinzuzufügen. Claude Code blockiert die Bearbeitung, bevor sie ausgeführt wird, und übergibt die Blocked:-Meldung des Skripts als Feedback an Claude.

Kontext nach der Komprimierung erneut einfügen

Wenn sich das Kontextfenster von Claude füllt, fasst die Komprimierung die Konversation zusammen, um Platz zu schaffen. Dabei können wichtige Details verloren gehen. Verwenden Sie einen SessionStart-Hook mit einem compact-Matcher, um nach jeder Komprimierung wichtigen Kontext erneut einzufügen.

Claude Code fügt einfachen Text, den Ihr Befehl auf stdout schreibt, dem Kontext von Claude hinzu. Dieses Beispiel erinnert Claude an Projektkonventionen und die jüngste Arbeit. Fügen Sie Folgendes zu .claude/settings.json im Stammverzeichnis Ihres Projekts hinzu:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
          }
        ]
      }
    ]
  }
}

Sie können echo durch einen beliebigen Befehl ersetzen, der dynamische Ausgabe erzeugt, etwa git log --oneline -5, um die letzten Commits anzuzeigen. Um Kontext bei jedem Sitzungsstart einzufügen, sollten Sie stattdessen CLAUDE.md verwenden. Informationen zu Umgebungsvariablen finden Sie unter CLAUDE_ENV_FILE in der Referenz.

Konfigurationsänderungen prüfen

Verfolgen Sie, wann sich Einstellungs- oder Skill-Dateien während einer Sitzung ändern. Das Event ConfigChange wird ausgelöst, wenn ein externer Prozess oder Editor eine Konfigurationsdatei ändert, sodass Sie Änderungen für Compliance-Zwecke protokollieren oder nicht autorisierte Änderungen blockieren können.

Dieses Beispiel hängt jede Änderung an ein Audit-Log an. Fügen Sie Folgendes zu ~/.claude/settings.json hinzu:

{
  "hooks": {
    "ConfigChange": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
          }
        ]
      }
    ]
  }
}

Der Matcher filtert nach Konfigurationstyp: user_settings, project_settings, local_settings, policy_settings oder skills. Um zu verhindern, dass eine Änderung wirksam wird, beenden Sie mit Exit-Code 2 oder geben Sie {"decision": "block"} zurück. Das vollständige Eingabeschema finden Sie in der ConfigChange-Referenz.

Um zu bestätigen, dass der Hook Änderungen aufzeichnet, bearbeiten Sie eine Einstellungsdatei in einem anderen Editor, während eine Sitzung läuft, und öffnen Sie dann ~/claude-config-audit.log: Der Hook hängt pro Änderung eine JSON-Zeile mit Zeitstempel, Quelle und Dateipfad an.

Umgebung neu laden, wenn sich Verzeichnis oder Dateien ändern

Manche Projekte setzen je nach Verzeichnis, in dem Sie sich befinden, unterschiedliche Umgebungsvariablen. Tools wie direnv erledigen das in Ihrer Shell automatisch, aber das Bash-Tool von Claude übernimmt diese Änderungen nicht von selbst.

Die Kombination eines SessionStart-Hooks mit einem CwdChanged-Hook löst dieses Problem. SessionStart lädt die Variablen für das Verzeichnis, in dem Sie starten, und CwdChanged lädt sie jedes Mal neu, wenn Claude das Verzeichnis wechselt. Beide schreiben in CLAUDE_ENV_FILE, das Claude Code vor jedem Bash-Befehl als Skript-Präambel ausführt. Fügen Sie Folgendes zu ~/.claude/settings.json hinzu:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ],
    "CwdChanged": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ]
  }
}

Führen Sie direnv allow einmal in jedem Verzeichnis aus, das eine .envrc enthält, damit direnv sie laden darf. Wenn Sie devbox oder nix statt direnv verwenden, funktioniert dasselbe Muster mit devbox shellenv oder devbox global shellenv anstelle von direnv export bash.

Um auf bestimmte Dateien statt auf jeden Verzeichniswechsel zu reagieren, verwenden Sie FileChanged mit einem matcher, der die zu überwachenden Dateinamen durch | getrennt auflistet. Beim Erstellen der Überwachungsliste teilt Claude Code diesen Wert in literale Dateinamen auf, statt ihn als Regex auszuwerten. Unter FileChanged erfahren Sie, wie derselbe Wert auch filtert, welche Hook-Gruppen bei einer Dateiänderung ausgeführt werden. Dieses Beispiel überwacht .envrc und .env im Arbeitsverzeichnis:

{
  "hooks": {
    "FileChanged": [
      {
        "matcher": ".envrc|.env",
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ]
  }
}

Eingabeschemas, die watchPaths-Ausgabe und Details zu CLAUDE_ENV_FILE finden Sie in den Referenzeinträgen zu CwdChanged und FileChanged.

Bestimmte Berechtigungsabfragen automatisch genehmigen

Überspringen Sie den Genehmigungsdialog für Tool-Aufrufe, die Sie immer erlauben. Dieses Beispiel genehmigt automatisch ExitPlanMode, das Tool, das Claude aufruft, wenn es die Präsentation eines Plans abgeschlossen hat und fragt, ob es fortfahren soll, sodass Sie nicht jedes Mal gefragt werden, wenn ein Plan fertig ist.

Anders als bei den obigen Exit-Code-Beispielen muss Ihr Hook für die automatische Genehmigung eine JSON-Entscheidung auf stdout schreiben. Claude Code führt PermissionRequest-Hooks aus, wenn es Sie gleich um eine Berechtigung bitten würde, und wenn Ihr Hook "behavior": "allow" zurückgibt, beantwortet Claude Code die Anfrage in Ihrem Namen.

Der Matcher beschränkt den Hook ausschließlich auf ExitPlanMode, sodass keine anderen Abfragen betroffen sind. Fügen Sie Folgendes zu ~/.claude/settings.json hinzu:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "ExitPlanMode",
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
          }
        ]
      }
    ]
  }
}

Wenn der Hook genehmigt, verlässt Claude Code den Plan-Modus und stellt den Berechtigungsmodus wieder her, der aktiv war, bevor Sie den Plan-Modus aufgerufen haben. Das Transkript zeigt „Allowed by PermissionRequest hook“ an der Stelle, an der der Dialog erschienen wäre. Über den Hook wird immer die aktuelle Konversation beibehalten: Er kann den Kontext nicht löschen und keine neue Implementierungssitzung starten, wie es der Dialog kann.

Um stattdessen einen bestimmten Berechtigungsmodus festzulegen, kann die Ausgabe Ihres Hooks ein updatedPermissions-Array mit einem setMode-Eintrag enthalten. Der Wert mode ist ein beliebiger Berechtigungsmodus wie default, acceptEdits oder bypassPermissions, und destination: "session" wendet ihn nur für die aktuelle Sitzung an.

[!NOTE]

bypassPermissions gilt nur, wenn Sie die Sitzung mit bereits verfügbarem Bypass-Modus gestartet haben: --dangerously-skip-permissions, --permission-mode bypassPermissions, --allow-dangerously-skip-permissions oder permissions.defaultMode: "bypassPermissions" in Benutzer-, --settings- oder verwalteten Einstellungen. Es gilt nicht, wenn der Bypass-Modus durch permissions.disableBypassPermissionsMode deaktiviert ist oder wenn Sie die Sitzung im eingeschränkten Modus gestartet haben.

Claude Code speichert ihn nie als defaultMode.

Um die Sitzung auf acceptEdits umzuschalten, schreibt Ihr Hook dieses JSON auf stdout:

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "updatedPermissions": [
        { "type": "setMode", "mode": "acceptEdits", "destination": "session" }
      ]
    }
  }
}

Halten Sie den Matcher so eng wie möglich. Ein Matching auf .* oder ein leerer Matcher würde jede Berechtigungsabfrage für Tools automatisch genehmigen, einschließlich Dateischreibvorgängen und Shell-Befehlen. Den vollständigen Satz an Entscheidungsfeldern finden Sie in der PermissionRequest-Referenz.

Wie Hooks funktionieren

Claude Code löst Hook-Events an bestimmten Lebenszykluspunkten aus. Wenn ein Event ausgelöst wird, führt Claude Code alle übereinstimmenden Hooks parallel aus; siehe Hook-Handler-Felder für die Behandlung doppelter Handler. Die folgende Tabelle zeigt jedes Event und wann es ausgelöst wird:

Ereignis Wann es ausgelöst wird
SessionStart Wenn eine Sitzung beginnt oder fortgesetzt wird
Setup Wenn Sie Claude Code mit --init-only starten oder mit --init oder --maintenance im -p-Modus. Für einmalige Vorbereitung in CI oder Skripten
UserPromptSubmit Wenn ein Prompt abgesendet wird, bevor Claude ihn verarbeitet. Wird auch bei Turns ausgelöst, die Claude Code selbst startet
UserPromptExpansion Wenn ein von Ihnen eingegebener Befehl in eine Eingabeaufforderung erweitert wird, bevor sie Claude erreicht. Kann die Erweiterung blockieren
PreToolUse Bevor ein Werkzeugaufruf ausgeführt wird. Kann ihn blockieren
PermissionRequest Wenn ein Werkzeugaufruf eine Genehmigungsentscheidung benötigt
PermissionDenied Wenn der automatische Modus einen Werkzeugaufruf ablehnt, einschließlich Ablehnungen ohne Klassifizierer-Urteil. Verwenden Sie JSON hookSpecificOutput.retry: true, um dem Modell mitzuteilen, dass es den abgelehnten Werkzeugaufruf möglicherweise erneut versuchen kann. Claude Code ignoriert retry, wenn der Klassifizierer kein Urteil gefällt hat
PostToolUse Nach erfolgreichem Werkzeugaufruf
PostToolUseFailure Nach fehlgeschlagenem Werkzeugaufruf
PostToolBatch Nach Auflösung eines vollständigen Satzes paralleler Werkzeugaufrufe, bevor der nächste Modellaufruf erfolgt
Notification Wenn Claude Code eine Benachrichtigung sendet
MessageDisplay Während der Text der Assistentnachricht angezeigt wird
SubagentStart Wenn ein Subagent erzeugt wird
SubagentStop Wenn ein Subagent beendet wird
TaskCreated Wenn eine Aufgabe über TaskCreate erstellt wird
TaskCompleted Wenn eine Aufgabe als abgeschlossen markiert wird
Stop Wenn Claude die Antwort beendet
StopFailure Wenn die Runde aufgrund eines API-Fehlers endet
TeammateIdle Wenn ein Agent-Team-Teamkollege im Begriff ist, untätig zu werden
InstructionsLoaded Wenn eine CLAUDE.md- oder .claude/rules/*.md-Datei in den Kontext geladen wird. Wird beim Sitzungsstart und beim verzögerten Laden von Dateien während einer Sitzung ausgelöst
ConfigChange Wenn sich eine Konfigurationsdatei während einer Sitzung ändert
CwdChanged Wenn sich das Arbeitsverzeichnis ändert, z. B. wenn Claude einen cd-Befehl ausführt. Nützlich für reaktive Umgebungsverwaltung mit Tools wie direnv
DirectoryAdded Wenn ein Arbeitsverzeichnis während einer Sitzung über /add-dir oder die SDK-Steueranforderung register_repo_root hinzugefügt wird
FileChanged Wenn sich eine überwachte Datei auf der Festplatte ändert. Das Feld matcher gibt an, welche Dateinamen überwacht werden sollen
WorktreeCreate Wenn ein Worktree über --worktree, isolation: "worktree" oder für eine Hintergrundsitzung erstellt wird. Ersetzt das Standard-Git-Verhalten
WorktreeRemove Wenn ein Worktree, den ein WorktreeCreate-Hook erstellt hat, entfernt wird
PreCompact Vor Kontextkomprimierung
PostCompact Nach Abschluss der Kontextkomprimierung
PreModelSwitch Bevor Claude Code einen Modellwechsel anwendet, den Sie oder ein Client angefordert haben. Kann den Wechsel blockieren
PostModelSwitch Nach Änderung des Modells der Sitzung, einschließlich Änderungen, die Claude Code selbst vornimmt, z. B. Wiederherstellung des Modells beim Fortsetzen einer Sitzung
Elicitation Wenn ein MCP-Server während eines Werkzeugaufrufs Benutzereingaben anfordert
ElicitationResult Nachdem ein Benutzer auf eine MCP-Abfrage antwortet, bevor die Antwort an den Server zurückgesendet wird
SessionEnd Wenn eine Sitzung beendet wird

Jeder Hook hat einen type, der bestimmt, wie er ausgeführt wird. Die meisten Hooks verwenden "type": "command", was einen Shell-Befehl ausführt. Vier weitere Typen sind verfügbar:

  • "type": "http": Event-Daten an eine URL POSTen. Siehe HTTP-Hooks.
  • "type": "mcp_tool": ein Tool auf einem bereits verbundenen MCP-Server aufrufen. Siehe MCP-Tool-Hooks.
  • "type": "prompt": Single-Turn-LLM-Bewertung. Siehe Prompt-basierte Hooks.
  • "type": "agent": Multi-Turn-Verifizierung mit Tool-Zugriff. Agent-Hooks sind experimentell und können sich ändern. Siehe Agent-basierte Hooks.

Ergebnisse aus mehreren Hooks kombinieren

Wenn mehrere Hooks das gleiche Event abgleichen, wird jeder Hook-Befehl bis zur Fertigstellung ausgeführt, bevor Claude Code die Ergebnisse zusammenführt. Ein Hook, der deny zurückgibt, stoppt nicht die Ausführung von Sibling-Hooks. Verlassen Sie sich nicht darauf, dass ein Hook's deny Nebenwirkungen in einem anderen Hook unterdrückt.

Nachdem alle übereinstimmenden Hooks fertig sind, kombiniert Claude Code ihre Ausgaben. Für PreToolUse-Berechtigungsentscheidungen gewinnt die restriktivste Antwort in der Reihenfolge deny, defer, ask, allow. Text aus additionalContext wird von jedem Hook beibehalten und zusammen an Claude übergeben.

Das folgende Beispiel registriert zwei PreToolUse-Hooks auf Bash. Der erste hängt jeden Befehl an eine Protokolldatei an und beendet sich mit 0. Der zweite führt ein Skript aus, das mit 2 beendet wird, um zu verweigern, wenn der Befehl rm -rf enthält:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r .tool_input.command >> ~/.claude/bash.log"
          },
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm-rf.sh"
          }
        ]
      }
    ]
  }
}

Wenn Claude versucht, rm -rf /tmp/build auszuführen, werden beide Hooks parallel ausgeführt. Der Logging-Hook schreibt den Befehl in ~/.claude/bash.log und beendet sich mit 0, was keine Entscheidung meldet. Der Guardrail-Hook beendet sich mit 2, was den Tool-Aufruf verweigert. Die Verweigerung gewinnt, sodass Claude Code den Befehl blockiert und Claude das Guardrail's stderr zeigt. Der Log-Eintrag wird trotzdem geschrieben, weil der Logging-Hook bereits ausgeführt wurde.

Eingabe lesen und Ausgabe zurückgeben

Hooks kommunizieren mit Claude Code über stdin, stdout, stderr und Exit-Codes. Wenn ein Event ausgelöst wird, übergibt Claude Code Event-spezifische Daten als JSON an stdin Ihres Skripts. Ihr Skript liest diese Daten, führt seine Arbeit aus und teilt Claude Code mit, was als nächstes zu tun ist, über den Exit-Code.

Hook-Eingabe

Jedes Event enthält gemeinsame Felder wie session_id, eine eindeutige ID für die Sitzung, und cwd, das Arbeitsverzeichnis, wenn das Event ausgelöst wurde, aber jeder Event-Typ fügt unterschiedliche Daten hinzu. Wenn Claude einen Bash-Befehl ausführt, erhält ein PreToolUse-Hook diese Felder auf stdin:

  • hook_event_name: das Event, das den Hook ausgelöst hat
  • tool_name: das Tool, das Claude verwenden wird
  • tool_input: die Argumente, die Claude an das Tool übergeben hat. Für Bash enthält sein command-Feld den Shell-Befehl.

Beispielsweise sieht die Hook-Eingabe für einen npm test-Befehl so aus:

{
  "session_id": "abc123",
  "cwd": "/Users/sarah/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

Ihr Skript kann dieses JSON parsen und auf alle diese Felder reagieren. UserPromptSubmit-Hooks erhalten stattdessen den prompt-Text, SessionStart-Hooks erhalten eine source von startup, resume, clear, compact oder fork, und so weiter. Siehe Gemeinsame Eingabefelder in der Referenz für gemeinsame Felder und jeden Event-Abschnitt für Event-spezifische Schemas.

Hook-Ausgabe

Ihr Skript teilt Claude Code mit, was als nächstes zu tun ist, indem es auf stdout oder stderr schreibt und mit einem bestimmten Code beendet wird. Beispielsweise ein PreToolUse-Hook, der einen Befehl blockieren möchte:

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q "drop table"; then
  echo "Blocked: dropping tables is not allowed" >&2  # stderr wird zu Claudes Feedback
  exit 2 # exit 2 = Aktion blockieren
fi

exit 0  # exit 0 = keine Entscheidung; der normale Berechtigungsfluss gilt

Bei einem anderen Exit-Code als 0 und 2 und ohne gültige JSON-Ausgabe wird die Aktion bei den meisten Events fortgesetzt, es sei denn, es handelt sich um einen Hook, dessen Fehlschlagen die Aktion blockiert. Ein Hook, bei dem onFailure auf "block" gesetzt ist, ist ein Beispiel dafür. Beenden Sie mit 0, um keinen Einwand zu melden, oder mit 2, um die Aktion zu blockieren:

  • Exit 0: Wenn Sie einen PreToolUse-Hook mit 0 beenden, durchläuft der Tool-Aufruf weiterhin den normalen Berechtigungsfluss, da exit 0 ihn nicht genehmigt. Für UserPromptSubmit-, UserPromptExpansion-, SessionStart- und PostModelSwitch-Hooks fügt Claude Code stdout, das es als Klartext behandelt, zu Claudes Kontext hinzu.
  • Exit 2: Schreiben Sie einen Grund auf stderr. Je nach Event erhält Claude ihn als Feedback, damit es sich anpassen kann, der Benutzer sieht ihn, oder es erscheint keine Meldung, wie bei ConfigChange und Elicitation. Einige Events können nicht blockiert werden: Für SessionStart und andere zeigt exit 2 stderr dem Benutzer an und die Ausführung wird fortgesetzt. Siehe Exit-Code-2-Verhalten pro Event für die vollständige Liste.
  • Jeder andere Exit-Code: Die Pro-Event-Ausnahmen, etwa dass WorktreeCreate bei jedem Exit-Code ungleich null fehlschlägt, finden Sie unter Exit-Code-Ausgabe. Bei anderen Events finden Sie Ihren Fall anhand dessen, was Ihr Hook auf stdout ausgegeben hat, sofern es sich nicht um einen Hook handelt, dessen Fehlschlagen die Aktion blockiert:
    • Ein geparstes Objekt, das die Schemavalidierung besteht: Claude Code ignoriert den Exit-Code, nur das JSON entscheidet das Ergebnis, und der Hook wird nicht als Fehler gemeldet.
    • Ein geparstes Objekt, das die Schemavalidierung nicht besteht, oder stdout, das Claude Code als JSON zu parsen versucht, das aber kein gültiges JSON ist: Die Aktion wird als nicht blockierender Fehler fortgesetzt. Prüfen Sie die Meldung <hook name> hook error auf die Validierungs- oder Parse-Meldung.
    • Stdout, das Claude Code als Klartext behandelt, oder leeres stdout: Die Aktion wird als nicht blockierender Fehler fortgesetzt. Das Transkript zeigt eine <hook name> hook error-Meldung, dann die erste Zeile von stderr mit dem Präfix Failed with non-blocking status code:. Um das vollständige stderr zu erfassen, aktivieren Sie Debug-Logging mit claude --debug oder durch Ausführung von /debug während der Sitzung.

Strukturierte JSON-Ausgabe

Exit-Codes geben Ihnen nur die Möglichkeit, zu blockieren oder zu schweigen. Für mehr Kontrolle beenden Sie mit 0 und geben stattdessen ein JSON-Objekt auf stdout aus.

[!NOTE]

Verwenden Sie exit 2, um mit einer stderr-Meldung zu blockieren, oder exit 0 mit JSON für strukturierte Kontrolle. Wählen Sie einen Ansatz pro Hook. Für das, was passiert, wenn Sie sie mischen, siehe Exit-Code-Ausgabe.

Beispielsweise kann ein PreToolUse-Hook einen Tool-Aufruf ablehnen und Claude mitteilen, warum, oder ihn dem Benutzer zur Genehmigung eskalieren:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Use rg instead of grep for better performance"
  }
}

Mit "deny" bricht Claude Code den Tool-Aufruf ab und gibt permissionDecisionReason an Claude als Feedback zurück.

Bei PreToolUse können Sie auch "ask" zurückgeben, um dem Benutzer die normale Berechtigungsabfrage anzuzeigen, oder "allow", um die interaktive Berechtigungsabfrage zu überspringen. Bei "allow" gelten deny- und ask-Regeln, einschließlich unternehmensweit verwalteter Deny-Listen, weiterhin, ebenso wie Abfragen für:

Ein vierter Wert, "defer", ist im nicht interaktiven Modus mit dem Flag -p verfügbar. Wird er zurückgegeben, endet der Turn mit dem beibehaltenen Tool-Aufruf, sodass ein Agent SDK-Wrapper Eingaben sammeln und fortfahren kann. Siehe Einen Tool-Aufruf für später aufschieben in der Referenz.

Ein PreModelSwitch-Hook gibt das gleiche permissionDecision-Feld zurück: "allow" lässt einen Modellwechsel fortfahren, und "deny" bricht ihn ab. "ask" lässt Sie den Wechsel bestätigen, wenn Sie /model in einer interaktiven Sitzung ausführen; überall sonst behandelt Claude Code "ask" als Verweigerung. Siehe PreModelSwitch-Entscheidungskontrolle.

Andere Events verwenden unterschiedliche Entscheidungsmuster. Beispielsweise verwenden PostToolUse- und Stop-Hooks ein Top-Level-Feld decision: "block", während PermissionRequest hookSpecificOutput.decision.behavior verwendet. Siehe die Zusammenfassungstabelle in der Referenz für eine vollständige Aufschlüsselung nach Event.

Für UserPromptSubmit-Hooks verwenden Sie hookSpecificOutput.additionalContext stattdessen, um Text in Claudes Kontext zu injizieren. Verschachteln Sie additionalContext in hookSpecificOutput; wenn Sie es auf der obersten Ebene des JSON platzieren, ignoriert Claude Code es stillschweigend. Beispielsweise fügt diese Ausgabe den aktuellen Branch-Status zu jedem Prompt hinzu:

{
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "Current branch: release-42. Deploy freeze until Friday."
  }
}

Siehe UserPromptSubmit-Entscheidungskontrolle für die vollständige Ausgabeform, einschließlich Blockierung von Prompts und Festlegung des Sitzungstitels.

Hooks mit type: "prompt" handhaben die Ausgabe anders: siehe Prompt-basierte Hooks.

Hooks mit Matchern filtern

Ohne einen Matcher wird ein Hook bei jedem Auftreten seines Events ausgelöst. Matcher ermöglichen es Ihnen, das einzugrenzen. Wenn Sie beispielsweise einen Formatter nur nach Datei-Bearbeitungen ausführen möchten (nicht nach jedem Tool-Aufruf), fügen Sie einen Matcher zu Ihrem PostToolUse-Hook hinzu:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "prettier --write ..." }
        ]
      }
    ]
  }
}

Der "Edit|Write"-Matcher wird ausgelöst, wenn Claude das Edit- oder Write-Tool verwendet, nicht wenn es Bash, Read oder ein anderes Tool verwendet. Ein Komma trennt Alternativen auf die gleiche Weise, sodass "Edit, Write" gleichwertig ist. Siehe Matcher-Muster für die Auswertung von einfachen Namen und regulären Ausdrücken.

[!NOTE]

Claude kann auch Dateien erstellen oder ändern, indem er Shell-Befehle ausführt. Wenn Ihr Hook jede Dateiänderung sehen muss, z. B. für Compliance-Scanning oder Audit-Protokollierung, fügen Sie einen Stop-Hook hinzu, der den Arbeitsbaum einmal pro Runde scannt. Für Pro-Aufruf-Abdeckung stattdessen auch Bash|PowerShell abgleichen und Ihr Skript geänderte und nicht verfolgte Dateien mit git status --porcelain auflisten. Der Abschnitt PowerShell-Hook-Eingabe erklärt, warum das Abgleichen von nur Bash nicht ausreicht. Um einen Hook auszuführen, wenn sich eine bestimmte Datei auf der Festplatte ändert, unabhängig davon, wer sie geschrieben hat, verwenden Sie einen FileChanged-Hook.

Jeder Event-Typ gleicht ein bestimmtes Feld ab:

Event Worauf der Matcher filtert Beispiel-Matcher-Werte
PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied Tool-Name Bash, Edit|Write, mcp__.*
SessionStart wie die Sitzung gestartet wurde startup, resume, clear, compact, fork
Setup welches CLI-Flag das Setup ausgelöst hat init, maintenance
SessionEnd warum die Sitzung endete clear, resume, logout, prompt_input_exit, other
Notification Benachrichtigungstyp permission_prompt, idle_prompt, auth_success, elicitation_dialog, elicitation_url_dialog, elicitation_complete, elicitation_response, agent_needs_input, agent_completed, quota_auto_resume_fired, quota_auto_resume_stale, quota_auto_resume_disabled, plugin_notification
SubagentStart Agent-Typ general-purpose, Explore, Plan oder benutzerdefinierte Agent-Namen
PreCompact, PostCompact was die Komprimierung ausgelöst hat manual, auto
PreModelSwitch, PostModelSwitch kanonischer Name des Modells, zu dem die Sitzung wechselt, wie unter PreModelSwitch beschrieben claude-opus-5, claude-opus-4-6|claude-opus-5, .*opus.*
SubagentStop Agent-Typ gleiche Werte wie SubagentStart
ConfigChange Konfigurationsquelle user_settings, project_settings, local_settings, policy_settings, skills
DirectoryAdded wie das Verzeichnis hinzugefügt wurde slash_command, register_repo_root
StopFailure Fehlertyp rate_limit, overloaded, authentication_failed, oauth_org_not_allowed, account_on_hold, billing_error, invalid_request, model_not_found, server_error, max_output_tokens, cloud_credential_error, unknown
InstructionsLoaded Ladegrund session_start, nested_traversal, path_glob_match, include, compact
Elicitation MCP-Servername Ihre konfigurierten MCP-Servernamen
ElicitationResult MCP-Servername gleiche Werte wie Elicitation
FileChanged Dateinamen zum Überwachen (siehe FileChanged) .envrc|.env
UserPromptExpansion Befehlsname Ihre Skill- oder Befehlsnamen
UserPromptSubmit, PostToolBatch, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, CwdChanged, MessageDisplay keine Matcher-Unterstützung wird immer bei jedem Auftreten ausgelöst

Die Registerkarten unten zeigen ein paar weitere Matcher auf verschiedene Event-Typen.

Jeden Bash-Befehl protokollieren

Gleichen Sie nur Bash-Tool-Aufrufe ab und protokollieren Sie jeden Befehl in einer Datei. Das PostToolUse-Event wird ausgelöst, nachdem der Befehl abgeschlossen ist, sodass tool_input.command enthält, was ausgeführt wurde. Der Hook erhält die Event-Daten als JSON auf stdin, und jq -r '.tool_input.command' extrahiert nur die Befehlszeichenfolge, die >> an die Protokolldatei anhängt:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
          }
        ]
      }
    ]
  }
}

MCP-Tools abgleichen

MCP-Tools verwenden eine andere Namenskonvention als integrierte Tools: mcp__<server>__<tool>, wobei <server> der MCP-Servername und <tool> das Tool ist, das er bereitstellt. Beispielsweise mcp__github__search_repositories oder mcp__filesystem__read_file. Tools von einem Plugin-gebündelten Server verwenden stattdessen ein Scoped-Server-Segment, z. B. mcp__plugin_my-plugin_db__query. Verwenden Sie einen Regex-Matcher, um alle Tools von einem bestimmten Server zu erfassen, oder gleichen Sie Server übergreifend mit einem Muster wie mcp__.*__write.* ab. Siehe MCP-Tools abgleichen in der Referenz für die vollständige Liste der Beispiele.

Der folgende Befehl extrahiert den Tool-Namen aus der Hook-JSON-Eingabe mit jq und schreibt ihn auf stderr. Das Schreiben auf stderr hält stdout sauber für JSON-Ausgabe und sendet die Meldung in das Debug-Protokoll:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__github__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"GitHub tool called: $(jq -r '.tool_name')\" >&2"
          }
        ]
      }
    ]
  }
}

Beim Sitzungsende aufräumen

Das SessionEnd-Event unterstützt Matcher auf den Grund, warum die Sitzung endete. Dieser Hook wird nur bei clear ausgelöst (wenn Sie /clear ausführen), nicht bei normalen Exits:

{
  "hooks": {
    "SessionEnd": [
      {
        "matcher": "clear",
        "hooks": [
          {
            "type": "command",
            "command": "rm -f /tmp/claude-scratch-*.txt"
          }
        ]
      }
    ]
  }
}

Hooks mit dem Feld if nach Tool-Name und Argumenten filtern

Das Feld if verwendet Berechtigungsregel-Syntax zum Filtern von Hooks nach Tool-Name und Argumenten zusammen, sodass der Hook-Prozess nur spawnt, wenn der Tool-Aufruf übereinstimmt. Dies geht über matcher hinaus, das auf der Gruppenebene nur nach Tool-Name filtert.

Beispielsweise, um einen Hook nur auszuführen, wenn Claude git-Befehle verwendet, anstatt alle Bash-Befehle:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(git *)",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh"
          }
        ]
      }
    ]
  }
}

Ob Ihr Hook-Befehl ausgeführt wird, hängt von der Form Ihres if-Musters und dem Bash-Befehl ab, den Claude aufruft:

if-Muster Bash-Befehl Hook wird ausgeführt? Warum
Bash(git *) git push ja Befehlsname stimmt überein
Bash(git *) npm test && git push ja jeder Subbefehl wird überprüft; git push stimmt überein
Bash(git *) echo $(git log) ja Befehle in $() und Backticks werden überprüft; git log stimmt überein
Bash(git *) echo $(date) nein kein Subbefehl stimmt mit git * überein
Bash(git push *) echo $(date) ja Muster, die mehr als den Befehlsnamen angeben, führen den Hook trotzdem bei $(), Backticks oder $VAR aus

Wenn Claude Code nicht bestimmen kann, welche Befehle die Bash-Eingabe ausführt, führt es Ihren Hook unabhängig vom Muster aus. Die Bash-Matching-Tabelle behandelt die Befehlsformen, die Claude Code eingrenzen kann und nicht. Da der Filter Best-Effort ist, verwenden Sie das Berechtigungssystem anstelle eines Hooks, um ein hartes Allow oder Deny durchzusetzen.

Das Feld if akzeptiert die gleichen Muster wie Berechtigungsregeln: "Bash(git *)", "Edit(*.ts)" und so weiter. Um mehrere Tool-Namen abzugleichen, verwenden Sie separate Handler, jeder mit seinem eigenen if-Wert, oder gleichen Sie auf der matcher-Ebene ab, wo Pipe-Alternation unterstützt wird.

if funktioniert nur bei Tool-Events: PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest und PermissionDenied. Das Hinzufügen zu einem anderen Event verhindert, dass der Hook ausgeführt wird.

Hook-Speicherort konfigurieren

Wo Sie einen Hook hinzufügen, bestimmt seinen Bereich:

Speicherort Bereich Freigegeben
~/.claude/settings.json Alle Ihre Projekte Nein, lokal auf Ihrem Computer
.claude/settings.json Einzelnes Projekt Ja, kann im Repo committed werden
.claude/settings.local.json Einzelnes Projekt Nein, gitignoriert wenn Claude Code eine Einstellung darin speichert
Verwaltete Richtlinieneinstellungen Organisationsweit Ja, von Admin kontrolliert
Plugin hooks/hooks.json Wenn Plugin aktiviert ist Ja, mit dem Plugin gebündelt
Skill Frontmatter Der Rest der Sitzung, sobald der Skill aufgerufen wird. Siehe Hooks in Skills und Agents Ja, in der Skill-Datei definiert
Subagent Frontmatter Während dieser Subagent läuft Ja, in der Subagent-Datei definiert

Führen Sie /hooks in Claude Code aus, um alle konfigurierten Hooks nach Event gruppiert zu durchsuchen.

Um Hooks zu deaktivieren, setzen Sie "disableAllHooks": true in Ihrer Einstellungsdatei. Claude Code liest den Wert, der nach Einstellungspriorität angewendet wird, sodass die Einstellungsdatei eines Projekts Ihre überschreiben kann. Hooks, die in verwalteten Einstellungen konfiguriert sind, werden weiterhin ausgeführt, es sei denn, disableAllHooks ist auch dort gesetzt. Für die vollständige Reichweite jeder Ebene siehe disableAllHooks.

Wenn Sie Einstellungsdateien direkt bearbeiten, während Claude Code läuft, werden Hook-Änderungen normalerweise automatisch vom Datei-Watcher aufgegriffen.

Prompt-basierte Hooks

Für Entscheidungen, die Urteilsvermögen erfordern, anstatt deterministischer Regeln, verwenden Sie type: "prompt"-Hooks. Anstatt einen Shell-Befehl auszuführen, sendet Claude Code Ihren Prompt und die Hook-Eingabedaten an ein Claude-Modell, um die Entscheidung zu treffen. Sie können ein anderes Modell mit dem Feld model angeben, wenn Sie mehr Leistung benötigen.

Die einzige Aufgabe des Modells ist, seine Entscheidung als JSON zurückzugeben:

  • "ok": true: die Aktion wird fortgesetzt
  • "ok": false: was passiert, hängt vom Ereignis ab:
    • Stop und SubagentStop: der reason wird an Claude zurückgegeben, sodass es weiterarbeitet, es sei denn, die Antwort setzt auch "impossible": true, um die Bedingung als eine zu kennzeichnen, die niemals erfüllt werden kann. In diesem Fall erlaubt Claude Code den Stop und der Turn endet
    • PreToolUse: der Tool-Aufruf wird verweigert; standardmäßig endet der Turn und der Ablehnungs-reason erscheint im Chat als Warnzeile. Setzen Sie continueOnBlock: true auf dem Hook, um stattdessen den reason an Claude als Tool-Fehler zurückzugeben, sodass es sich anpassen und fortfahren kann
    • PostToolUse: standardmäßig endet der Turn und der reason erscheint im Chat als Warnzeile. Setzen Sie continueOnBlock: true, um den reason an Claude zurückzugeben und den Turn stattdessen fortzusetzen
    • PostToolBatch, UserPromptSubmit und UserPromptExpansion: der Turn endet und der reason erscheint im Chat als Warnzeile

Dieses Beispiel verwendet einen Stop-Hook, um das Modell zu fragen, ob alle angeforderten Aufgaben abgeschlossen sind. Wenn das Modell "ok": false zurückgibt, weil die Bedingung noch nicht erfüllt ist, arbeitet Claude weiter und verwendet den reason als nächste Anweisung:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}."
          }
        ]
      }
    ]
  }
}

Für vollständige Konfigurationsoptionen siehe Prompt-basierte Hooks in der Referenz.

Agent-basierte Hooks

[!WARNING]

Agent-Hooks sind experimentell. Verhalten und Konfiguration können sich in zukünftigen Versionen ändern. Für Produktions-Workflows bevorzugen Sie Command-Hooks.

Wenn die Verifizierung das Inspizieren von Dateien oder das Ausführen von Befehlen erfordert, verwenden Sie type: "agent"-Hooks. Im Gegensatz zu Prompt-Hooks, die einen einzelnen LLM-Aufruf tätigen, spawnen Agent-Hooks einen Subagent, der Dateien lesen, Code durchsuchen und andere Tools verwenden kann, um Bedingungen zu überprüfen, bevor eine Entscheidung zurückgegeben wird.

Agent-Hooks verwenden das "ok" / "reason"-Antwortformat mit einem längeren Standard-Timeout von 60 Sekunden und bis zu 50 Tool-Use-Turns. Sie unterstützen nicht das impossible-Feld von Prompt-Hooks. Bei ok: false behandelt Claude Code einen Agent-Hook auf die gleiche Weise wie einen Prompt-Hook mit continueOnBlock: true beim gleichen Event, sodass bei PreToolUse und PostToolUse der Turn fortgesetzt wird; Agent-Hooks haben kein continueOnBlock-Feld. Siehe Agent-Hook-Konfiguration für die Felder, einschließlich des $ARGUMENTS-Platzhalters, den Claude Code durch die JSON-Eingabe des Hooks ersetzt.

Dieses Beispiel überprüft, dass Tests bestanden werden, bevor Claude beendet werden darf:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS",
            "timeout": 120
          }
        ]
      }
    ]
  }
}

Verwenden Sie Prompt-Hooks, wenn die Hook-Eingabedaten allein ausreichen, um eine Entscheidung zu treffen. Verwenden Sie Agent-Hooks, wenn Sie etwas gegen den tatsächlichen Zustand der Codebasis überprüfen müssen.

Für vollständige Konfigurationsoptionen siehe Agent-basierte Hooks in der Referenz.

HTTP-Hooks

Verwenden Sie type: "http"-Hooks, um Event-Daten an einen HTTP-Endpunkt zu POSTen, anstatt einen Shell-Befehl auszuführen. Der Endpunkt erhält die gleichen JSON-Daten, die ein Command-Hook auf stdin erhalten würde, und gibt Ergebnisse über den HTTP-Antwortkörper mit dem gleichen JSON-Format zurück.

HTTP-Hooks sind nützlich, wenn Sie möchten, dass ein Webserver, eine Cloud-Funktion oder ein externer Service Hook-Logik handhabt: beispielsweise ein gemeinsamer Audit-Service, der Tool-Use-Events über ein Team hinweg protokolliert.

Dieses Beispiel POSTet jeden Tool-Use an einen lokalen Logging-Service:

{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "http",
            "url": "http://localhost:8080/hooks/tool-use",
            "headers": {
              "Authorization": "Bearer $MY_TOKEN"
            },
            "allowedEnvVars": ["MY_TOKEN"]
          }
        ]
      }
    ]
  }
}

Ihr Endpunkt antwortet mit einem JSON-Body im gleichen Ausgabeformat wie Command-Hooks, und Claude Code prüft außerdem den Antwortstatus:

  • 2xx-Status: Um einen Tool-Aufruf zu blockieren, geben Sie die entsprechenden hookSpecificOutput-Felder im Body zurück.
  • Jeder andere Status oder eine fehlgeschlagene Anfrage: Claude Code meldet einen nicht blockierenden Fehler und lässt die Aktion fortfahren. Damit ein fehlgeschlagener Endpunkt die Aktion blockiert, setzen Sie onFailure: "block" für den Hook.

Header-Werte unterstützen Umgebungsvariablen-Interpolation mit $VAR_NAME oder ${VAR_NAME}-Syntax. Nur Variablen, die im Array allowedEnvVars aufgelistet sind, werden aufgelöst; alle anderen $VAR-Referenzen bleiben leer.

Für vollständige Konfigurationsoptionen und Response-Handling siehe HTTP-Hooks in der Referenz.

Einschränkungen und Fehlerbehebung

Einschränkungen

Beachten Sie diese Einschränkungen beim Entwerfen von Hooks:

  • Command Hooks kommunizieren nur über stdout, stderr und Exit-Codes. Sie können keine /-Befehle oder Tool-Aufrufe auslösen. Text, der über additionalContext zurückgegeben wird, wird als Systemhinweis eingefügt, den Claude als Klartext liest. HTTP Hooks kommunizieren stattdessen über den Response-Body.
  • Hook-Timeouts variieren je nach Typ. Überschreiben Sie pro Hook mit dem Feld timeout in Sekunden.
    • command, http, mcp_tool: 10 Minuten. Claude Code senkt diesen Standard auf 30 Sekunden für UserPromptSubmit-, PreModelSwitch- und PostModelSwitch-Hooks und auf 10 Sekunden für MessageDisplay-Hooks.
    • prompt: 30 Sekunden.
    • agent: 60 Sekunden.
    • SessionEnd-Hooks aller Typen teilen sich ein Budget von 1,5 Sekunden. Wenn Ihre Einstellungen ein längeres timeout pro Hook setzen, erhöht Claude Code das Budget entsprechend, bis zu 60 Sekunden.
  • PostToolUse-Hooks können Aktionen nicht rückgängig machen, da das Tool bereits ausgeführt wurde.
  • PermissionRequest-Hooks werden ausgelöst, wenn Claude Code Sie um Erlaubnis fragen möchte oder wenn es einen Aufruf, für den keine Abfrage angezeigt werden kann, andernfalls automatisch ablehnen würde. Im nicht interaktiven Modus mit dem Flag -p werden sie außerhalb des dontAsk-Modus weiterhin ausgeführt, und ein Aufruf, über den kein Hook entscheidet und den nichts anderes beantworten kann, wird abgelehnt.
  • Stop-Hooks werden ausgelöst, wenn Claude die Antwort beendet, nicht nur bei Aufgabenvollendung. Sie werden nicht bei Benutzerunterbrechungen ausgelöst. API-Fehler lösen stattdessen StopFailure aus.
  • Wenn mehrere PreToolUse-Hooks updatedInput zurückgeben, um die Eingabe eines Tools umzuschreiben, führt Claude Code die Umschreibungen nicht zusammen und garantiert nicht, mit welcher Umschreibung das Tool ausgeführt wird. Vermeiden Sie, dass mehr als ein Hook die Eingabe desselben Tools umschreibt.

Hooks und Genehmigungsmodi

Mit einem Hook in einer Einstellungsdatei oder in der hooks/hooks.json eines Plugins können Sie Einschränkungen nicht über das hinaus lockern, was Berechtigungsregeln zulassen, und das "deny" eines Hooks gilt in jedem Berechtigungsmodus:

Wenn Ihr PreToolUse-Hook im Plan-Modus für eine Dateibearbeitung "allow" zurückgibt, erhalten Sie dieselbe Abfrage, Blockierung oder Genehmigung, die die Bearbeitung ohne Hook erhalten würde. Um diese Beschränkung für Hook-Genehmigungen aufzuheben, genehmigen Sie den Plan oder wechseln Sie in einen anderen Berechtigungsmodus.

  • "deny" in jedem Berechtigungsmodus: Ein Hook, der permissionDecision: "deny" zurückgibt, blockiert das Tool auch im bypassPermissions-Modus oder mit --dangerously-skip-permissions. PreToolUse-Hooks werden vor jeder Prüfung des Berechtigungsmodus in jedem Berechtigungsmodus ausgelöst, einschließlich dontAsk. Dies ermöglicht es Ihnen, eine Richtlinie durchzusetzen, die Benutzer nicht umgehen können, indem sie ihren Berechtigungsmodus ändern.

[!NOTE]

Wenn auf Ihrem Rechner keine verwalteten Einstellungen vorhanden sind und Ihre Sitzung keine /login-Anmeldedaten für einen Team- oder Enterprise-Plan verwendet, kann ein Mod einen Aufruf genehmigen, den Ihr PreToolUse-Hook blockiert hat. Eine Sitzung, die stattdessen mit einem API-Schlüssel oder einem langlebigen CLAUDE_CODE_OAUTH_TOKEN läuft, verwendet diese Anmeldung nicht, selbst wenn diese Anmeldung gespeichert ist.

Im Plan-Modus kann ein Mod einen solchen blockierten Aufruf nur genehmigen, wenn er nur lesend ist, also keine Dateibearbeitung. Für die Fälle, in denen die Genehmigung eines Mods nicht über Ihre Regeln und Hooks hinauskommt, siehe Berechtigungen mit Hooks erweitern.

Hook wird nicht ausgelöst

Der Hook ist konfiguriert, wird aber nie ausgeführt.

  • Führen Sie /hooks aus und bestätigen Sie, dass der Hook unter dem richtigen Ereignis angezeigt wird
  • Bei einem Hook im Frontmatter eines Skills rufen Sie den Skill auf oder bitten Sie Claude darum und führen Sie dann erneut /hooks aus. /hooks listet keine Hooks aus einem Skill auf, der in der Sitzung noch nicht aufgerufen wurde. Wenn /hooks den Hook weiterhin nicht auflistet, prüfen Sie andere Ursachen, etwa Frontmatter, das nicht geparst wurde, oder eine der Einschränkungen für Skill-Hooks
  • Überprüfen Sie, dass das Matcher-Muster den Tool-Namen genau entspricht. Matcher sind Groß-/Kleinschreibung-empfindlich
  • Überprüfen Sie, dass Sie den richtigen Ereignistyp auslösen: PreToolUse wird vor der Tool-Ausführung ausgelöst, PostToolUse wird danach ausgelöst. Ein PermissionRequest-Hook wird ausgelöst, wenn Claude Code Sie um Genehmigung bitten möchte; siehe die Einschränkungen für die nicht-interaktiven Fälle

Hook-Fehler in der Ausgabe

Sie sehen eine Nachricht wie „PreToolUse hook error: ...“ im Transkript.

  • Ihr Skript wurde unerwartet mit einem Code ungleich Null beendet. Testen Sie es manuell, indem Sie Beispiel-JSON pipen:

    echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh
    echo $?  # Check the exit code
    
  • Wenn Sie „command not found“ sehen, verwenden Sie absolute Pfade oder ${CLAUDE_PROJECT_DIR}, um auf Skripte zu verweisen. Um Shell-Quoting ganz zu vermeiden, fügen Sie "args": [] hinzu, um zur Exec-Form zu wechseln, die das Skript direkt ohne Shell spawnt

  • Wenn Sie „jq: command not found“ sehen, installieren Sie jq oder verwenden Sie Python/Node.js für JSON-Parsing

  • Wenn die Meldung blocking because Git Bash wasn't found enthält, arbeiten Sie unter Windows, Claude Code hat Git Bash nicht gefunden, und der fehlgeschlagene oder abgelaufene Hook hat den Tool-Aufruf blockiert. Siehe Fehlgeschlagene Hooks unter Windows ohne Git Bash für die Lösungen

  • Wenn die Benachrichtigung eine JSON-Validierungsmeldung anzeigt, wurde die stdout Ihres Hooks als JSON geparst, aber die Schema-Validierung ist fehlgeschlagen. Wenn sie eine JSON-Parse-Meldung anzeigt, sah die stdout wie ein JSON-Objekt aus, war aber kein gültiges JSON. Beides passiert auch bei Exit 0.

    Um einen Parse-Fehler zu beheben, erstellen Sie die Payload mit einem JSON-Encoder wie jq statt String-Verkettung, damit Anführungszeichen und Backslashes in Werten escaped werden. Der Abschnitt Exit code output der Referenz behandelt die Exit-Code- und JSON-Kombinationen

  • Wenn das Skript überhaupt nicht ausgeführt wird, machen Sie es ausführbar: chmod +x ./my-hook.sh

/hooks zeigt keine konfigurierten Hooks

Sie haben eine Einstellungsdatei bearbeitet, aber die Hooks werden nicht im Menü angezeigt.

  • Dateibearbeitungen werden normalerweise automatisch aufgegriffen. Wenn sie nach einigen Sekunden nicht angezeigt werden, hat der Datei-Watcher die Änderung möglicherweise übersehen: Starten Sie Ihre Sitzung neu, um ein Neuladen zu erzwingen.
  • Überprüfen Sie, dass Ihr JSON gültig ist: Nachfolgende Kommas und Kommentare sind nicht zulässig
  • Bestätigen Sie, dass sich die Einstellungsdatei am richtigen Ort befindet: .claude/settings.json für Projekt-Hooks, ~/.claude/settings.json für globale Hooks
  • Wenn das Menü Only hooks from managed settings run here anzeigt, hat Ihre Organisation allowManagedHooksOnly gesetzt. Hooks in Ihren Benutzer-, Projekt- und lokalen Einstellungsdateien werden nicht ausgeführt und nicht aufgelistet

Stop Hook trifft die Block-Obergrenze

Claude arbeitet weiter, anstatt zu stoppen, und beendet dann den Turn mit einer Warnung, dass der Stop Hook zu viele Male hintereinander blockiert hat.

Claude Code überschreibt einen Stop Hook, nachdem er achtmal hintereinander blockiert hat, ohne dass Claude dazwischen einen Tool-Aufruf ausgeführt hat. Ihr Hook-Skript muss überprüfen, ob es bereits eine Fortsetzung ausgelöst hat. Parsen Sie das Feld stop_hook_active aus der JSON-Eingabe und beenden Sie es früh, wenn es true ist:

#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0  # Allow Claude to stop
fi
# ... rest of your hook logic

Wenn Ihr Hook legitim mehr als acht Iterationen benötigt, um zu konvergieren, erhöhen Sie die Obergrenze mit CLAUDE_CODE_STOP_HOOK_BLOCK_CAP.

Hook JSON hat keine Auswirkung

Ihr Hook gibt gültiges JSON aus, aber die Entscheidung hat keine Auswirkung und es wird kein Fehler im Transkript angezeigt. Überprüfen Sie, welche Ursache zutrifft:

  • Zusätzliche Ausgabe vor dem JSON: Etwas anderes schreibt zuerst nach stdout, normalerweise ein bedingungsloses echo in Ihrem Shell-Profil, sodass die Ausgabe nicht mehr mit { beginnt. Siehe Shell-Profil-Ausgabe vor dem JSON.
  • Ein Feld auf der falschen Ebene: Vergleichen Sie die Platzierung jedes Feldes mit dem Format JSON output. Zum Beispiel gehört permissionDecision in hookSpecificOutput, nicht auf die oberste Ebene. Siehe Felder auf der falschen Ebene.

Shell-Profil-Ausgabe vor dem JSON

Hooks werden in nicht interaktiven Shells ausgeführt, aber Git Bash und einige Konfigurationen, wie BASH_ENV, das auf ~/.bashrc zeigt, laden dennoch Ihr Profil, und alles, was das Profil ausgibt, gelangt vor dem JSON Ihres Hooks nach stdout:

Shell ready on arm64
{"decision": "block", "reason": "Not allowed"}

Sofern der Hook nicht asynchron ist, liest Claude Code eine Ausgabe, die nicht mit { beginnt, als Klartext, sodass Ihr JSON ignoriert wird. Da der Hook mit Exit 0 beendet wurde, zeigt das Transkript auch keinen Fehler. Um diese Ursache zu prüfen, starten Sie Claude Code mit claude --debug, lösen Sie den Hook aus und suchen Sie im Debug-Log nach Hook output does not start with {. Um das Problem zu beheben, umschließen Sie die echo-Anweisungen in Ihrem Profil so, dass sie nur in interaktiven Shells ausgeführt werden:

# In ~/.zshrc or ~/.bashrc
if [[ $- == *i* ]]; then
  echo "Shell ready"
fi

Die Variable $- enthält Shell-Flags, und i bedeutet interaktiv. Hooks werden in nicht-interaktiven Shells ausgeführt, daher wird das Echo übersprungen.

Felder auf der falschen Ebene

Wenn Ihr Hook permissionDecision oder additionalContext auf der obersten Ebene statt in hookSpecificOutput zurückgibt, wird das JSON immer noch geparst, und Claude Code ignoriert die falsch platzierten Felder ohne Fehler zu melden. Um zu sehen, welche Felder ignoriert wurden, starten Sie Claude Code mit claude --debug und suchen Sie im Debug-Protokoll nach Hook JSON output had unrecognized keys.

Prüfen, was ein Hook getan hat

Drücken Sie Ctrl+O, um die Transkript-Ansicht zu öffnen, und suchen Sie nach dem Ergebnis des Hooks:

  • Erfolg: Sie sehen nichts, es sei denn, das JSON des Hooks zeigt etwas an, etwa systemMessage oder Stop Hook-Feedback.
    • Um zu bestätigen, dass der Hook ausgeführt wurde, prüfen Sie seine Auswirkung, etwa eine umformatierte Datei
  • Blockierender Fehler: Bei den meisten Ereignissen sehen Sie die Meldung, die mit der Blockierung ausgegeben wurde, zum Beispiel Blocked: rm commands are not allowed. Bei einigen Ereignissen, etwa ConfigChange und Elicitation, sehen Sie keine Meldung. Exit code 2 beschreibt, woher die Meldung stammt.
  • Nicht blockierender Fehler: Sie sehen eine Benachrichtigung <hook name> hook error mit einer kurzen Erklärung, etwa der ersten Zeile von stderr nach Failed with non-blocking status code: oder einer JSON-Validierungs- oder Parse-Meldung. Die Aktion wurde fortgesetzt.

Um das Ergebnis für einen bestimmten Exit-Code und eine bestimmte stdout nachzuschlagen, einschließlich der ereignisspezifischen Ausnahmen, lesen Sie den Abschnitt Exit code output in der Referenz.

Für vollständige Ausführungsdetails, einschließlich der Exit-Codes, stdout und stderr der Hooks, lesen Sie das Debug-Log. Starten Sie Claude Code mit claude --debug-file /tmp/claude.log, um in einen bekannten Pfad zu schreiben, und führen Sie dann tail -f /tmp/claude.log in einem anderen Terminal aus. Wenn Sie ohne dieses Flag gestartet haben, führen Sie /debug während der Sitzung aus, um das Logging zu aktivieren und den Log-Pfad zu finden.

Weitere Informationen