Inhalt
"Ich möchte nach jeder Bearbeitung automatisch formatieren." "Niemand soll jemals .env oder package-lock.json überschreiben." "Gefährliche rm -rf-Befehle stoppen." Der Weg, diese "das muss immer passieren"-Regeln real werden zu lassen – ohne von den Launen der KI abhängig zu sein – sind Claude Code Hooks. Ein Hook ist ein Shell-Befehl, der an bestimmten Punkten im Lebenszyklus von Claude Code automatisch ausgeführt wird, und Hooks sind außerdem ein Baustein von Plugins.
Dieser Artikel legt auf Basis der offiziellen Dokumentation dar, was Hooks sind, die Event-Liste, wie man sie konfiguriert, den Ein-/Ausgabe-Kontrakt, Anwendungsfälle und die Sicherheit. Drei Punkte vorweg. ① Ein Hook ist "deterministische Logik, die der Harness (Claude Code selbst) ausführt" – er feuert garantiert, ohne darauf zu warten, dass das Modell sich dafür "entscheidet". ② Hooks schreibt man in settings.json als Event-Name → matcher → command. ③ Events wie PreToolUse können per Exit-Code 2 oder JSON "blockieren" – und so Bearbeitungen geschützter Dateien oder gefährliche Befehle stoppen.
Feuert "garantiert" an wichtigen Lebenszyklus-Punkten
— der Harness führt ihn deterministisch aus, nicht das Ermessen des Modells
SessionStart
Session beginnt. Die Ausgabe wird als Kontext eingespeist
UserPromptSubmit
Wenn ein Prompt abgeschickt wird [kann blockieren]
PreToolUse
Direkt bevor ein Tool läuft = der Türsteher [kann blockieren]
PostToolUse
Nachdem ein Tool erfolgreich war = Auto-Format / Audit
Stop
Wenn eine Antwort endet = weitermachen, bis die Tests bestehen usw. [kann blockieren]
An jedem Punkt läuft dein Shell-Befehl. Die Klassiker: PreToolUse, um gefährliche Aktionen schon an der Tür abzuweisen, PostToolUse, um automatisch zu formatieren.
1. Was sind Claude Code Hooks?
Die offizielle Definition lautet: "Hooks sind benutzerdefinierte Shell-Befehle, die an bestimmten Punkten im Lebenszyklus von Claude Code ausgeführt werden. Sie bieten deterministische Kontrolle über das Verhalten von Claude Code und stellen sicher, dass bestimmte Aktionen immer geschehen, anstatt sich darauf zu verlassen, dass das LLM sich für ihre Ausführung entscheidet." Man setzt sie ein, um Projektregeln durchzusetzen, sich wiederholende Aufgaben zu automatisieren und Claude Code in vorhandene Tools zu integrieren.
Der Kern ist Determinismus. Bitte Claude, "die Tests auszuführen", und ob es das tut, hängt von seinem "Ermessen" ab. Aber mit einem Hook führt der Harness ihn immer aus – keine Laune kommt ins Spiel. Neben Befehlen (command) gibt es inzwischen auch Handler-Typen wie HTTP, MCP-Tools, LLM-Prompts und Subagent-Verifikation – aber zum Einstieg reicht es, sich Hooks als "einen Mechanismus, um an wichtigen Punkten immer einen Shell-Befehl auszuführen" vorzustellen.
2. Die Hook-Events
Ein Event steht dafür, "wo im Lebenszyklus es feuert". Beginne mit den neun Klassikern ("kann blockieren" = du kannst diese Aktion per Exit-Code 2 oder JSON stoppen).
| Event | Feuert, wenn | Blockieren |
|---|---|---|
| SessionStart | Eine Session beginnt oder wird fortgesetzt (stdout wird als Kontext eingespeist) | Nein |
| UserPromptSubmit | Du schickst einen Prompt ab, bevor Claude ihn verarbeitet | Ja |
| PreToolUse | Direkt vor einem Tool-Aufruf (der wichtigste Türsteher) | Ja |
| PostToolUse | Nachdem ein Tool erfolgreich war (die Aktion selbst lässt sich nicht rückgängig machen) | Ja |
| Notification | Bei einer Benachrichtigung (Warten auf Eingabe/Berechtigung usw.) | Nein |
| Stop | Wenn Claude mit dem Antworten fertig ist (blockieren = weiterarbeiten) | Ja |
| SubagentStop | Wenn ein Subagent fertig ist | Ja |
| SessionEnd | Wenn eine Session beendet wird | Nein |
| PreCompact | Vor der Kontext-Kompaktierung | Ja |
Die Doku von 2026 ergänzt viele weitere Events – PermissionRequest, PostToolUseFailure, ConfigChange, FileChanged, WorktreeCreate und andere. Aber Event-Namen können zwischen Versionen hinzukommen oder sich ändern, deshalb stützt sich dieser Artikel auf die stabilen neun Klassiker plus den Kontrakt im nächsten Abschnitt (die vollständige aktuelle Liste findest du in der offiziellen Doku).
3. Hooks konfigurieren
Hooks schreibt man unter dem Schlüssel "hooks" in settings.json. Der Ort legt den Geltungsbereich fest: Benutzer (~/.claude/settings.json) / Projekt (.claude/settings.json, per Git teilbar) / lokal (.claude/settings.local.json) / verwaltete Richtlinie (Organisation) / die hooks/hooks.json eines Plugins. Die JSON-Form sieht so aus.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
Die Struktur ist "hooks → Event-Name → ein Array aus { matcher, hooks:[...] } → jeder Hook hat type + command." Der matcher gibt den Ziel-Tool-Namen an: "*" (oder weggelassen) passt auf alle, "Edit|Write" ist eine durch | getrennte Liste, und andere Zeichen sind regulärer Ausdruck (z. B. mcp__memory__.*). Groß-/Kleinschreibung ist relevant. Der Befehl /hooks listet die konfigurierten Hooks auf, ist aber schreibgeschützt – zum Hinzufügen oder Ändern bearbeitet man settings.json direkt. Alle deaktivieren mit "disableAllHooks": true.
4. Der Ein-/Ausgabe-Kontrakt
Ein Hook empfängt JSON über die Standardeingabe (stdin) und gibt sein Ergebnis über den Exit-Code oder JSON auf der Standardausgabe zurück.
Eingabe (stdin): Zu den gemeinsamen Feldern gehören session_id, transcript_path, cwd und hook_event_name. Tool-Events ergänzen tool_name und tool_input (z. B. {"command":"rm -rf /tmp/build"}); UserPromptSubmit ergänzt prompt. Exit-Codes: 0 = Erfolg (bei manchen Events wird stdout zum Kontext hinzugefügt – wobei Exit 0 bei PreToolUse keine "Freigabe" ist; der normale Berechtigungsfluss gilt weiterhin), 2 = blockieren (stderr wird Claude als Material zum Nachjustieren übergeben, und JSON-Ausgabe wird ignoriert).
# Beispiel: "deny" von PreToolUse über strukturierte JSON-Ausgabe (auf stdout ausgegeben)
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Database writes are not allowed"
}
}
# Gemeinsame Felder: continue (false = vollständig stoppen) / decision:"block"+reason /
# additionalContext (für Claude angehängt) / updatedInput (Argumente umschreiben)
Das wichtigste Prinzip: "Hooks können Beschränkungen verschärfen, aber nicht lockern." Die Rückgabe von allow überspringt nur die Abfrage; deny-Regeln in jedem Geltungsbereich (einschließlich verwalteter Einstellungen) haben immer Vorrang. Ein PreToolUse-deny blockiert sogar unter bypassPermissions / --dangerously-skip-permissions. Zum umfassenderen Berechtigungsmodell siehe Berechtigungsmodi und Sicherheit.
5. Beispiel-Anwendungsfälle
Die offiziellen Klassiker, jeweils mit ihrer Konfiguration.
Die klassischen Automatisierungen
PostToolUse + Edit|Write führt automatisch prettier / einen Linter aus.PreToolUse blockiert (Exit 2) Bearbeitungen an .env, .git/ usw.PreToolUse erkennt rm -rf usw. und gibt deny zurück.SessionStart-stdout lädt Konventionen und Notizen jedes Mal neu (auch nach Kompaktierung).Notification für Desktop-Hinweise; PostToolUse, um den Befehlsverlauf zu protokollieren.Stop lässt Claude nicht stoppen, bis die Tests bestehen (weiterarbeiten, bis grün).
Hinweis: Claude kann Dateien auch über Bash ändern. Um jede Änderung zu erfassen, füge einen Stop-Hook hinzu, der den Arbeitsbaum einmal pro Runde durchsucht.
6. Sicherheit
Hooks sind mächtig, aber sie führen automatisch beliebige Shell-Befehle mit deinen Rechten aus – nimm das nicht auf die leichte Schulter.
⚠️ Die offizielle Warnung
"Hooks führen automatisch beliebige Shell-Befehle aus. Du allein bist für die Sicherheit der Hooks verantwortlich, die du konfigurierst. NUTZUNG AUF EIGENE GEFAHR." Hooks können Dateien lesen, deine Codebasis verändern, Daten exfiltrieren oder jeden beliebigen Befehl ausführen – konfiguriere nur solche, denen du vollständig vertraust.
Startup-Snapshot (ein zentrales Sicherheitsmerkmal): Die Hook-Konfiguration wird beim Session-Start erfasst, sodass Konfigurationsänderungen mitten in der Session nicht wirksam werden. Das verhindert, dass ein bösartiger Prompt oder eine Tool-Ausgabe deine Hook-Konfiguration umschreibt während einer Session. Wende Änderungen in einer neuen Session an.
In der Praxis: validiere und quote Eingaben immer (mit jq extrahieren; ungequotete Variablen können zu zusätzlichen Argumenten oder Shell-Syntax werden), nutze absolute Pfade und ${CLAUDE_PROJECT_DIR}, fass sensible Dateien wie .env oder .ssh nicht an und führe niemals eval auf Tool-Ausgaben aus. Hooks laufen ohne kontrollierendes Terminal (kein /dev/tty). In Organisationen können Admins Hooks mit allowManagedHooksOnly einschränken.
Zusammenfassung
Claude Code Hooks sind benutzerdefinierte Shell-Befehle, die an wichtigen Lebenszyklus-Punkten automatisch laufen und machen "das muss immer passieren" real und deterministisch, ohne vom Ermessen des Modells abhängig zu sein. Die klassischen Events sind die neun: SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Notification / Stop / SubagentStop / SessionEnd / PreCompact (PreToolUse und andere können blockieren – und so Bearbeitungen geschützter Dateien oder gefährliche Befehle stoppen). Konfiguriert werden sie in settings.json unter "hooks" als Event → matcher → type + command.
Die E/A ist JSON auf stdin, Exit-Code 0 (Erfolg) / 2 (blockieren) oder strukturiertes JSON auf stdout. Das Prinzip: "du kannst verschärfen, aber nicht lockern" (deny gewinnt immer). Die klassischen Anwendungsfälle: Auto-Format, Dateien schützen, gefährliche Befehle stoppen, Kontext erneut einspeisen, Audit, Testen vor dem Stoppen. Aber weil sie beliebigen Code ausführen, sei streng damit, nur sicheren Hooks zu vertrauen und Eingaben zu validieren/quoten, und verstehe, dass die Konfiguration beim Start erfasst wird. Verwandt: Plugins, MCP, Claude Code Fehler.
FAQ
F. Wofür sind Hooks da?
A. Sie automatisieren deterministisch "das muss immer passieren". Dinge wie "nach Bearbeitungen formatieren", "geschützte Dateien dürfen nie überschrieben werden", "gefährliche rm -rf stoppen" und "Tests bestehen, bevor gestoppt wird" werden garantiert vom Harness ausgeführt, ohne sich auf das Ermessen der KI zu verlassen. Ein Hook ist ein Shell-Befehl, der an wichtigen Lebenszyklus-Punkten läuft und in settings.json konfiguriert wird.
F. Welche Events (Zeitpunkte) gibt es?
A. Die Klassiker sind neun: SessionStart (Beginn), UserPromptSubmit (beim Abschicken), PreToolUse (direkt vor einem Tool), PostToolUse (nach einem Tool), Notification, Stop (Antwort endet), SubagentStop, SessionEnd (Beendigung), PreCompact (vor der Kompaktierung). Davon können PreToolUse, UserPromptSubmit, Stop, PreCompact und andere blockieren und die Aktion stoppen. Das Release 2026 ergänzt viele weitere Events, aber die Namen können sich zwischen Versionen ändern, prüfe also die offizielle Doku für den aktuellsten Stand.
F. Kann ich Bearbeitungen an geschützten Dateien oder gefährliche Befehle stoppen?
A. Ja – mit einem PreToolUse-Hook. Ein Skript inspiziert den Dateipfad oder Befehl in tool_input, und wenn er auf .env, rm -rf usw. passt, gibt es Exit-Code 2 (oder JSON mit permissionDecision:"deny") zurück, um ihn zu blockieren. Entscheidend: deny hat immer Vorrang und stoppt sogar unter bypassPermissions. Hooks wirken nur in Richtung "Beschränkungen verschärfen".
F. Ich habe meine Konfiguration geändert, aber sie wird nicht wirksam.
A. Das ist so gewollt (ein Sicherheitsmerkmal). Die Hook-Konfiguration wird beim Session-Start als Snapshot erfasst, sodass Änderungen mitten in der Session nicht greifen. Das verhindert, dass ein bösartiger Prompt oder eine Tool-Ausgabe deine Hook-Konfiguration heimlich umschreibt. Starte eine neue Session, um sie anzuwenden. Beachte, dass /hooks eine schreibgeschützte Liste ist; Hooks fügt man hinzu oder ändert man, indem man settings.json direkt bearbeitet.
F. Sind Hooks sicher?
A. Nicht bedingungslos. Hooks führen beliebige Shell-Befehle mit deinen Rechten aus, weshalb die Doku "Nutzung auf eigene Gefahr" sagt. Konfiguriere nur Hooks, denen du vertraust, validiere und quote Eingaben mit jq, nutze absolute Pfade und fass .env / .ssh nicht an und führe niemals eval auf Tool-Ausgaben aus. In Organisationen können Admins Hooks mit allowManagedHooksOnly einschränken.