VIBE CODING
KURS6 min read

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:

EventWann es feuertTypischer Einsatz
PreToolUseBevor Claude ein Werkzeug nutztGefährliche Befehle blockieren
PostToolUseNachdem ein Werkzeug gelaufen istLinter/Formatter nach Dateiänderungen
SessionStartBeim Start einer SessionUmgebung prüfen, Status laden
StopWenn Claude fertig istAbschluss-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_DIR zeigt 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:

SkillHook
Was ist es?Wissen und Anleitungen für das ModellShell-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 AnweisungNein, 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:

  1. Lege .claude/settings.json mit dem PostToolUse-Hook aus Beispiel 1 an (falls die Datei existiert, ergänze nur den "hooks"-Block)
  2. Starte eine neue Claude-Code-Session und lass Claude eine kleine Änderung an deinem Bot-Code machen
  3. Beobachte die Ausgabe: Läuft ESLint automatisch nach der Änderung?
  4. 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.json unter "hooks" — vom System ausgeführt, nicht vom Modell entschieden
  • Die wichtigsten Events: PreToolUse (vorher, kann blockieren), PostToolUse (nachher, ideal für Linter), SessionStart und Stop
  • 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.json und .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.