Claude Code Hooks
Kurz: Shell-Kommandos (oder Prompts/Agents), die Claude Code automatisch an bestimmten Punkten im Ablauf ausführt – z. B. bevor ein Tool läuft, nachdem Claude fertig geantwortet hat, oder wenn eine Session startet bzw. endet.
Genauer: Hooks werden in settings.json konfiguriert, pro Event (z. B. Stop, PreToolUse, SessionEnd) und optional mit einem “Matcher” (z. B. nur für bestimmte Tools). Wichtig: Stop feuert nach jedem Antwort-Turn, nicht nur einmal am Ende der ganzen Konversation – für “einmal pro Session” ist eigentlich SessionEnd gedacht.
Kontext bei uns: Wir haben testweise einen Stop-Hook gebaut, der nach jeder Antwort das komplette JSONL-Transkript 1:1 in eine Obsidian-Notiz dumpt – dann aber wieder verworfen, weil du stattdessen inhaltliche Hefteinträge statt Rohtext wolltest. Jetzt schreibe ich Glossareinträge wie diesen stattdessen live während des Gesprächs.
Im Detail
Konfiguration und Matcher
Hooks werden pro Event in settings.json (oder settings.local.json für lokale, nicht committete Overrides) konfiguriert. Eine typische Definition sieht so aus:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "echo 'Bash wird ausgeführt' >> log.txt" }]
}
]
}
}Der matcher filtert, für welche Tools/Ereignisse der Hook überhaupt feuert — ohne Matcher läuft er bei jedem Event dieser Kategorie. Mehrere Hooks lassen sich für dasselbe Event registrieren; sie laufen dann der Reihe nach.
Verfügbare Event-Typen
Neben PreToolUse/PostToolUse (vor bzw. nach jeder Tool-Ausführung) und Stop (nach jedem Antwort-Turn) gibt es u. a. SessionStart/SessionEnd (einmalig beim Start/Ende einer Session), UserPromptSubmit (wenn der Nutzer eine Nachricht abschickt, bevor Claude sie verarbeitet) und PreCompact (bevor der Kontext komprimiert wird). Jeder Event-Typ bekommt dabei unterschiedliche strukturierte Daten über stdin übergeben (z. B. bei PreToolUse den Namen des Tools und dessen Eingabeparameter als JSON) — ein Hook-Skript kann diese Daten auslesen und darauf basierend entscheiden, ob und wie es reagiert.
Blockieren von Tool-Aufrufen
Ein PreToolUse-Hook kann eine Tool-Ausführung sogar blockieren (indem er mit einem bestimmten Exit-Code oder einer bestimmten Ausgabe antwortet), was sich z. B. für eigene Sicherheitsregeln nutzen lässt — etwa um bestimmte Bash-Befehle grundsätzlich zu verbieten, unabhängig von Claudes eigener Einschätzung. Das ist ein wichtiger Unterschied zu bloßen Instruktionen in CLAUDE.md: Ein Hook ist eine harte, vom Harness selbst durchgesetzte Regel, die nicht durch geschickte Prompt-Formulierung umgangen werden kann, während Textinstruktionen im Prinzip immer nur Verhaltensrichtlinien sind, denen das Modell folgt.
Shell-Kommandos vs. Prompts/Agenten
Neben reinen Shell-Kommandos können Hooks auch komplexere Prompts oder eigene Agenten anstoßen, nicht nur einzeilige Skripte. Das erlaubt z. B. einen Stop-Hook, der nach jeder Antwort automatisch einen Review-Agenten auf die zuletzt geänderten Dateien loslässt, oder einen SessionEnd-Hook, der eine Zusammenfassung der Session generiert — deutlich mächtiger als ein reines Shell-Skript, aber auch mit entsprechend höherem Ressourcenverbrauch, da dabei wieder ein LLM-Aufruf involviert ist.
Wichtige Unterschiede zwischen ähnlich klingenden Events
Stop feuert nach jedem Antwort-Turn, nicht nur einmal am Ende der ganzen Konversation — ein leicht zu übersehender Fallstrick, wenn man eigentlich “einmal pro Session” erreichen möchte. Für dieses Ziel ist SessionEnd gedacht, das tatsächlich nur beim Beenden der gesamten Session feuert. Wer beides verwechselt, riskiert entweder einen Hook, der bei jedem einzelnen Antwort-Turn unnötig oft läuft, oder einen, der gar nicht wie gewünscht am eigentlichen Ende reagiert.
Siehe auch: JSONL