Hooks: Automatische Leitplanken für deinen Agenten
Lerne, wie du mit Hooks in Claude Code automatische Leitplanken einziehst — Linter nach jeder Änderung, Schutz vor destruktiven Befehlen, Events wie PreToolUse und PostToolUse.
Hooks: Automatische Leitplanken für deinen Agenten
"Bitte lass nach jeder Änderung den Linter laufen" — steht in deiner CLAUDE.md, und trotzdem vergisst Claude es in jeder dritten Session. Der Grund ist simpel: Anweisungen im Kontext sind Bitten. Das Modell befolgt sie meistens. Meistens reicht aber nicht, wenn dein Content-Bot nachts unbeaufsichtigt läuft.
Für alles, was immer passieren muss, gibt es Hooks: Shell-Kommandos, die Claude Code selbst ausführt — automatisch, bei jedem passenden Ereignis, ohne dass das Modell mitentscheiden darf.
Was Hooks sind
Ein Hook ist ein Eintrag in der settings.json deines Projekts (.claude/settings.json) unter dem Schlüssel "hooks". Du legst fest: Bei welchem Ereignis soll welches Kommando laufen. Claude Code führt es dann verlässlich aus — das Modell kann es weder vergessen noch überspringen.
Die wichtigsten Ereignisse:
| Event | Wann es feuert | Typischer Einsatz |
|---|---|---|
PreToolUse | Bevor Claude ein Werkzeug nutzt | Gefährliche Befehle blockieren |
PostToolUse | Nachdem ein Werkzeug gelaufen ist | Linter/Formatter nach Dateiänderungen |
SessionStart | Beim Start einer Session | Umgebung prüfen, Status laden |
Stop | Wenn Claude fertig ist | Abschluss-Checks, Benachrichtigungen |
Ein PreToolUse-Hook kann eine Aktion sogar verhindern: Beendet sich dein Kommando mit Exit-Code 2, wird das Werkzeug blockiert und Claude bekommt deine Fehlermeldung als Feedback.
Beispiel 1: Linter nach jeder Dateiänderung
Zurück zur Content-Fabrik. Dein Bot-Projekt hat ESLint konfiguriert, und du willst, dass jede von Claude geänderte Datei sofort geprüft wird — nicht erst, wenn der Bot nachts mit einem Syntaxfehler abstürzt.
In .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx eslint --no-warn-ignored \"$CLAUDE_PROJECT_DIR\""
}
]
}
]
}
}
Was hier passiert:
"PostToolUse"— der Hook feuert nach jedem Werkzeug-Einsatz"matcher": "Edit|Write"— aber nur bei den Werkzeugen, die Dateien ändern"command"— das Shell-Kommando;$CLAUDE_PROJECT_DIRzeigt auf dein Projektverzeichnis
Meldet ESLint einen Fehler, sieht Claude die Ausgabe direkt und korrigiert nach — noch in derselben Session, ohne dass du es anstoßen musst. Aus "bitte denk an den Linter" wird ein Regelkreis, der sich selbst schließt.
Beispiel 2: Warnung vor destruktiven Befehlen
Dein Bot-Projekt enthält eine queue.json mit allen geplanten Posts und eine .env mit dem Bot-Token. Beides darf niemals einem übermütigen Aufräum-Befehl zum Opfer fallen. Ein PreToolUse-Hook prüft jeden Bash-Befehl, bevor er läuft:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guard.sh"
}
]
}
]
}
}
Im Skript .claude/hooks/guard.sh steckt die eigentliche Logik: Der Hook liest den geplanten Befehl aus der Hook-Eingabe (Claude Code übergibt sie als JSON auf stdin) und blockiert, was gefährlich aussieht:
#!/bin/bash
befehl=$(jq -r '.tool_input.command // ""')
if echo "$befehl" | grep -qE 'rm -rf|queue\.json|\.env'; then
echo "Blockiert: Befehl beruehrt geschuetzte Dateien ($befehl)" >&2
exit 2
fi
exit 0
Exit-Code 2 heißt: Werkzeug-Aufruf abgebrochen, Fehlermeldung geht an Claude. Der Agent muss sich einen anderen Weg suchen — oder dich fragen. Exit-Code 0 heißt: freie Fahrt. Vergiss nicht, das Skript ausführbar zu machen (chmod +x .claude/hooks/guard.sh).
Ein Hinweis zur Ehrlichkeit: Ein simpler Muster-Filter ist eine Leitplanke, kein Panzerglas. Kreative Umwege fängt er nicht alle ab. Für die typischen Unfälle — versehentliches Löschen, hastiges Überschreiben — reicht er trotzdem erstaunlich weit.
Hook oder Skill? Die Abgrenzung
Beide leben im .claude/-Ordner, beide automatisieren — und trotzdem sind sie Gegensätze:
| Skill | Hook | |
|---|---|---|
| Was ist es? | Wissen und Anleitungen für das Modell | Shell-Kommando, vom System ausgeführt |
| Wer entscheidet? | Claude (wendet an, wenn es passt) | Niemand — läuft immer beim Event |
| Kann vergessen werden? | Ja, wie jede Anweisung | Nein, wird erzwungen |
| Typischer Einsatz | "So schreibst du einen Post" | "Nach jedem Edit läuft der Linter" |
Merksatz: Skill = Wissen fürs Modell. Hook = Gesetz vom System. Alles, was verhandelbar ist (Stil, Vorgehen, Prozesswissen), gehört in Skills. Alles, was nicht verhandelbar ist (Qualitäts-Checks, Schutzregeln), gehört in Hooks.
Die Kombination macht den Unterschied: Der Skill erklärt Claude, wie gute Arbeit aussieht. Der Hook stellt sicher, dass schlechte Arbeit nicht durchkommt. In der 5-Phasen-Pipeline heißt das: Skills treiben die Phasen, Hooks bewachen die Übergänge.
Drei Regeln für gute Hooks
Regel 1: Schnell bleiben. Ein PostToolUse-Hook läuft nach jeder passenden Aktion. Ein Linter, der 30 Sekunden braucht, bremst jede Session aus. Prüfe wenn möglich nur die geänderte Datei statt des ganzen Projekts, und miss die Laufzeit, bevor du einen Hook dauerhaft aktivierst.
Regel 2: Laut scheitern, leise durchwinken. Wenn alles in Ordnung ist, soll der Hook still sein (Exit-Code 0, keine Ausgabe). Wenn etwas schiefläuft, soll die Fehlermeldung konkret sein — "Blockiert: Befehl berührt queue.json" hilft Claude beim Umplanen, ein nacktes "Error" hilft niemandem.
Regel 3: Hooks sind Code — behandle sie so. Die settings.json und deine Hook-Skripte gehören ins Git-Repository, damit jede Session (und jedes Teammitglied) dieselben Leitplanken hat. Nach jeder Änderung an einem Hook gilt: einmal absichtlich den Fehlerfall auslösen und prüfen, ob die Leitplanke wirklich greift.
Übung: Deine erste Leitplanke
Zieh die Linter-Leitplanke in dein Bot-Projekt ein:
- Lege
.claude/settings.jsonmit demPostToolUse-Hook aus Beispiel 1 an (falls die Datei existiert, ergänze nur den"hooks"-Block) - Starte eine neue Claude-Code-Session und lass Claude eine kleine Änderung an deinem Bot-Code machen
- Beobachte die Ausgabe: Läuft ESLint automatisch nach der Änderung?
- Der Härtetest: Bitte Claude, absichtlich eine Datei mit einem Fehler zu schreiben (etwa einer ungenutzten Variable). Greift der Hook? Korrigiert Claude von selbst nach?
Bonus: Baue den Guard aus Beispiel 2 ein und bitte Claude testweise, queue.json zu löschen. Wenn die Blockade greift und Claude höflich ablehnt statt zu löschen, hast du alles richtig gemacht.
Zusammenfassung
- Hooks sind Shell-Kommandos in der
settings.jsonunter"hooks"— vom System ausgeführt, nicht vom Modell entschieden - Die wichtigsten Events:
PreToolUse(vorher, kann blockieren),PostToolUse(nachher, ideal für Linter),SessionStartundStop - Exit-Code 2 in einem
PreToolUse-Hook blockiert die Aktion und gibt Claude deine Begründung als Feedback - Praktische Leitplanken für die Content-Fabrik: Linter nach jeder Dateiänderung, Guard vor destruktiven Befehlen auf
queue.jsonund.env - Abgrenzung: Skill = Wissen fürs Modell (kann ignoriert werden), Hook = erzwungene Regel vom System (kann es nicht)
Mit Subagenten und Hooks hast du jetzt beides: ein Team, das für dich arbeitet, und Leitplanken, die es auf Kurs halten. Zeit für den Blick zurück und nach vorn: Fazit und Ausblick.