← Alle Beitrage

Claude Code Hooks: Warum jeder meiner 95 Hooks existiert

From the guide: Claude Code Comprehensive Guide

Ich habe 95 Hooks für Claude Code gebaut. Jeder einzelne existiert, weil zuerst etwas schiefgelaufen ist. Der git-safety-guardian existiert, weil Claude einen Force-Push auf main gemacht hat. Der recursion-guard existiert, weil ein Subagent unendlich viele Kindprozesse erzeugt hat. Das blog-quality-gate existiert, weil ich einen Beitrag mit 7 Passivsätzen und einer verwaisten Fußnote veröffentlicht habe.1

TL;DR

Claude Code Hooks führen Shell-Befehle an bestimmten Punkten im Lebenszyklus der KI-gestützten Entwicklung aus. Hooks bieten deterministische Garantien (Blockieren gefährlicher Git-Befehle, Kontextinjektion, Qualitätsdurchsetzung) auf einem probabilistischen System (dem LLM). Nach dem Aufbau von 95 Hooks in meiner gesamten Infrastruktur habe ich festgestellt, dass die besten Hooks aus Vorfällen entstehen, nicht aus Planung. Dieser Beitrag behandelt die Architektur, die Entstehungsgeschichten hinter meinen kritischsten Hooks und die Muster, die ich in 9 Monaten Hook-Entwicklung gelernt habe.


Die Architektur

Claude Code stellt Lebenszyklus-Ereignisse bereit, an denen Hooks Verhalten abfangen, modifizieren oder blockieren können:2

Sitzungsereignisse

Ereignis Wann es ausgelöst wird Meine Hooks
SessionStart Neue Sitzung beginnt session-start.sh — injiziert Datum, validiert venv, initialisiert Rekursionsstatus
SessionEnd Sitzung wird beendet Temporäre Dateien aufräumen

Werkzeugausführungsereignisse

Ereignis Wann es ausgelöst wird Meine Hooks
PreToolUse Vor jeder Werkzeugausführung git-safety-guardian.sh, recursion-guard.sh, credentials-check.sh
PostToolUse Nach Abschluss des Werkzeugs post-deliberation.sh, log-bash.sh

Antwortereignisse

Ereignis Wann es ausgelöst wird Meine Hooks
UserPromptSubmit Benutzer sendet einen Prompt Kontextinjektoren (Datum, Branch, Modellinformationen)
Stop Claude beendet die Antwort deliberation-pride-check.sh, reviewer-stop-gate.sh

Jeder Hook empfängt JSON über stdin und kommuniziert über stdout:

{"decision": "block", "reason": "Force push to main is prohibited"}

Oder er erlaubt stillschweigend durch Beenden mit Exit-Code 0.3


Entstehungsgeschichten: Die Hooks, die am meisten zählen

Hook 1: git-safety-guardian.sh (PreToolUse:Bash)

Der Vorfall: Während einer frühen Claude Code Sitzung bat ich den Agenten, „die Git-Historie aufzuräumen.” Der Agent führte git push --force origin main aus. Der Force-Push überschrieb drei Tage an Commits auf einem geteilten Branch. Ich konnte von einem lokalen Backup wiederherstellen, aber der 4-stündige Wiederherstellungsprozess überzeugte mich davon, dass probabilistische Beurteilung niemals destruktive Git-Operationen kontrollieren sollte.

Der Hook:

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

# Only check git commands
echo "$COMMAND" | grep -qE '\bgit\b' || exit 0

# Block force push to main/master
if echo "$COMMAND" | grep -qiE 'git\s+push\s+.*--force.*\b(main|master)\b'; then
    cat << EOF
{"decision": "block", "reason": "Force push to main/master blocked by safety hook"}
EOF
fi

Die Lektion: Der Hook versucht nicht, die Absicht zu verstehen. Er führt Mustererkennung auf dem Befehlsstring durch. Einfach, deterministisch, unmöglich durch geschicktes Prompting zu umgehen. Der Agent kann weiterhin Force-Pushes auf Feature-Branches durchführen (manchmal legitim), aber main/master sind dauerhaft geschützt.4

Verhinderte Vorfälle in der Lebenszeit: 8 abgefangene Force-Push-Versuche über 9 Monate.

Hook 2: recursion-guard.sh (PreToolUse:Task)

Der Vorfall: Beim Aufbau des Deliberation-Systems führte ich eine Sitzung aus, die 3 Explorations-Subagenten erzeugte. Jeder Subagent erzeugte ohne Spawn-Limits seine eigenen Subagenten. Die Rekursion verbrauchte API-Token mit der 10-fachen normalen Rate. Ich beendete die Sitzung manuell, nachdem ich den sich beschleunigenden Token-Verbrauch bemerkte.

Der Hook:

#!/bin/bash
CONFIG_FILE="${HOME}/.claude/configs/recursion-limits.json"
STATE_FILE="${HOME}/.claude/state/recursion-depth.json"

MAX_DEPTH=2
MAX_CHILDREN=5
DELIB_SPAWN_BUDGET=2
DELIB_MAX_AGENTS=12

# Validate integers safely (((VAR++)) crashes with set -e when VAR=0)
is_positive_int() {
    [[ "$1" =~ ^[0-9]+$ ]] && [[ "$1" -gt 0 ]]
}

Die zentrale Designentscheidung: Agenten erben ein Spawn-Budget von ihrem Elternprozess, anstatt die Tiefe zu inkrementieren. Ein Root-Agent mit budget=12 kann dieses Budget auf jede beliebige Baumstruktur verteilen. Tiefenbasierte Limits sind zu starr (sie verhindern tiefe, aber schmale Ketten, die völlig unbedenklich sind).5

Blockierte Vorfälle in der Lebenszeit: 23 unkontrollierte Spawn-Versuche.

Hook 3: blog-quality-gate.sh (Stop)

Der Vorfall: Ich veröffentlichte einen Blogbeitrag mit 7 Passivsätzen, einer Fußnote, die im Text referenziert aber im Referenzabschnitt fehlte, und „was implemented by the team” als Eröffnungszeile. Der Beitrag sah in meinem Editor poliert aus, bestand aber grundlegende Qualitätsprüfungen nicht, die jeder menschliche Reviewer entdeckt hätte.

Der Hook: Führt meinen 12-Modul-Blog-Linter auf jeder geänderten Blog-Inhaltsdatei aus. Prüft auf Passivkonstruktionen, verwaiste Fußnoten, fehlende Meta-Beschreibungen, nicht markierte Codeblöcke und Zitationsintegrität. Jeder Fund ist spezifisch: „Zeile 47: Passivkonstruktion erkannt in ‚was implemented by the team.’ Vorschlag: ‚the team implemented.’”

Die Parallele zu menschlichem Feedback: Der Hook kritisiert die Arbeit, nicht den Ausführenden. Er sagt „Zeile 47 enthält Passiv,” nicht „Sie schreiben schlecht.” Dasselbe Prinzip, das menschliches Feedback konstruktiv macht, macht auch automatisiertes Feedback nützlich.


Das Muster hinter 95 Hooks

Die konfigurationsgetriebene Architektur

Meine Hooks entwickelten sich von fest codierten Werten zu konfigurationsgetriebenem Verhalten:

~/.claude/configs/
├── recursion-limits.json     # Depth, spawn budgets, timeouts
├── deliberation-config.json  # Consensus thresholds per task type
├── consensus-profiles.json   # security=85%, docs=50%
├── circuit-breaker.json      # Failure mode configurations
└── file-scope-rules.json     # Path-scoped hook application

Die Verlagerung von Schwellenwerten in JSON-Konfigurationsdateien bedeutete, dass ich das Verhalten anpassen konnte, ohne Bash-Skripte zu bearbeiten. Als ich sicherheitsbezogenen Konsens bei 85 % brauchte, aber Dokumentation bei 50 %, dauerte die Konfigurationsänderung 30 Sekunden. Eine Codeänderung hätte Bearbeitung, Tests und erneutes Deployment erfordert.6

Das Lebenszyklus-Schichtungsmuster

Meine 95 Hooks bilden ein Sicherheitsnetz mit vier Schichten:

Schicht 1: Prävention (PreToolUse) — Schlechte Dinge stoppen, bevor sie passieren. git-safety-guardian, credentials-check, recursion-guard.

Schicht 2: Kontext (UserPromptSubmit, SessionStart) — Informationen injizieren, die der Agent benötigt. Datum, Branch, Projektkontext, Speichereinträge, Philosophieprinzipien.

Schicht 3: Validierung (PostToolUse) — Überprüfen, ob abgeschlossene Aktionen den Standards entsprechen. Post-Deliberation-Konsensprüfung, Ausgabeprotokollierung.

Schicht 4: Qualität (Stop) — Die finale Ausgabe kontrollieren. Pride Check, Quality Gate, Reviewer Stop Gate.

Jede Schicht ist unabhängig. Wenn ein PreToolUse-Hook stillschweigend fehlschlägt, erkennt der Stop-Hook dennoch Qualitätsprobleme. Tiefenverteidigung, angewendet auf KI-Agentenverhalten.


Konfiguration

Hooks befinden sich in .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "~/.claude/hooks/git-safety-guardian.sh",
        "timeout": 5000
      }
    ],
    "PreToolUse:Task": [
      {
        "command": "~/.claude/hooks/recursion-guard.sh"
      }
    ]
  }
}

Das matcher-Feld filtert, welche Werkzeuge den Hook auslösen. PreToolUse:Task ist eine Kurzform für einen Matcher, der nur bei Task-Werkzeugaufrufen ausgelöst wird. Asynchrone Hooks (async: true) laufen im Hintergrund, ohne zu blockieren.7

Geltungsbereichshierarchie

  1. Benutzerebene (~/.claude/settings.json) — gilt für alle Projekte. Meine 95 Hooks befinden sich hier.
  2. Projektebene (.claude/settings.json) — fügt projektspezifische Hooks hinzu.
  3. Skill-/Subagent-Frontmatter — beschränkt auf den Lebenszyklus einer bestimmten Komponente.8

Was ich anders machen würde

Mit 3 Hooks beginnen, nicht mit 25. Mein erster Monat brachte 25 Hooks hervor, von denen viele Kontext hinzufügten, den der Agent bereits hatte. Der Overhead von 25 Hooks, die bei jedem Werkzeugaufruf geladen wurden, war messbar. Ich reduzierte schließlich auf die Hooks, die echten Mehrwert lieferten (echte Vorfälle verhinderten, echte Qualitätsprobleme erkannten).

Konfigurationsgetrieben vom ersten Tag an. Ich verbrachte zwei Wochen damit, fest codierte Schwellenwerte in JSON-Konfigurationsdateien umzustrukturieren. Diese Umstrukturierung wäre kostenlos gewesen, wenn ich von Anfang an mit Konfigurationsdateien begonnen hätte.

Testinfrastruktur frühzeitig aufbauen. Die ersten 20 Hooks hatten keine Tests. Als ich das Test-Harness hinzufügte (48 Bash-Integrationstests), fand ich 3 Hooks, die bei Randfällen stillschweigend fehlschlugen. Tests hätten bereits mit Hook Nr. 1 ausgeliefert werden sollen.


Wichtigste Erkenntnisse

Für Entwickler, die mit Hooks beginnen: - Beginnen Sie mit drei Hooks: Git-Sicherheit (PreToolUse:Bash), Kontextinjektion (UserPromptSubmit) und Quality Gate (Stop); fügen Sie weitere erst hinzu, wenn Sie Vorfälle haben, die sie rechtfertigen - Verwenden Sie das Entscheidungs-Timing-Framework: Hook-Architektur ist irreversibel (95 Hooks hängen davon ab), investieren Sie daher in das Lebenszyklusmodell, bevor Sie Hooks schreiben

Für Teams, die Hooks standardisieren: - Standardisieren Sie Hooks auf Benutzerebene, damit jedes Teammitglied dieselben Sicherheitsleitplanken erhält - Erfassen Sie Hook-Metriken (blockierte Operationen, abgefangene Vorfälle), um den Wartungsaufwand zu rechtfertigen - Überprüfen Sie Hook-Protokolle monatlich, um neue Muster zu identifizieren, die eine Automatisierung verdienen


Referenzen


  1. Hook-Infrastruktur des Autors. 95 Hooks über 6 Lebenszyklus-Ereignisse, entwickelt über 9 Monate (2025–2026). 

  2. Anthropic, „Claude Code Documentation,” 2025. Hook-Lebenszyklus-Ereignisse. 

  3. Anthropic, „Claude Code Documentation,” 2025. Hook-Ein-/Ausgabe-JSON-Format. 

  4. git-safety-guardian.sh des Autors. 8 abgefangene Force-Push-Versuche erfasst in ~/.claude/state/

  5. recursion-guard.sh des Autors. Budget-Vererbungsmodell dokumentiert in ~/.claude/configs/recursion-limits.json

  6. Konfigurationsgetriebene Architektur des Autors. 14 JSON-Konfigurationsdateien, die alle Hook-Schwellenwerte und -Regeln kodieren. 

  7. Anthropic, „Claude Code Documentation,” 2025. Hook-Konfiguration und asynchrone Ausführung. 

  8. Anthropic, „Claude Code Documentation,” 2025. Hook-Geltungsbereichshierarchie. 

Verwandte Beiträge

Building Custom Skills for Claude Code: A Complete Tutorial

Build a code review skill from scratch. Covers directory structure, frontmatter fields, LLM-based matching, context budg…

10 Min. Lesezeit

Context Window Management: What 50 Sessions Taught Me About AI Development

I measured token consumption across 50 Claude Code sessions. Context exhaustion degrades output before you notice. Here …

6 Min. Lesezeit

Claude Code Hooks Tutorial: 5 Production Hooks From Scratch

Build 5 production Claude Code hooks from scratch with full JSON configs: auto-formatting, security gates, test runners,…

12 Min. Lesezeit