Einladen & verdienen

So funktionieren Einladungsboni

Teile deinen Einladungslink. Registriert sich ein Freund darüber und lädt Guthaben auf, erhältst du die angezeigte Prämie für seine weiteren Aufladungen.

Claude Code Stop Hook: Tests vor „fertig“ prüfen

Ein kurzer Stop Hook prüft Tests oder Dateien, bevor Claude Code den Zug beendet.

Inhalt

Claude Code Stop Hook: Tests vor „fertig“ prüfen

Ein „fertig“ von Claude Code heißt nur, dass der Agent seinen Zug beenden will. Es belegt weder einen gelaufenen Test noch ein aktuelles Build-Artefakt. Ein Stop Hook kann unmittelbar davor eine kleine lokale Prüfung ausführen und bei einem klaren Fehler weiterarbeiten lassen. Er ersetzt weder CI noch eine vollständige Teststrategie oder eine manuelle Freigabe.

Stop Hook, CLAUDE.md und CI haben unterschiedliche Aufgaben

  • Ein Stop Hook startet eine kurze Prüfung, wenn Claude Code seine Antwort abschließt: etwa git diff --check, einen gezielten Test oder eine erwartete Datei.
  • CLAUDE.md beschreibt die Regeln für den Agenten, beispielsweise welche Prüfung nötig ist. Die Datei führt selbst keinen Befehl aus.
  • CI läuft nach einem Push oder Pull Request in einer getrennten Umgebung. Sie bleibt die verbindliche Schranke für das Team.

Ein Hook, der bei jedem Turn ein Deployment auslöst, etwas veröffentlicht oder Daten an ein externes System schreibt, ist dafür ungeeignet. Solche Seiteneffekte sind schwer wiederholbar und im Fehlerfall schwer zurückzunehmen.

Einen überprüfbaren Abschluss definieren

Notieren Sie vor der Konfiguration genau vier Punkte:

  1. Behauptung: Was darf der Agent nach dem Turn sagen? Zum Beispiel: „Der Build wurde erzeugt.“
  2. Nachweis: Welche kurze lokale Prüfung belegt das? Etwa npm test -- --runInBand und test -s dist/app.js.
  3. Erfolg: Beide Prüfungen enden mit Exit-Code 0.
  4. Blockierung: Bei einem Fehler liefert der Hook JSON mit decision: "block" und einem kurzen reason.

Prüfen Sie die Befehle zuerst ohne Hook. Dauern sie mehrere Minuten oder brauchen sie Netzwerkzugriff, wählen Sie eine fokussiertere lokale Prüfung; den vollständigen Lauf übernimmt CI.

Wenn Claude Code über eine API angebunden ist, öffnen Sie zuerst die aktuelle BetterToken-Anleitung, hinterlegen Ihren eigenen API Key in der Tool-Konfiguration und senden eine kurze Testanfrage. Prüfen Sie danach im Dashboard das erwartete Modell, den Status und die Token-Nutzung. Der lokale Hook braucht den Key nicht; schreiben Sie ihn nie ins Hook-Log.

Einen minimalen Stop Hook einrichten

Legen Sie in .claude/settings.json einen projektbezogenen Stop Hook mit kurzer Laufzeit an:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "./scripts/check-before-stop.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Speichern Sie die Prüfung als scripts/check-before-stop.sh. Die Beispielbefehle sind nur für ein Node-Projekt; ersetzen Sie sie durch die tatsächlich vorhandenen Befehle und Pfade Ihres Repositorys.

#!/usr/bin/env sh
set -eu

if [ -t 0 ]; then
  input='{"stop_hook_active":false}'
else
  input=$(cat)
fi

stop_hook_active=$(printf '%s' "$input" | node -e '
let raw = "";
process.stdin.on("data", chunk => raw += chunk);
process.stdin.on("end", () => {
  try { process.stdout.write(String(Boolean(JSON.parse(raw).stop_hook_active))); }
  catch { process.stdout.write("false"); }
});')

block_stop() {
  if [ "$stop_hook_active" = "true" ]; then
    printf '%s\n' "Stop-Prüfung schlägt weiterhin fehl: $block_reason. Führen Sie sie manuell aus; CI bleibt erforderlich." >&2
    exit 0
  fi

  BLOCK_REASON="$block_reason" node -e 'process.stdout.write(JSON.stringify({decision:"block",reason:`Stop-Prüfung fehlgeschlagen: ${process.env.BLOCK_REASON}`}) + "\n")'
  exit 0
}

if ! npm test -- --runInBand >/dev/null 2>&1; then
  block_reason='npm test ausführen und den fehlgeschlagenen Test beheben'
  block_stop
fi

if ! test -s dist/app.js; then
  block_reason='dist/app.js neu erzeugen'
  block_stop
fi

printf '%s\n' 'Stop-Prüfung bestanden: Tests und dist/app.js'
exit 0

Machen Sie die Datei ausführbar:

chmod +x scripts/check-before-stop.sh

Nach der aktuellen Claude-Code-Dokumentation kann ein Stop Hook mit Code 0 strukturiertes JSON zurückgeben: decision: "block" verhindert das Beenden des Turns, und reason nennt Claude Code die Ursache. Ein Nicht-Null-Code und ein Timeout haben eine eigene Hook-Fehler-Semantik; verwenden Sie sie daher nicht als einzigen Blockiervertrag. Die Prüfung muss in das konfigurierte Zeitlimit passen.

Das Eingabefeld stop_hook_active ist beim nächsten Stop true, wenn Claude Code schon wegen eines Stop Hooks weiterarbeitet. Die fail-open-Verzweigung schreibt dann eine kurze Warnung nach stderr und liefert 0, statt denselben Fehler blind erneut zu blockieren. Das verhindert eine Endlosschleife, lockert aber nicht die CI-Grenze. Wenn wiederholtes Blockieren nötig ist, definieren Sie einen eigenen Zähler und eine explizite Grenze, statt eine nicht dokumentierte feste Wiederholungszahl anzunehmen.

Den vollständigen Ablauf manuell prüfen

Testen Sie nicht nur, ob das Skript im Terminal startet, sondern alle Zweige:

  1. Ändern Sie im Skript dist/app.js vorübergehend in dist/missing.js und führen Sie printf '%s\n' '{"stop_hook_active":false}' | ./scripts/check-before-stop.sh; echo $? aus. Erwartet werden JSON mit "decision":"block", ein kurzer reason und Code 0.
  2. Stellen Sie den korrekten Pfad wieder her, erzeugen Sie den Build und wiederholen Sie den Befehl. Erwartet wird Code 0.
  3. Setzen Sie erneut einen fehlenden Pfad, lassen Sie Claude Code eine kleine reversible Änderung ausführen und prüfen Sie, dass decision: "block" den Stop verhindert und den benannten Grund zurückmeldet.
  4. Ohne den Pfad zu korrigieren, führen Sie printf '%s\n' '{"stop_hook_active":true}' | ./scripts/check-before-stop.sh; echo $? aus. Erwartet werden eine kurze stderr-Warnung und Code 0; damit ist die Anti-Loop-Verzweigung geprüft.
  5. Stellen Sie den Pfad wieder her oder erstellen Sie ein aktuelles Artefakt. Beim nächsten Abschluss muss der Hook mit 0 enden und den Turn freigeben.

Dieser Ablauf trennt einen funktionierenden Stop Hook von einem Skript, das im Terminal fehlschlägt, Claude Code aber dennoch stoppen lässt.

Einen fehlgeschlagenen Stop sauber behandeln

Trennen Sie zwei Fälle. Liefert der Hook JSON mit decision: "block", lesen Sie reason: Die geprüfte Bedingung ist regulär fehlgeschlagen. Starten Sie diese Prüfung manuell, beheben Sie Test oder Code, vergewissern Sie sich, dass das Artefakt vom aktuellen Befehl stammt, und wiederholen Sie die Claude-Code-Aufgabe.

Beendet sich der Hook-Befehl selbst mit einem Nicht-Null-Code oder Timeout, ist das ein Ausführungsfehler des Hooks und kein bestätigter reason-Block. Lesen Sie Hook-Fehler und stderr, starten Sie das Skript manuell und korrigieren Sie Pfad, Rechte, Abhängigkeit oder Zeitlimit, bevor Sie erneut testen.

Protokollieren Sie nur Prüfungsname und Ergebnis. Geben Sie weder API Keys noch Inhalte aus .env, vollständige Prompts oder komplette Testlogs aus. Ein bestandenes git diff --check bestätigt keine Fachlogik; eine vorhandene Datei bestätigt keinen frischen Build. Der Hook kann ausschließlich die Behauptungen absichern, die Sie explizit darin prüfen.

Den API-Workflow getrennt halten

Für Claude Code über einen API-Provider erstellen und verwalten Sie den API Key in Ihrem eigenen Konto. Der Hook bleibt dabei lokal: Er braucht keinen Zugriff auf den Key, auf vollständige Prompts oder auf Dashboard-Logs. Prüfen Sie bei einer API-Störung die aktuelle Dokumentation für Base URL und Konfiguration; vermischen Sie diese Diagnose nicht mit dem lokalen Stop-Check.

Quellen

Bereit, Ihren LLM-Workflow zu optimieren?

Verbinden Sie Modelle über eine API, verwalten Sie Schlüssel und behalten Sie KI-Kosten im Blick.

Kostenlos starten