Teams fügen Claude Code Hooks hinzu, damit KI-Agenten keinen Schaden anrichten, und nehmen dann an, dass sie funktionieren. Unsere bestanden jeden Lauf und taten dabei nichts. Ein Hook, der still nichts tut, ist schlimmer als gar keiner, weil niemand mehr hinschaut. Die Lösung sind vier günstige Checks, die jedes Team übernehmen kann.
Die kurze Antwort: Ein Hook verstummt, wenn seine Ausgabe nirgendwo ankommt, wenn sein Pfad nicht existiert oder wenn sein Exit-Code umgeschrieben wird. Prüfen Sie alle drei in der CI. Und legen Sie den wichtigsten Hook auf das Stop-Ereignis, damit der Agent nicht „fertig“ sagen kann, solange Tests rot sind.
Wie blockieren Claude Code Hooks überhaupt etwas?
Ein Hook ist ein Shell-Befehl, den Claude Code bei einem Ereignis ausführt. PreToolUse läuft vor einem Tool-Aufruf, Stop, wenn der Agent fertig werden will. Der Befehl bekommt das Ereignis als JSON-Objekt auf stdin.
Der Exit-Code entscheidet:
Exit 0 lässt durch.
Exit 2 blockiert. Was der Hook nach stderr schreibt, geht als Begründung an den Agenten zurück.
Jeder andere Code ist ein nicht blockierender Fehler. Claude Code macht weiter.
Das ist der ganze Vertrag. Alles, was bei uns kaputtging, ging innerhalb davon kaputt.
Warum taten unsere Hooks nichts?
Zwei Hooks in unserer Firmenkonfiguration waren eine Woche lang stumm, vom ersten Tag an. Drei Ursachen, jede für sich harmlos:
Stumm. Beide schrieben ihre einzige Meldung nach stderr. Der Befehl in den Settings endete auf 2>/dev/null. Der Agent hörte kein Wort.
Fehlend. Beide nutzten einen relativen Pfad. In einer Session, die in einem verschachtelten Repository startete, existierte der Pfad nicht. Exit 127, Befehl nicht gefunden.
Maskiert. Ein || true am Ende machte aus 127 eine 0. Bei einem blockierenden Ereignis macht es aus einer 2 genauso eine 0. Jeder Lauf „bestand“.
Niemand bemerkte es, weil ein stummer Hook genauso aussieht wie ein gesunder. Wir fanden es erst bei einer Analyse unserer eigenen Claude-Code-Sessions.
Wir haben unserem Validator einen Check hinzugefügt, der in der CI unserer Repositories läuft. Vier Greps über .claude/settings.json, nichts wird ausgeführt:
Check
Was er findet
Fix
Das Skript existiert
Einen Pfad, der nicht existiert
"$CLAUDE_PROJECT_DIR"/... oder ein absoluter Pfad
Das Skript ist ausführbar
Einen Hook, der nur zufällig läuft
chmod +x
stderr wird nicht verworfen, wenn das Skript dorthin schreibt
Einen stummen Hook
2>/dev/null entfernen
Ein PreToolUse-Hook endet nicht auf || true
Einen Block, der zum Durchlass wird
|| true entfernen
Wir haben den Check gegen den echten Fehler getestet. Die alte Konfiguration meldete kritische Fehler, die korrigierte bestand.
Nicht jedes || true ist ein Fehler. Unsere Begrüßung läuft auf SessionStart mit 2>/dev/null || true, mit Absicht. Eine Begrüßung darf nie eine Session kaputt machen. Der Check meldet es nur dort, wo ein Block erwartet wird.
Die Lektion in einem Satz, wie sie in unserem Hook gegen KI-Signaturen steht: „A rule is a request. This is the lock.“ Eine Regel ist eine Bitte, ein Hook ist ein Schloss. Und ein Schloss braucht einen eigenen Test.
Vor Kurzem hatte der Agent seine Regeln nur in Regeldateien, und manchmal hielt er sich nicht daran. Also haben wir daraus Checks gemacht, die er nicht umgehen kann.
Filip Papranec
Gründer von Digitaliko
Welcher Hook sperrt wirklich?
Der Stop-Hook. Ein Agent, der „fertig“ sagt, während Tests rot sind, kostet einen Senior eine Review-Runde. Ein Stop-Hook zwingt den Agenten, das zuerst zu beheben.
Unsere Version aus dem öffentlichen Starter, leicht gekürzt:
#!/bin/bash
# Stop hook: the agent can't finish while the checks are red.
in=$(cat)
[ "$(printf '%s' "$in" | jq -r '.stop_hook_active // false')" = true ] && exit 0
cd "${CLAUDE_PROJECT_DIR:-.}" 2>/dev/null || exit 0
out=$(GATE_SKIP_INSTALL=1 GATE_SCRIPTS="typecheck lint test" bash scripts/gate.sh checks 2>&1) && exit 0
jq -n --arg r "Checks are red. Fix them before you say the task is done:
$out" '{decision: "block", reason: $r}'
Schritt für Schritt macht er Folgendes:
01
Liest stop_hook_active
Ist es true, macht der Agent bereits wegen dieses Hooks weiter. Der Hook lässt ihn durch, damit er sich nicht endlos dreht.
02
Führt die Checks aus
Typecheck, Lint und Tests, dieselben wie in der CI.
03
Blockiert mit Begründung
Sind die Checks rot, gibt er decision: block mit dem Fehlerlog als Begründung zurück.
04
Der Agent behebt die Ursache
Er liest das Log, behebt den Fehler und versucht erneut, fertig zu werden.
Er blockiert mit JSON, nicht mit einem Exit-Code. Der Agent arbeitet weiter, und die Begründung, die er bekommt, ist genau das, was fehlschlug.
Er ist eine Frühwarnung, nicht das Gate. In unserem Agenten-Loop läuft der maßgebliche Check nach der Session noch einmal, in Code, den der Agent nicht anfassen kann. Der Hook spart nur eine Runde.
Was ging in unserem eigenen Stop-Hook kaputt?
Der Stop-Hook unseres Loops hatte einen eigenen stillen Fehler. Er setzte einen festen, minimalen PATH ohne die Werkzeugverzeichnisse des Benutzers, sodass in Repositories mit Bun die Werkzeuge fehlten, die die Checks brauchen. Außerdem suchte er das Gate an einem festen Ort, den es nur auf der Maschine des Agenten gab. Ein PR behob beides: der volle PATH, und das Gate wird relativ zum Hook selbst gefunden.
Claude Code Hooks im Team: wo anfangen?
Gehen Sie durch, was Ihre Repositories davon schon haben. Jeder Punkt sind ein paar Zeilen in den Settings oder in der CI:
Am leichtesten übersieht man den dritten Punkt. Unser Hook gegen KI-Signaturen liest seine Eingabe mit jq, weicht dann auf python3 und danach auf sed aus. Ein fehlendes jq darf das Schloss nie in ein stilles Erlauben verwandeln. Relative Pfade wiederum brechen in verschachtelten Repositories und Worktrees.
Starten können Sie mit dem Claude Code Production Starter: ein Push-Gate, ein Secret-Scan und ein Stop-Hook, MIT-Lizenz.
Möchten Sie Hooks, die in Ihren Repositories halten?
Wir richten Hooks, Gates und CI direkt im Repository eines Teams ein im Rahmen von AI-native SDLC für Entwicklerteams. Fehlen Ihrem Team eher Hände als Regeln? Sehen Sie sich einen Senior-Entwickler für Ihr Team an. KI schreibt heute unseren gesamten Code, und ein Senior steht für das Ergebnis gerade. Seit 2023 haben wir 15+ Produktionsprojekte geliefert.
Wir melden uns innerhalb von zwei Arbeitstagen und wählen gemeinsam, was wir zuerst lösen.
Shell-Befehle, die Claude Code bei Ereignissen ausführt, etwa PreToolUse vor einem Tool-Aufruf oder Stop, wenn der Agent fertig werden will. Ein Hook bekommt das Ereignis als JSON auf stdin und entscheidet mit seinem Exit-Code oder einer JSON-Antwort.
Wie blockiert ein Claude Code Hook einen Befehl?
Mit Exit-Code 2. Claude Code blockiert dann die Aktion und gibt das, was der Hook nach stderr geschrieben hat, als Begründung an den Agenten zurück. Exit 0 lässt sie durch. Jeder andere Code ist ein nicht blockierender Fehler, und der Agent macht weiter.
Warum läuft mein Claude Code Hook nicht?
Meist wegen eines relativen Pfads, der im Session-Verzeichnis nicht existiert, wegen stderr, das mit 2>/dev/null verworfen wird, oder wegen eines || true am Ende, das den Exit-Code umschreibt. Beginnen Sie den Pfad mit "$CLAUDE_PROJECT_DIR" und prüfen Sie die Hook-Konfiguration in der CI.
Was bedeutet stop_hook_active?
Es ist true, wenn der Agent bereits weitermacht, weil ein Stop-Hook ihn blockiert hat. Ist es true, beenden Sie sofort. Sonst blockiert ihn ein Check, den er nicht beheben kann, endlos.
Reicht ein Stop-Hook als Quality Gate?
Nein. Er ist eine Frühwarnung innerhalb der Session. Führen Sie dieselben Checks noch einmal in der CI und im Branch-Schutz aus, wo der Agent sie nicht ändern kann.
Fragen Sie eine KI zu diesem Artikel
Die KI nutzt dabei auch unsere anderen Artikel und Erfahrung aus echten Projekten.
Playwright MCP gibt einem KI-Agenten einen echten Browser. Wie wir ihn nutzen, damit der Agent seine eigene Änderung in der laufenden App prüft und PASS oder FAIL mit Screenshots zurückgibt, was das findet, was Unit-Tests übersehen, und wann einfache Playwright-Skripte besser sind.
LLM as a Judge heißt: Ein Sprachmodell bewertet die Arbeit eines anderen Modells anhand schriftlicher Kriterien. Wie wir das bei jedem Pull Request unseres KI-Agenten einsetzen: zuerst maschinelle Checks, dann eine frische Session nur mit Lesezugriff, die widerlegen soll, ein typisiertes Urteil und die Regeln, die nach seinen Fehlern dazukamen.
Wie wir Claude Code Review auf jedem Pull Request mit einer wiederverwendbaren GitHub Action betreiben: was der KI-Reviewer suchen soll, wie er grün blieb und schwieg, was er übersieht und warum nur ein Mensch freigibt.
Zeit, mit dem Planen aufzuhören und das Problem zu lösen.