Praxisprojekt Second Brain · Agenten

Hooks

Lektion 4/611 Min. LesezeitFortgeschritten

Lernziele

  • Du wählst aus, welche Prüfungen im Vault als HookEin Befehl, den der Harness bei einem festen Ereignis automatisch ausführt, etwa vor oder nach jedem Tool-Aufruf. Ein Hook vor dem Aufruf kann ihn blockieren und dem Modell den Grund melden.Im Glossar laufen und welche nicht.
  • Du richtest einen Hook ein, der Frontmatter vor dem Schreiben prüft, und liest an seinem Exit-Code ab, ob er blockiert.
  • Du entscheidest für jeden Hook, ob ein Fehler im Hook selbst die Aktion stoppt oder durchlässt.

Ein Hook startet bei einem Ereignis, ein Zeitplan zu einer Uhrzeit. Hooks sind das richtige Werkzeug für alles, was jedes Mal passieren muss. Genau diese Dinge übersieht eine Anweisung im Prompt irgendwann.

Wie ein Hook in Claude Code aufgebaut ist, zeigt die Lektion Die vier Ringe am Beispiel eines Hooks, der git push auf main blockiert. Hier geht es darum, welche Hooks ein Vault braucht.

Was sich lohnt

Prüfen vor dem Schreiben. Der Hook prüft, ob das Frontmatter lesbar ist und die Pflichtfelder enthält. Eine kaputte Seite, die beim Schreiben auffällt, kostet dich nichts. Fällt sie erst einen Monat später auf, war sie seitdem für jede Abfrage unsichtbar.

Lint nach einem Lauf. Kaputte Links entstehen in dem Moment, in dem genug Kontext da ist, um sie richtig zu reparieren. Ein Hook auf das Ereignis Stop läuft, wenn Claude mit seiner Antwort fertig ist.

Commit nach einem geplanten Lauf. Damit gibt es keinen Lauf mehr, der vierzig Dateien geändert und keinen Commit hinterlassen hat. Stop feuert auch nach jeder Antwort in einer normalen Session. Gib diesen Hook deshalb nur dem geplanten Lauf mit, etwa über eine eigene Einstellungsdatei und den Schalter --settings.

Melden beim Löschen. Jede Löschung, jederzeit, wird sichtbar. Ein gepflegter Vault löscht wenig. Eine Meldung kostet also nichts und zählt in dem Moment, in dem sie kommt.

So sieht der Prüf-Hook aus. In .claude/settings.json im Vault meldest du ihn für das Ereignis PreToolUse an. Er läuft vor jedem Aufruf des Werkzeugs Write:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check_frontmatter.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

Das Skript .claude/hooks/check_frontmatter.py bekommt den geplanten Aufruf als JSON. Darin stehen der Pfad und der vollständige Inhalt der Datei. Die Pflichtfelder title, type, created und updated stammen aus dem Seitenvertrag der CLAUDE.md. Skript und Eintrag für die settings.json liegen im Werkzeugkasten des Kurses im Ordner hooks/:

import json, sys

data = json.load(sys.stdin)
path = data["tool_input"].get("file_path", "")
text = data["tool_input"].get("content", "")

if "/wiki/" not in path or not path.endswith(".md") or path.endswith(("/index.md", "/log.md")):
    sys.exit(0)

lines = text.split("\n")
if lines[0] != "---" or "---" not in lines[1:]:
    print(f"Blocked: {path} has no frontmatter block.", file=sys.stderr)
    sys.exit(2)

head = lines[1:lines.index("---", 1)]
keys = {l.split(":", 1)[0] for l in head if ":" in l and not l.startswith(" ")}
missing = [k for k in ("title", "type", "created", "updated") if k not in keys]
if missing:
    print(f"Blocked: {path} is missing {', '.join(missing)} in the frontmatter.", file=sys.stderr)
    sys.exit(2)

Seiten außerhalb von wiki/, Index und Log lässt das Skript durch. Fehlt der Frontmatter-Block oder ein Pflichtfeld, endet es mit Code 2. Das blockiert den Aufruf, und die Meldung auf stderr geht an Claude. Der Hook prüft nur Write, denn bei Edit steht im Aufruf nur das geänderte Stück. Fehler aus Änderungen findet der Lint.

Wir haben den Hook in einem Test-Vault mit Claude Code 2.1.322 und dem Modell Haiku ausprobiert. Der Auftrag verlangte ausdrücklich eine Seite ohne Frontmatter:

Der Prüf-Hook blockt eine Seite ohne Frontmatter1/4
  1. DuCreate the file wiki/concepts/Testing effect.md containing only the line '# Testing effect'. Do not add anything else. Report what happened.

Was sich nicht lohnt

Alles, was langsam ist. Ein Hook, der bei jedem Schreiben läuft und zwei Sekunden braucht, macht aus einem Import von vierzig Seiten eine Pause von achtzig Sekunden. Du schaltest ihn dann ab.

Alles, was Urteil braucht. Claude Code kennt inzwischen auch Hooks vom Typ prompt und agent, die ein Modell entscheiden lassen. Nach unserer Einschätzung gehört die Frage, ob eine Seite gut genug ist, trotzdem nicht in einen Hook. Ein Hook, der darüber entscheidet, liegt in beide Richtungen daneben, und er blockiert mitten im Lauf. Qualität prüft ein zweiter Agent oder du im Rückblick.

Welcher Hook passt?

Entscheide für jede Prüfung, ob sie als Hook blockieren darf, als Hook nie blockieren soll oder gar kein Hook wird.

Noch offen (6)

  • Frontmatter prüfen, bevor eine Wiki-Seite geschrieben wird
  • Schreiben in raw/ verhindern
  • Eine Meldung schicken, wenn eine Seite gelöscht wird
  • Nach dem geplanten Lauf committen
  • Beurteilen, ob eine neue Konzeptseite gut genug geschrieben ist
  • Bei jedem Schreiben den ganzen Vault linten, zwei Sekunden pro Lauf

Hook, der blockiert (0)

    Hook, der nie blockiert (0)

      Kein Hook (0)

        Schnell und still

        Ein Hook sollte deutlich unter einer Sekunde fertig sein und nichts ausgeben, wenn die Prüfung besteht. Hooks, die auch bei Erfolg etwas melden, gewöhnen dich daran, ihre Ausgabe zu übergehen. Am Tag, an dem einer anschlägt, ist das so, als hättest du keine Hooks.

        Das Skript oben braucht rund 30 Millisekunden und schweigt bei Erfolg. Bei Code 0 landet die Standardausgabe für die meisten Ereignisse ohnehin nur im Debug-Log. Setz trotzdem ein timeout. Ohne diese Angabe wartet Claude Code bei einem Hook vom Typ command bis zu 600 Sekunden (Stand: Nov. 2026).

        Verhalten bei Fehlern

        Leg für jeden Hook ausdrücklich fest, ob ein Fehlschlag die Aktion blockiert.

        Prüf-Hooks sollen blockieren: Eine Seite, die die Prüfung nicht besteht, soll gar nicht erst geschrieben werden.

        Melde-Hooks lassen die Aktion immer durch. Scheitert eine Benachrichtigung, bleibt die Arbeit trotzdem erhalten.

        Claude Code unterscheidet dabei zwei Fälle. Blockiert wird nur, wenn der Hook mit Code 2 endet. Stürzt der Hook ab, endet er mit Code 1 oder läuft er in das Zeitlimit, geht die Aktion standardmäßig weiter. Ein Prüf-Hook mit falschem Pfad lässt dann still alles durch. Ab Claude Code 2.1.295 drehst du das mit "onFailure": "block" im Eintrag des Hooks um.

        Hook endet mit Ohne onFailure Mit "onFailure": "block"
        Code 0 Aktion läuft Aktion läuft
        Code 2 blockiert, stderr geht an Claude blockiert, stderr geht an Claude
        Absturz, Code 1, Zeitlimit Aktion läuft trotzdem blockiert

        Der schlimme Fall ist ein blockierender Hook, der aus einem fremden Grund scheitert und deinen geplanten Import eine Woche lang still anhält. Setzt du onFailure auf block, reicht dafür ein fehlendes python3 im Suchpfad des Jobs. Was blockiert, muss deshalb so einfach sein, dass es nur aus dem Grund scheitert, für den es da ist. Starte das Skript nach jeder Änderung einmal von Hand mit einer Beispiel-Eingabe.

        Merksätze

        • Hooks laufen bei Ereignissen und eignen sich für alles, was jedes Mal passieren muss.
        • Lohnend sind Prüfung vor dem Schreiben, Lint und Commit nach dem Lauf und eine Meldung beim Löschen.
        • Langsame Prüfungen und Urteile über Qualität gehören nicht in einen Hook.
        • Ein Hook ist schnell, schweigt bei Erfolg und hat ein timeout.
        • Nur Code 2 blockiert. Abstürze lassen die Aktion durch, außer du setzt "onFailure": "block", und dann muss der Hook sehr einfach sein.

        Prüf dich selbst

        Denkfrage

        Dein Prüf-Hook verweist nach einem Umzug des Vaults auf einen Pfad, den es nicht mehr gibt. Was passiert bei den nächsten Läufen?

        Denkfrage

        Warum prüft der Hook nur Write und nicht Edit?

        Prüf dich selbst

        1. 1Mit welchem Exit-Code blockiert ein PreToolUse-Hook den Aufruf?
        2. 2Ein Hook läuft bei jedem Schreiben und braucht zwei Sekunden. Was ist das Problem?
        3. 3Welche Prüfung gehört nicht in einen Hook?
        4. 4Ein Hook, der nach jeder Antwort committet, ist auf Stop gesetzt. Warum gibst du ihn nur dem geplanten Lauf mit?

        Quellen

        1. Hooks reference · Anthropic, Stand: Nov. 2026

          Ereignisse, Exit-Codes, Standard-Zeitlimit 600 s, onFailure ab 2.1.295, Hook-Typen prompt und agent.

        2. Run Claude Code programmatically · Anthropic, Stand: Nov. 2026

          Zusätzliche Einstellungen per --settings.

        Dein Fortschritt bleibt nur in diesem Browser gespeichert.