Feine KI-Automatisierung, die nix vergisst: Claude Code Hooks
Warum sollte ich das hier lesen?
Wenn Du mit Claude Code arbeitest und Dir schon einmal gewünscht hast, dass bestimmte Dinge automatisch passieren, ohne dass Du jedes Mal daran denken musst, dann bist Du hier richtig.
Was Du hier lernst: Drei konkrete Beispiele
Beispiel 1: Automatische Backups Bevor Claude Code eine wichtige Konfigurationsdatei ändert, wird automatisch eine Sicherungskopie erstellt. Ohne dass Du daran denken musst. Ohne dass Du ein Kommando eingeben musst. Einfach zuverlässig, jedes Mal. Falls etwas schiefgeht, existiert die vorherige Version und Du kannst innerhalb von Sekunden zurückwechseln. Die Wiederherstellung erfolgt entweder manuell oder durch einen entsprechend konfigurierten Hook bzw. MCP-Server.
Beispiel 2: Lückenlose Protokollierung und Meta-Analysen Jede Aktion, die Claude Code durchführt, wird in einer Protokoll-Tabelle in einer Datenbank festgehalten. Welche Datei wurde wann geändert? Welches Kommando wurde ausgeführt? Am Ende des Tages hast Du einen vollständigen Überblick über alle Änderungen. Das ist besonders wertvoll in Teams oder bei komplexen Projekten, wo Nachvollziehbarkeit wichtig ist.
Der eigentliche Mehrwert entsteht jedoch durch Meta-Analysen dieser Protokolldaten. Du kannst Claude oder Ollama bitten, die gesammelten Protokolle zu analysieren und Muster zu erkennen. Etwa welche Dateien besonders häufig geändert werden, welche Fehler wiederholt auftreten oder wo Performance-Engpässe entstehen. So verstehst Du, woran es immer und immer wieder hängt. Diese Erkenntnisse helfen dabei, systematische oder systemische Fehler zu identifizieren und langfristig zu beheben, statt nur Symptome zu behandeln.
Beispiel 3: Sicherheitsprüfungen vor kritischen Änderungen Bestimmte Dateien oder Verzeichnisse sind besonders kritisch. Ein Hook kann prüfen, ob eine geplante Änderung gegen festgelegte Regeln verstößt, und die Aktion blockieren, bevor Schaden entsteht. Etwa wenn jemand versucht, eine Produktionsdatenbank außerhalb der erlaubten Wartungsfenster zu ändern. Solche Hooks erhöhen die Sicherheit innerhalb eines Vertrauensmodells, ersetzen aber keine echten Sicherheitsgrenzen.
Weitere Bereiche, in denen ich standardmäßig Hooks einsetze:
- Automatische Berechtigungsprüfung: Nach jeder Dateiänderung werden Dateiberechtigungen automatisch geprüft und gegebenenfalls auf die korrekten Werte gesetzt.
- MCP-Server-Integration: Ich nutze Hooks auch, um MCP-Server (Model Context Protocol Server) für Datenbankzugriffe, HTTP-Requests oder Code-Analysen einzubinden, statt direkte Kommandos auszuführen.
- Content-Validierung: Bei der Text-Erstellung wird via Claude Hooks automatisiert geprüft, ob die Vorgaben von Autorenprofilen, Struktur- und Richtlinien-Dateien eingehalten werden. Wenn nicht, wird via Kritiker-System und MCP-Server eine Korrektur der jeweiligen Systemparameter eingeleitet.
- Automatisierte Dokumentation: Nach Code-Änderungen werden Dokumentationen und Code-Kommentare automatisch aktualisiert und auf Konsistenz geprüft.
- Code-Quality-Checks: Vor kritischen Operationen werden automatisch Syntax-Prüfungen, Stil-Analysen und Qualitätskontrollen durchgeführt.
- Automatische Tests: Nach Änderungen werden relevante Tests ausgeführt, Ergebnisse protokolliert und bei Fehlern Benachrichtigungen versendet.
- Security-Scanning: Vor jeder Dateiänderung wird automatisch geprüft, ob versehentlich Passwörter, API-Keys oder andere sensible Daten im Code enthalten sind.
- Deployment-Validierung: Vor dem Deployment werden automatisch Checklisten geprüft, kritische Konfigurationen validiert und Abhängigkeiten überprüft.
Die Vorteile auf einen Blick
- Zuverlässigkeit: Hooks laufen jedes Mal, ohne dass Du daran denken musst. Sie vergessen nicht, werden nicht müde und machen keine Ausnahmen.
- Konsistenz: Egal ob Du alleine arbeitest oder im Team, Hooks sorgen dafür, dass bestimmte Standards immer eingehalten werden.
- Zeitersparnis: Einmal eingerichtet, erledigen Hooks wiederkehrende Aufgaben automatisch. Das spart Zeit und reduziert Fehlerquellen.
- Sicherheit: Hooks können als zusätzliche Schutzschicht innerhalb eines Vertrauensmodells dienen und verhindern, dass versehentlich kritische Änderungen ohne Absicherung durchgeführt werden. Wichtig: Hooks laufen im lokalen User-Kontext und sind keine Sicherheitsgrenze gegen kompromittierte Benutzer oder manipulierte Konfigurationen.
Für wen ist das relevant?
Hooks sind besonders wertvoll, wenn Du regelmäßig mit Claude Code arbeitest und dabei an wichtigen Projekten tätig bist. Falls Du in einer Umgebung arbeitest, in der Fehler teuer sind, etwa im Gesundheitswesen, in der Finanzbranche oder bei kritischen Infrastrukturen, bieten Hooks ein zusätzliches Sicherheitsnetz.
Aber auch bei kleineren Projekten können Hooks sinnvoll sein, wenn Du einfach mehr Kontrolle und Nachvollziehbarkeit möchtest. Ich habe in meinen eigenen Projekten festgestellt, dass selbst einfache Hooks wie automatische Backups den Unterschied machen können zwischen einer stressfreien Fehlerkorrektur und stundenlangem Debugging.
Falls Du bisher noch nie mit Hooks gearbeitet hast, keine Sorge. Diese Dokumentation führt Dich Schritt für Schritt durch alle wichtigen Konzepte, von den Grundlagen bis zu bewährten Praktiken.
Was sind Claude Hooks?
Claude Code Hooks ermöglichen es, bei bestimmten Ereignissen eigenständig zusätzliche Aufgaben zu erledigen. Etwa ein Backup anzulegen, bevor eine Datei geändert wird. Oder jede Aktion zu protokollieren, damit Du später nachvollziehen kannst, was passiert ist.
Ein Hook ist im Grunde ein kleines Programm, das Du selbst schreibst und das zu bestimmten Zeitpunkten in Deinem Arbeitsablauf mit Claude Code ausgeführt wird. Das Wort "Hook" kommt aus dem Englischen und bedeutet "Haken". Vergleichbar mit einem Aufhänger, an dem Du Deine eigenen Aktionen einhängen kannst.
Wie funktioniert das Grundprinzip?
Das Konzept ist vergleichbar mit Benachrichtigungen auf Deinem Smartphone. Wenn eine bestimmte Sache passiert, wird eine Aktion ausgelöst. Bei Claude Code sieht das so aus: Wenn Claude Code eine Datei bearbeiten möchte, prüft das System zunächst, ob Du für dieses Ereignis einen Hook eingerichtet hast. Falls ja, wird Dein Hook-Programm gestartet, bevor die eigentliche Änderung durchgeführt wird.
Ich nutze Hooks in meinen eigenen Projekten, um beispielsweise vor jeder Änderung an einer Konfigurationsdatei eine Sicherungskopie anzulegen. Das erspart mir das manuelle Kopieren und schützt mich vor versehentlichen Fehlern.
Was ist der Unterschied zwischen passiven und aktiven Hooks?
Hooks können auf zwei verschiedene Arten arbeiten. Passive Hooks beobachten nur, was passiert, und führen zusätzliche Aktionen durch, ohne den normalen Ablauf zu beeinflussen. Ein Beispiel: Du lässt Claude Code eine Datei ändern, und Dein Hook schreibt parallel dazu einen Eintrag in eine Protokoll-Datei. Die Änderung selbst läuft ganz normal ab.
Aktive Hooks hingegen können eingreifen und den Ablauf beeinflussen oder sogar stoppen. Wenn Du etwa eine Regel hast, dass bestimmte Dateien nur zu bestimmten Zeiten geändert werden dürfen, könnte ein aktiver Hook die Änderung blockieren, sobald die Regel verletzt wird. Claude Code würde dann eine Fehlermeldung erhalten.
Drei konkrete Anwendungsbeispiele
Beispiel 1: Sicherungskopien für kritische Dateien
Beim Arbeiten an einer wichtigen Konfigurationsdatei für einen Webserver kann ein Hook vor jeder Änderung eigenständig eine Kopie dieser Datei erstellen. Sollte durch die Änderung etwas kaputtgehen, existiert noch die vorherige Version, auf die Du zurückwechseln kannst. Die Wiederherstellung erfolgt entweder manuell oder durch einen entsprechend konfigurierten Hook bzw. MCP-Server.
Beispiel 2: Automatisierung bei der Content-Erstellung
Bei der Erstellung von Inhalten für Websites oder Dokumentationen gibt es oft strikte Vorgaben: Autorenprofile müssen eingehalten werden, bestimmte Strukturen sind vorgeschrieben, Links müssen korrekt gesetzt werden. Ein Hook kann diese Vorgaben automatisch prüfen und bei Abweichungen sofort eine Korrektur einleiten. So entsteht konsistenter Content, ohne dass Du jedes Detail manuell überprüfen musst.
Beispiel 3: Qualitätsprüfungen im Gesundheitswesen
Im medizinischen Bereich gibt es oft strenge Vorschriften, welche Änderungen an Patientendaten erlaubt sind. Ein Hook kann als Teil einer umfassenderen Compliance-Architektur vor jeder Änderung prüfen, ob die geplante Aktion bestimmten Regeln entspricht, und die Änderung gegebenenfalls verhindern. Hooks ersetzen dabei keine revisionssicheren Audit-Systeme, können aber eine sinnvolle Ergänzung sein.
Warum Hooks statt manueller Prozesse?
Hooks erledigen Aufgaben zuverlässig und konsistent, ohne dass Du daran denken musst. Auch KI-Anweisungen in CLAUDE.md-Dateien können durch Kontextfenster-Komprimierung verloren gehen. Ein Hook läuft hingegen bei jedem entsprechenden Ereignis, unabhängig vom Kontext. Die detaillierten Vor- und Nachteile findest Du im entsprechenden Kapitel.
Für wen sind Hooks sinnvoll?
Hooks sind besonders wertvoll, wenn Du:
- Claude Code regelmäßig für wichtige Aufgaben einsetzt.
- an Projekten arbeitest, bei denen Fehler kostspielig oder peinlich wären.
- bestimmte Regeln oder Vorschriften einhalten musst (Compliance, Datenschutz).
- Meta-Analysen über Deine Arbeitsweise erstellen möchtest (welche Fehler treten wiederholt auf?).
- einfach mehr Kontrolle darüber haben möchtest, was genau passiert.
Für gelegentliche Experimente oder beim Ausprobieren neuer Funktionen sind Hooks meist übertrieben. Der Aufwand, ein Hook-Programm zu schreiben und zu konfigurieren, lohnt sich erst, wenn die Automatisierung häufiger zum Einsatz kommt. Als Orientierung: Wenn Du eine bestimmte Maßnahme mehr als zehnmal manuell durchführen würdest, könnte sich ein Hook lohnen.
Welche Hook-Typen gibt es?
Claude Code bietet verschiedene Hook-Ereignisse, die unterschiedliche Phasen einer Arbeitssitzung abdecken. Du kannst an mehreren Stellen eingreifen, je nachdem, was Du erreichen möchtest.
Session-Hooks: Zu Beginn und am Ende
SessionStart wird ausgelöst, sobald Du eine neue Arbeitssitzung mit Claude Code startest. Das ist der Zeitpunkt, an dem Du eventuell Vorbereitungen treffen möchtest. In einem meiner Projekte nutze ich diesen Hook, um eine temporäre Protokolldatei anzulegen, in die alle Aktionen der Session geschrieben werden. So habe ich am Ende einen vollständigen Überblick, was während der Sitzung passiert ist.
SessionEnd wird ausgelöst, wenn Du die Arbeitssitzung beendest. Dieser Hook eignet sich für Aufräumarbeiten. Du könntest beispielsweise die Protokolldatei komprimieren und an einem sicheren Ort ablegen. Oder einen Zusammenfassungsbericht erstellen, der zeigt, wie viele Dateien geändert wurden.
Benutzer-Interaktions-Hooks: Wenn Du etwas eingibst
UserPromptSubmit wird jedes Mal ausgelöst, wenn Du eine Eingabe an Claude Code sendest. Das kann nützlich sein, wenn Du nachvollziehen möchtest, welche Fragen oder Anweisungen Du gestellt hast. In einem größeren Team könnte dieser Hook alle Benutzer-Eingaben in eine zentrale Datenbank schreiben, damit später erkennbar ist, wer welche Anfragen gestellt hat.
Tool-Hooks: Vor und nach Aktionen
Diese Hooks sind meist die am häufigsten genutzten, weil sie direkt bei konkreten Aktionen greifen.
PreToolUse: Bevor etwas passiert
PreToolUse wird ausgelöst, bevor Claude Code ein bestimmtes Werkzeug verwendet. Ein Werkzeug ist in diesem Kontext eine konkrete Aktion wie das Bearbeiten einer Datei, das Ausführen eines Kommandos oder das Anlegen einer neuen Datei.
Dieser Hook eignet sich besonders für Sicherungsmaßnahmen. Wenn Claude Code etwa eine Datei bearbeiten möchte, kannst Du vorher eine Kopie anlegen. Wenn ein Kommando ausgeführt werden soll, kannst Du prüfen, ob dieses Kommando in Deiner Umgebung erlaubt ist.
Ich nutze PreToolUse regelmäßig, um vor Änderungen an produktiven Konfigurationsdateien Backups zu erstellen. Das hat mich schon mehrfach vor größeren Problemen bewahrt, weil ich schnell zur vorherigen Version zurückkehren konnte.
PostToolUse: Nachdem etwas passiert ist
PostToolUse wird ausgelöst, nachdem Claude Code ein Werkzeug verwendet hat. Hier kannst Du prüfen, ob die Aktion erfolgreich war, oder zusätzliche Schritte durchführen.
Ein konkretes Beispiel aus meiner Praxis: Nach jeder Änderung an einer bestimmten Datei führe ich einen automatischen Syntax-Check durch. Der PostToolUse-Hook startet das Prüfprogramm und schreibt das Ergebnis in eine Protokolldatei. Falls die Syntax fehlerhaft ist, wird sofort eine Warnung ausgegeben.
Abschluss-Hooks: Wenn etwas gestoppt wird
Stop wird ausgelöst, wenn die Hauptsitzung gestoppt wird. Das unterscheidet sich von SessionEnd insofern, als Stop auch bei einem unerwarteten Abbruch greift.
SubagentStop wird ausgelöst, wenn ein Unter-Agent gestoppt wird. Unter-Agenten sind spezialisierte Instanzen von Claude Code, die für bestimmte Aufgaben gestartet werden können. Dieser Hook wird meist seltener benötigt, kann aber in komplexeren Setups nützlich sein.
Der Unterschied zwischen Pre und Post verstehen
Der Zeitpunkt macht den entscheidenden Unterschied. Bei PreToolUse hast Du noch die Möglichkeit, eine Aktion zu verhindern. Du kannst etwa prüfen, ob eine Datei schreibgeschützt ist, und die Änderung blockieren. Bei PostToolUse ist die Aktion bereits durchgeführt. Du kannst dann nur noch reagieren, etwa indem Du eine Benachrichtigung sendest oder eine Folgeaktion auslöst.
In meinen Projekten nutze ich PreToolUse für Sicherheitsprüfungen und Backups, PostToolUse für Protokollierung und Verifizierung. Diese Trennung hat sich bewährt, weil sie klare Verantwortlichkeiten schafft.
Mehrere Hooks kombinieren
Du kannst für ein Ereignis auch mehrere Hooks einrichten. Wenn Du etwa sowohl ein Backup als auch eine Protokollierung bei jeder Dateiänderung möchtest, können beide Hooks parallel laufen. Claude Code führt sie nacheinander aus, in der Reihenfolge, wie Du sie konfiguriert hast.
Diese Kombinationsmöglichkeit eröffnet flexible Szenarien. In einem meiner größeren Projekte laufen bei jeder Dateiänderung drei Hooks: Backup erstellen, Änderung protokollieren, Code-Qualität prüfen. Jeder Hook hat eine spezifische Aufgabe und läuft unabhängig von den anderen. Sollte einer fehlschlagen, laufen die anderen trotzdem weiter.
Wie konfiguriere ich Hooks?
Hooks werden in einer speziellen Konfigurations-Datei eingerichtet. Diese Datei teilt Claude Code mit, welche Hooks bei welchen Ereignissen ausgeführt werden sollen.
Wo liegt die Konfigurations-Datei?
Die Datei befindet sich in Deinem Home-Verzeichnis unter dem Pfad ~/.claude/settings.json. Das Tilde-Zeichen steht für Dein persönliches Verzeichnis. Unter Windows wäre das beispielsweise C:\Users\DeinName\.claude\settings.json, unter macOS oder Linux /home/DeinName/.claude/settings.json.
Diese Datei verwendet das JSON-Format. JSON ist eine strukturierte Schreibweise, um Daten zu speichern. Falls Du noch nie mit JSON gearbeitet hast: Es ist ähnlich wie eine verschachtelte Liste, bei der Du Werte bestimmten Schlüsseln zuordnest.
Grundstruktur einer Hook-Konfiguration
Eine einfache Hook-Konfiguration sieht so aus:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "/pfad/zum/backup-skript.sh",
"timeout": 30
}
]
}
]
}
}
Was bedeuten diese Einträge konkret?
- "hooks": Der Hauptbereich, in dem alle Hook-Konfigurationen stehen.
- "PreToolUse": Das Ereignis, bei dem dieser Hook ausgelöst wird.
- "matcher": "Edit": Dieser Hook gilt nur für das Edit-Werkzeug (also wenn Claude Code eine Datei bearbeitet).
- "type": "command": Der Hook ist ein externes Programm, das ausgeführt wird.
- "command": Der vollständige Pfad zum Programm oder Skript.
- "timeout": 30: Das Programm darf maximal 30 Sekunden laufen.
Was ist ein Matcher?
Der Matcher legt fest, für welche Werkzeuge der Hook gelten soll. Du kannst entweder einen spezifischen Werkzeug-Namen angeben oder einen Platzhalter verwenden.
Spezifischer Matcher:
"matcher": "Edit"
Der Hook läuft nur, wenn Claude Code das Edit-Werkzeug verwendet.
Universeller Matcher:
"matcher": "*"
Der Stern bedeutet "alle Werkzeuge". Der Hook läuft bei jeder Aktion, egal welches Werkzeug verwendet wird.
Ich empfehle, spezifische Matcher zu verwenden, wann immer möglich. Das spart Rechenzeit und macht die Konfiguration übersichtlicher. Einen universellen Matcher nutze ich nur für allgemeine Protokollierungs-Hooks, die wirklich bei jeder Aktion laufen sollen.
Timeout richtig einstellen
Der Timeout-Wert gibt an, wie lange Dein Hook maximal laufen darf, bevor er abgebrochen wird. Die Zeitangabe erfolgt in Sekunden.
Warum ist das wichtig? Wenn Dein Hook zu lange läuft, blockiert er die Arbeit mit Claude Code. Du wartest dann vielleicht unnötig lange auf eine Antwort. Ich habe in der Praxis festgestellt, dass die meisten Hooks deutlich unter 10 Sekunden brauchen. Ein Backup erstellen dauert vielleicht 2 Sekunden, eine Protokollzeile schreiben unter einer Sekunde.
Als Orientierung:
- Einfaches Logging: 5 Sekunden.
- Backup erstellen: 20 Sekunden.
- Externe Prüfung (Syntax-Check etc.): 15 Sekunden.
Wenn Dein Hook regelmäßig länger braucht, könnte das auf ein Problem hinweisen. Eventuell lädt das Skript große Datenmengen oder wartet auf eine langsame Netzwerkverbindung.
Mehrere Hooks für ein Ereignis
Du kannst für dasselbe Ereignis mehrere Hooks einrichten. Sie werden dann nacheinander ausgeführt, in der Reihenfolge, wie sie in der Konfiguration stehen.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "/pfad/zum/backup-skript.sh",
"timeout": 20
},
{
"type": "command",
"command": "/pfad/zum/log-skript.sh",
"timeout": 5
}
]
}
]
}
}
In diesem Beispiel läuft zuerst das Backup-Skript, danach das Logging-Skript. Falls das Backup-Skript fehlschlägt, läuft das Logging-Skript trotzdem. Claude Code stoppt nicht bei einem Hook-Fehler, es sei denn, der Hook gibt ein spezielles Signal zurück.
Änderungen an der Konfiguration
Wenn Du die settings.json-Datei änderst, musst Du Claude Code neu starten, damit die Änderungen wirksam werden. Claude Code liest die Konfiguration beim Start ein und behält sie für die gesamte Sitzung bei.
Ich habe anfangs öfter vergessen, Claude Code neu zu starten, und mich gewundert, warum meine Hook-Änderungen nicht funktionierten. Inzwischen ist es für mich zur Gewohnheit geworden: Konfiguration ändern, speichern, Claude Code neu starten.
Hooks für verschiedene Ereignisse kombinieren
Du kannst in derselben Konfiguration Hooks für verschiedene Ereignisse definieren:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "/pfad/zum/init-skript.sh",
"timeout": 5
}
]
}
],
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "/pfad/zum/backup-skript.sh",
"timeout": 20
}
]
}
]
}
}
Hier läuft beim Session-Start ein Initialisierungs-Skript, und vor jeder Dateibearbeitung ein Backup-Skript. So kannst Du verschiedene Automatisierungen kombinieren.
Praxisbeispiel: Automatisches Backup vor Dateiänderungen
Eines der häufigsten Einsatzszenarien für Hooks ist das automatische Anlegen von Sicherungskopien, bevor eine Datei geändert wird. Lass uns gemeinsam durchgehen, wie so ein Hook aufgebaut ist.
Das Problem, das wir lösen
Du arbeitest an einem Projekt und lässt Claude Code eine Konfigurationsdatei anpassen. Die Änderung wird durchgeführt, aber danach funktioniert etwas nicht mehr richtig. Du möchtest zur vorherigen Version zurückkehren, hast aber kein Backup erstellt.
Das ist mir selbst so oft passiert, bevor ich Hooks eingesetzt habe. Besonders ärgerlich, wenn die Änderung selbst korrekt war, aber eine unvorhergesehene Abhängigkeit Probleme verursacht hat. Mit einem automatischen Backup-Hook passiert das nicht mehr.
Was der Hook tun soll
Unser Hook soll folgende Aufgaben erledigen:
- Prüfen, ob die Datei tatsächlich existiert.
- Prüfen, ob die Datei in einem Verzeichnis liegt, das wir sichern möchten.
- Eine Kopie der Datei anlegen, bevor Claude Code sie ändert.
- Eine Meldung ausgeben, dass das Backup erstellt wurde.
Ein einfaches Backup-Skript
Hier ist ein grundlegendes Beispiel in Python. Python eignet sich gut dafür, weil es auf den meisten Systemen verfügbar ist und JSON (das Format, in dem Claude Code die Daten übergibt) direkt verarbeiten kann:
#!/usr/bin/env python3
import json
import sys
import os
import shutil
from datetime import datetime
# Welche Verzeichnisse sollen gesichert werden?
BACKUP_DIRS = ["/projekt/config", "/projekt/src"]
# Wohin sollen die Backups?
BACKUP_LOCATION = "/projekt/backups"
def should_backup(file_path):
"""Prüft, ob die Datei gesichert werden soll"""
if not os.path.isfile(file_path):
return False
for backup_dir in BACKUP_DIRS:
if file_path.startswith(backup_dir):
return True
return False
def create_backup(file_path):
"""Erstellt eine Kopie der Datei mit Error Handling"""
# Backup-Verzeichnis erstellen falls nicht vorhanden
os.makedirs(BACKUP_LOCATION, exist_ok=True)
# Mikrosekunden für Kollisionsvermeidung
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
filename = os.path.basename(file_path)
backup_name = f"{filename}.backup.{timestamp}"
backup_path = os.path.join(BACKUP_LOCATION, backup_name)
try:
shutil.copy2(file_path, backup_path)
return backup_path
except (IOError, OSError) as e:
print(f"Backup fehlgeschlagen: {str(e)}", file=sys.stderr)
return None
# Daten von Claude Code einlesen
data = json.load(sys.stdin)
# Ist es ein PreToolUse-Ereignis für Edit oder Write?
if data.get("hook_event_name") == "PreToolUse":
tool_name = data.get("tool_name", "")
if tool_name in ["Edit", "Write"]:
file_path = data.get("tool_input", {}).get("file_path", "")
if file_path and should_backup(file_path):
backup_path = create_backup(file_path)
if backup_path:
print(f"Backup erstellt: {backup_path}", file=sys.stderr)
# Erfolgreicher Exit
print(json.dumps({"suppressOutput": True}))
sys.exit(0)
Wie funktioniert das Skript?
Das Skript liest zunächst Daten von Claude Code ein. Diese Daten kommen im JSON-Format über die Standard-Eingabe (stdin). JSON ist ein strukturiertes Textformat, ähnlich wie eine verschachtelte Liste.
Dann prüft das Skript, ob es sich um ein PreToolUse-Ereignis handelt und ob das Edit- oder Write-Werkzeug verwendet wird. Falls ja, wird der Dateipfad aus den Daten extrahiert.
Die Funktion should_backup() prüft, ob die Datei tatsächlich existiert und ob sie in einem der Verzeichnisse liegt, die wir sichern möchten. Das ist sinnvoll, weil Du wahrscheinlich nicht jede Datei sichern möchtest, sondern nur bestimmte kritische Verzeichnisse.
Falls alle Bedingungen erfüllt sind, erstellt die Funktion create_backup() eine Kopie. Der Dateiname enthält einen Zeitstempel, sodass Du später erkennst, wann das Backup erstellt wurde.
Warum über stderr ausgeben?
Die Zeile print(..., file=sys.stderr) gibt die Meldung über den Standard-Fehlerkanal aus. Das ist eine Konvention bei Unix-Systemen: Normale Programmausgaben gehen über stdout, Statusmeldungen und Fehler über stderr.
Claude Code zeigt Dir Meldungen über stderr an, sodass Du sehen kannst, dass das Backup erstellt wurde. Ausgaben über stdout würden hingegen als Steuerbefehle an Claude Code interpretiert.
Die Konfiguration dazu
In Deiner settings.json würdest Du diesen Hook so einrichten:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "/projekt/scripts/backup-hook.py",
"timeout": 30
}
]
}
]
}
}
Sobald Claude Code eine Datei bearbeiten möchte, läuft das Skript, prüft die Bedingungen und erstellt gegebenenfalls ein Backup. Du musst an nichts denken. Es passiert einfach.
Erweiterungen und Variationen
Dieses Grundgerüst lässt sich auf verschiedene Arten erweitern:
- Du könntest alte Backups automatisch löschen, etwa alle älter als 30 Tage.
- Du könntest die Backups komprimieren, um Speicherplatz zu sparen.
- Du könntest die Backups an einem anderen Ort ablegen, etwa in einem Cloud-Speicher.
- Du könntest eine Benachrichtigung per E-Mail senden, wenn ein kritisches File gesichert wurde.
In meiner eigenen Praxis habe ich zusätzlich eine Funktion eingebaut, die prüft, ob sich die Datei seit dem letzten Backup tatsächlich geändert hat. Falls nicht, wird kein neues Backup erstellt. Das spart Speicherplatz bei Dateien, die mehrfach geöffnet, aber nicht verändert werden.
Praxisbeispiel: Alle Aktionen protokollieren
Manchmal möchtest Du einfach wissen, was eigentlich passiert ist. Welche Dateien wurden geändert? Wann wurde ein Kommando ausgeführt? Ein Logging-Hook zeichnet alle Aktionen auf, sodass Du später nachvollziehen kannst, was während Deiner Arbeitssitzung mit Claude Code geschehen ist.
Warum ist Logging sinnvoll?
Bei kleineren Projekten mag das überflüssig erscheinen. Du arbeitest eine Stunde, änderst drei Dateien, alles bleibt überschaubar. Bei größeren Projekten oder längeren Sitzungen verliert man jedoch schnell den Überblick. Das ist mir selbst mehrfach passiert, dass ich am Ende eines Arbeitstages nicht mehr genau wusste, welche Änderungen ich eigentlich durchgeführt hatte.
Logging hilft in mehreren Situationen. Wenn etwas nicht mehr funktioniert, kannst Du zurückblicken und sehen, welche Datei zuletzt geändert wurde. Wenn Du im Team arbeitest, kannst Du den Kollegen zeigen, was Du gemacht hast. In manchen Umgebungen, etwa im Gesundheitswesen oder bei kritischen Infrastrukturen, sind Protokolle sogar vorgeschrieben. Hooks können hier einen Baustein bilden, ersetzen aber keine vollständigen Audit-Systeme.
Ein einfaches Logging-Skript
Das folgende Skript schreibt alle wichtigen Informationen in eine Textdatei. Jedes Mal, wenn Claude Code ein Werkzeug verwendet, wird ein Eintrag mit Zeitstempel, Werkzeug-Name und Dateipfad angelegt.
#!/usr/bin/env python3
import json
import sys
import os
from datetime import datetime
# Wohin soll das Protokoll geschrieben werden?
LOG_FILE = "/projekt/logs/claude-hooks.log"
LOG_DIR = os.path.dirname(LOG_FILE)
# Daten von Claude Code einlesen
data = json.load(sys.stdin)
# Aktuelle Zeit
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Ereignistyp und Werkzeug ermitteln
event = data.get("hook_event_name", "Unbekannt")
tool = data.get("tool_name", "Unbekannt")
session_id = data.get("session_id", "")
# Falls Edit oder Write verwendet wurde, Dateipfad auslesen
file_path = ""
if tool in ["Edit", "Write"]:
file_path = data.get("tool_input", {}).get("file_path", "")
# Log-Verzeichnis erstellen falls nicht vorhanden
os.makedirs(LOG_DIR, exist_ok=True)
# Eintrag ins Protokoll schreiben
try:
with open(LOG_FILE, "a", encoding="utf-8") as log:
if file_path:
log.write(f"{timestamp} | {session_id} | {event} | {tool} | {file_path}\n")
else:
log.write(f"{timestamp} | {session_id} | {event} | {tool}\n")
print(f"Protokolliert: {event} - {tool}", file=sys.stderr)
except (IOError, OSError) as e:
print(f"Protokollierung fehlgeschlagen: {str(e)}", file=sys.stderr)
# Erfolgreicher Exit
print(json.dumps({"suppressOutput": True}))
sys.exit(0)
Wie funktioniert dieses Skript?
Das Skript liest zunächst die Daten, die Claude Code übergibt. Diese Daten enthalten Informationen darüber, welches Ereignis gerade ausgelöst wurde und welches Werkzeug verwendet wird.
Die Variable LOG_FILE gibt an, wo das Protokoll gespeichert wird. Du solltest einen Pfad wählen, der außerhalb der Projektverzeichnisse liegt, damit die Datei nicht versehentlich gelöscht oder überschrieben wird.
Mit datetime.now() holt sich das Skript die aktuelle Uhrzeit. Der Zeitstempel ist wichtig, damit Du später erkennst, wann eine bestimmte Aktion durchgeführt wurde. Falls Du etwa feststellst, dass ein Fehler seit gestern besteht, kannst Du im Protokoll nachsehen, welche Änderungen gestern stattgefunden haben.
Das Skript prüft dann, ob es sich um eine Dateiänderung handelt. Bei den Werkzeugen Edit und Write ist ein Dateipfad relevant. Bei anderen Werkzeugen, etwa einem Bash-Kommando, gibt es keinen Dateipfad, sodass nur das Ereignis und das Werkzeug protokolliert werden.
Schließlich schreibt das Skript eine Zeile in die Protokolldatei. Jede Zeile enthält den Zeitstempel, das Ereignis, das Werkzeug und gegebenenfalls den Dateipfad. Das Format ist bewusst einfach gehalten, sodass Du die Datei mit einem normalen Texteditor öffnen und durchsuchen kannst.
Die Konfiguration für den Logging-Hook
In Deiner settings.json konfigurierst Du diesen Hook so, dass er bei allen Werkzeugen ausgelöst wird:
{
"hooks": {
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "/projekt/scripts/logging-hook.py",
"timeout": 5
}
]
}
]
}
}
Der Stern als Matcher bedeutet, dass dieser Hook bei jeder Aktion läuft, egal welches Werkzeug verwendet wird. Das ist in diesem Fall sinnvoll, weil Du wahrscheinlich alles protokollieren möchtest. Der Timeout ist mit 5 Sekunden kurz gehalten, weil das Schreiben einer Zeile in eine Textdatei kaum Zeit braucht.
Sensitive Daten nicht protokollieren
Eine wichtige Überlegung beim Logging ist der Umgang mit sensiblen Informationen. Wenn Du mit Passwörtern, API-Schlüsseln oder persönlichen Daten arbeitest, sollten diese nicht im Klartext im Protokoll landen.
Ich habe in einem meiner Projekte ein zusätzliches Filter-System eingebaut, das bestimmte Dateien oder Verzeichnisse vom Protokoll ausschließt. Etwa indem ich prüfe, ob der Dateipfad ein Verzeichnis wie /secrets/ enthält. Falls ja, wird nur der Dateiname protokolliert, nicht aber der vollständige Pfad.
Erweiterungen für fortgeschrittenes Logging
Dieses Grundgerüst lässt sich auf verschiedene Arten erweitern. Du könntest das Protokoll in eine Datenbank schreiben statt in eine Textdatei. Datenbanken ermöglichen komplexere Abfragen, etwa alle Änderungen der letzten Woche oder alle Aktionen an einer bestimmten Datei.
Du könntest auch mehr Details protokollieren, etwa wie groß die geänderte Datei ist oder wie lange die Aktion gedauert hat. In größeren Teams haben wir zusätzlich den Benutzernamen mit gespeichert, sodass nachvollziehbar ist, wer welche Änderung durchgeführt hat.
Eine weitere Möglichkeit ist die automatische Bereinigung alter Protokolle. Falls das Protokoll jeden Tag größer wird, könnte ein Skript alte Einträge nach einer bestimmten Zeit löschen oder komprimieren. In meinen eigenen Projekten behalte ich Protokolle für 90 Tage, danach werden sie automatisch archiviert.
Protokollierung und Datenschutz
Wenn Du in einer Umgebung arbeitest, in der Datenschutzgesetze wie die DSGVO gelten, achte darauf, dass Deine Protokolle keine personenbezogenen Daten enthalten, es sei denn, es besteht eine klare rechtliche Grundlage dafür. In vielen Fällen reicht es, nur die Aktion und den Dateipfad zu protokollieren, nicht aber den Inhalt der Datei.
In stark regulierten Projekten lernt man recht schnell, dass an bestimmten Stellen "weniger" absolute Pflicht ist. Ein einfaches Protokoll mit Zeitstempel, Aktion und Datei genügt oft, um Nachvollziehbarkeit zu gewährleisten, ohne unnötige Daten zu speichern (da freut sich der Exil-Schwabe, Betriebswirt und Nachhaltigkeits-Karl in mir).
Welche Daten übergibt Claude Code an Hooks?
Wenn ein Hook ausgeführt wird, erhält er Informationen von Claude Code im JSON-Format. Diese Daten enthalten alles, was Du wissen musst: welches Ereignis gerade passiert, welches Werkzeug verwendet wird und welche Parameter übergeben wurden.
Was ist JSON überhaupt?
JSON steht für JavaScript Object Notation und ist eine strukturierte Schreibweise für Daten. Du kannst es Dir vorstellen wie eine Tabelle, bei der jeder Wert einen Namen hat. Ein einfaches Beispiel sieht so aus:
{
"name": "Klaus Müller",
"alter": 42,
"wohnort": "Berlin"
}
Die Elemente in den geschweiften Klammern sind die einzelnen Informationen. Jeder Eintrag besteht aus einem Namen in Anführungszeichen, einem Doppelpunkt und dem zugehörigen Wert. Diese Struktur ist für Programme leicht zu lesen und gleichzeitig für Menschen verständlich.
JSON kann auch verschachtelt sein, also Informationen in mehreren Ebenen enthalten. Das ist vergleichbar mit einem Ordner, der weitere Unterordner enthält.
Warum ist es wichtig, die JSON-Struktur zu verstehen?
Dein Hook-Skript muss die Daten auslesen, die Claude Code übergibt. Wenn Du weißt, wo welche Information steht, kannst Du gezielt darauf zugreifen. Falls Du beispielsweise nur bei Änderungen an einer bestimmten Datei reagieren möchtest, musst Du wissen, wo der Dateipfad in der JSON-Struktur zu finden ist.
Ich habe anfangs viel Zeit damit verbracht, durch Versuch und Irrtum herauszufinden, welche Daten verfügbar sind. Mittlerweile muss man sich das nicht mehr merken, denn es steht in der offiziellen Claude Code Hooks Dokumentation.
Die grundlegende Struktur der Hook-Daten
Claude Code übergibt immer eine JSON-Struktur, die mindestens diese Felder enthält:
{
"hook_event_name": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "/projekt/config/settings.json",
"old_string": "alter Wert",
"new_string": "neuer Wert"
}
}
Das Feld hook_event_name gibt an, um welches Ereignis es sich handelt. Es könnte PreToolUse, PostToolUse, SessionStart oder ein anderes der verfügbaren Ereignisse sein.
Das Feld tool_name zeigt, welches Werkzeug gerade verwendet wird. Das könnte Edit sein für eine Dateiänderung, Write für das Erstellen einer neuen Datei oder Bash für ein Kommando.
Das Feld tool_input ist wieder eine verschachtelte Struktur und enthält die Parameter, die dem Werkzeug übergeben wurden. Bei einer Dateibearbeitung steht hier der Pfad zur Datei, der alte Inhalt und der neue Inhalt.
Wichtige Felder im Detail
file_path
Dieses Feld enthält den vollständigen Pfad zur Datei, die bearbeitet werden soll. Du findest es bei den Werkzeugen Edit und Write. Der Pfad könnte beispielsweise /projekt/src/app.py lauten.
command
Bei Bash-Kommandos steht hier das eigentliche Kommando, das ausgeführt wird. Ein Beispiel wäre ls -la /projekt. Dieses Feld ist nützlich, wenn Du bestimmte Kommandos protokollieren oder einschränken möchtest.
old_string und new_string
Diese beiden Felder enthalten den alten und den neuen Text bei einer Dateiänderung. Falls Du nachvollziehen möchtest, was genau geändert wurde, kannst Du diese Werte vergleichen. In manchen Fällen kann der Text sehr lang sein, sodass Du eventuell nur einen Teil davon protokollieren möchtest.
Ein praktisches Beispiel: Daten auslesen
Das folgende Python-Skript zeigt, wie Du auf die einzelnen Felder zugreifst:
#!/usr/bin/env python3
import json
import sys
# JSON-Daten von Claude Code einlesen
data = json.load(sys.stdin)
# Ereignistyp ermitteln
event = data.get("hook_event_name", "Unbekannt")
# Werkzeug ermitteln
tool = data.get("tool_name", "Unbekannt")
# Falls es ein Edit oder Write ist, Dateipfad auslesen
if tool in ["Edit", "Write"]:
tool_input = data.get("tool_input", {})
file_path = tool_input.get("file_path", "")
print(f"Datei wird bearbeitet: {file_path}", file=sys.stderr)
# Falls es ein Bash-Kommando ist, Kommando auslesen
if tool == "Bash":
tool_input = data.get("tool_input", {})
command = tool_input.get("command", "")
print(f"Kommando wird ausgeführt: {command}", file=sys.stderr)
Die Funktion data.get("feldname", "Standardwert") ist eine sichere Methode, um auf Felder zuzugreifen. Falls das Feld nicht existiert, wird der Standardwert zurückgegeben. Das verhindert Fehler, wenn die JSON-Struktur einmal anders aussieht als erwartet.
Wo findet man welche Information?
Hier eine Übersicht, welche Felder bei welchen Werkzeugen verfügbar sind:
- Edit:
file_path,old_string,new_string. - Write:
file_path,content. - Bash:
command,timeout. - Read:
file_path.
Diese Liste ist nicht vollständig, sie zeigt jedoch die am häufigsten genutzten Felder. Falls Du genau wissen möchtest, welche Daten ein bestimmtes Werkzeug übergibt, kannst Du ein einfaches Logging-Skript schreiben, das die komplette JSON-Struktur in eine Datei schreibt. So siehst Du alle verfügbaren Felder.
JSON-Daten für Debugging ausgeben
Beim Entwickeln eines neuen Hooks kann es hilfreich sein, die vollständigen JSON-Daten zunächst in eine Datei zu schreiben. So siehst Du, welche Informationen verfügbar sind.
#!/usr/bin/env python3
import json
import sys
data = json.load(sys.stdin)
# Gesamte JSON-Struktur in Datei schreiben
with open("/tmp/hook-debug.json", "w") as f:
json.dump(data, f, indent=2)
print("JSON-Daten gespeichert", file=sys.stderr)
Dieses Skript speichert alle Daten in einer formatierten Datei, die Du dann mit einem Texteditor öffnen kannst. Ich nutze diese Methode regelmäßig, um neue Hooks zu entwickeln oder bestehende zu debuggen.
Besonderheiten bei PostToolUse
Bei PostToolUse-Hooks, also Hooks, die nach einer Aktion ausgeführt werden, enthält die JSON-Struktur zusätzlich ein Feld tool_output. Dieses Feld zeigt das Ergebnis der Aktion. Bei einem Bash-Kommando wäre das etwa die Ausgabe des Kommandos, bei einer Dateiänderung eine Bestätigung, dass die Änderung erfolgreich war.
Diese Information ist wertvoll, wenn Du prüfen möchtest, ob eine Aktion tatsächlich geklappt hat. In einem meiner Hooks nutze ich tool_output, um bei fehlgeschlagenen Kommandos eine Benachrichtigung zu senden.
Wie kann ein Hook Claude Code beeinflussen?
Hooks können nicht nur Informationen protokollieren oder Backups erstellen. Sie können auch aktiv in den Ablauf eingreifen. Ein Hook kann Claude Code mitteilen, dass eine Aktion blockiert werden soll oder dass bestimmte Meldungen nicht angezeigt werden sollen.
Die Kommunikation in beide Richtungen
Bisher haben wir Hooks kennengelernt, die Daten von Claude Code empfangen und etwas damit tun. Das ist die eine Richtung. Es gibt aber auch die andere Richtung: Dein Hook kann Claude Code eine Rückmeldung geben.
Diese Rückmeldung erfolgt wieder über JSON. Dein Hook-Skript gibt am Ende ein JSON-Objekt aus, das Claude Code verarbeitet. Je nachdem, was in diesem JSON steht, verhält sich Claude Code unterschiedlich.
suppressOutput: Meldungen unterdrücken
Normalerweise zeigt Claude Code Dir an, dass ein Hook ausgeführt wurde. Das ist hilfreich beim Entwickeln und Testen, kann aber auch ablenkend sein, wenn viele Hooks laufen. Mit suppressOutput kannst Du diese Meldungen ausblenden.
#!/usr/bin/env python3
import json
import sys
data = json.load(sys.stdin)
# Hook-Logik hier...
# Rückmeldung an Claude Code
response = {"suppressOutput": True}
print(json.dumps(response))
sys.exit(0)
Wenn Du "suppressOutput": True zurückgibst, sieht der Benutzer keine Meldung über die Hook-Ausführung. Das ist sinnvoll bei Hooks, die im Hintergrund laufen und keine Aufmerksamkeit erfordern. Etwa ein einfacher Logging-Hook, der nur still protokolliert.
Falls Du hingegen möchtest, dass der Benutzer erfährt, was passiert ist, setzt Du suppressOutput auf False oder lässt das Feld ganz weg. Dann zeigt Claude Code die Ausgaben des Hooks an.
blockExecution: Aktionen blockieren
Der wohl mächtigste Rückgabewert ist blockExecution. Damit kann Dein Hook eine Aktion verhindern, bevor sie durchgeführt wird. Das funktioniert allerdings nur bei PreToolUse-Hooks, also Hooks, die vor der Aktion ausgeführt werden.
#!/usr/bin/env python3
import json
import sys
data = json.load(sys.stdin)
# Prüfen, ob die Datei geschützt ist
tool_input = data.get("tool_input", {})
file_path = tool_input.get("file_path", "")
if "/geschuetzt/" in file_path:
# Aktion blockieren
response = {
"blockExecution": True,
"message": "Diese Datei ist schreibgeschützt und darf nicht geändert werden."
}
print(json.dumps(response))
sys.exit(0)
# Aktion erlauben
response = {"blockExecution": False}
print(json.dumps(response))
sys.exit(0)
In diesem Beispiel prüft der Hook, ob die Datei in einem geschützten Verzeichnis liegt. Falls ja, wird die Aktion blockiert. Claude Code erhält dann die Meldung, dass die Datei nicht geändert werden darf, und die Änderung wird nicht durchgeführt.
Diese Funktion ist besonders wertvoll in Umgebungen mit strengen Sicherheitsregeln. Ich habe einen solchen Hook in einem Projekt eingesetzt, bei dem bestimmte Konfigurationsdateien nur zu bestimmten Zeiten geändert werden durften. Der Hook prüfte die aktuelle Uhrzeit und blockierte Änderungen außerhalb des erlaubten Zeitfensters.
Fehlercodes und Abbrüche
Ein Hook-Skript kann auch mit einem Fehlercode enden, indem es sys.exit(1) aufruft statt sys.exit(0). Der Wert 0 bedeutet, dass alles in Ordnung ist. Jeder andere Wert signalisiert einen Fehler.
Wenn ein Hook mit einem Fehlercode endet, zeigt Claude Code eine Warnung an. Die geplante Aktion wird jedoch trotzdem durchgeführt, es sei denn, Du hast zusätzlich blockExecution auf True gesetzt.
#!/usr/bin/env python3
import json
import sys
data = json.load(sys.stdin)
try:
# Hook-Logik...
pass
except Exception as e:
# Fehler aufgetreten
print(f"Hook-Fehler: {str(e)}", file=sys.stderr)
sys.exit(1)
# Alles OK
print(json.dumps({"suppressOutput": True}))
sys.exit(0)
Dieser Aufbau ist defensiv programmiert. Falls während der Hook-Ausführung etwas schiefgeht, wird der Fehler protokolliert und das Skript bricht ab. Claude Code erfährt davon und kann den Benutzer informieren.
Eine eigene Nachricht ausgeben
Du kannst im Rückgabe-JSON auch ein message-Feld hinzufügen. Diese Nachricht wird dann dem Benutzer angezeigt.
response = {
"suppressOutput": False,
"message": "Backup erstellt in /backups/config_20231215.json"
}
print(json.dumps(response))
Das ist nützlich, wenn Du dem Benutzer mitteilen möchtest, was der Hook getan hat. Etwa wo das Backup gespeichert wurde oder dass eine Prüfung erfolgreich war.
Wann welcher Rückgabewert sinnvoll ist
Die Wahl des Rückgabewerts hängt davon ab, was Dein Hook tun soll. Hier ein paar Orientierungspunkte:
- Stilles Logging:
suppressOutput: True, keine weitere Rückmeldung nötig. - Backup mit Bestätigung:
suppressOutput: False,messagemit Pfad zum Backup. - Sicherheitsprüfung:
blockExecution: Truefalls Regel verletzt, sonstFalse. - Fehlende Berechtigung:
blockExecution: True,messagemit Erklärung.
In meinen eigenen Projekten nutze ich suppressOutput für etwa 80 Prozent der Hooks. Die meisten Hooks laufen einfach im Hintergrund und protokollieren still. Nur bei kritischen Aktionen oder Sicherheitsprüfungen gebe ich explizite Meldungen aus.
Vorsicht mit blockExecution
Das Blockieren von Aktionen ist ein scharfes Schwert. Falls Dein Hook einen Fehler hat und fälschlicherweise alle Aktionen blockiert, kannst Du nicht mehr mit Claude Code arbeiten. Teste solche Hooks gründlich, bevor Du sie produktiv einsetzt.
Ich habe einmal einen Hook geschrieben, der alle Dateiänderungen blockieren sollte, wenn keine Internetverbindung besteht. Der Hook hatte einen Logikfehler und blockierte auch bei bestehender Verbindung. Ich musste die Hook-Konfiguration manuell aus der settings.json entfernen, um wieder arbeiten zu können.
Kombination mehrerer Rückgabewerte
Du kannst mehrere Felder gleichzeitig zurückgeben. Etwa eine Aktion blockieren und gleichzeitig eine Nachricht anzeigen:
response = {
"blockExecution": True,
"suppressOutput": False,
"message": "Änderungen an dieser Datei sind nur zwischen 9 und 17 Uhr erlaubt."
}
print(json.dumps(response))
Diese Kombination ist benutzerfreundlich. Der Benutzer erfährt nicht nur, dass die Aktion blockiert wurde, sondern auch warum. Er kann dann entsprechend reagieren.
Wann lohnen sich Hooks wirklich?
Hooks sind ein mächtiges Werkzeug, aber nicht in jeder Situation die richtige Wahl. Es gibt Situationen, in denen Hooks enorm helfen, und andere, in denen sie mehr Aufwand verursachen als sie einsparen.
Die klaren Vorteile von Hooks
Der größte Vorteil liegt in der Zuverlässigkeit. Ein Hook läuft jedes Mal, wenn das entsprechende Ereignis eintritt. Du kannst es nicht vergessen, NIEMAND im Team vergisst je etwas, auch nicht die neue Junior-Dev-Person, die gerade eingestellt wurde. Das ist besonders wertvoll bei Aufgaben, die Du regelmäßig durchführen solltest, aber die leicht in Vergessenheit geraten.
Ich beobachte recht häufig, dass viele Menschen in Claude Code arbeiten, aber so gut wie nie oder nur sporadisch mal eine Datei vor einer größeren Änderung sichern. Verständlich, denn in der Hektik des Alltags denkt man einfach nicht dran, oder die Änderung erscheint trivial genug. Genau hier greifen Hooks zuverlässig ein, ohne dass man selbst noch daran denken muss.
Ein weiterer Vorteil ist die Konsistenz. Wenn zehn Personen im Team arbeiten und jede Person Backups auf ihre eigene Art erstellt, entstehen unterschiedliche Strukturen. Ein Hook sorgt dafür, dass alle Backups gleich aussehen, am gleichen Ort gespeichert werden und die gleichen Namenskonventionen haben.
Hooks skalieren gut. Ob Du fünf Änderungen pro Tag machst oder fünfzig, der Hook läuft zuverlässig. Der Aufwand bleibt gleich, während der Nutzen mit der Anzahl der Aktionen steigt. Bei größeren Projekten mit vielen Änderungen zahlt sich das besonders aus.
Nachteile und Herausforderungen
Hooks erfordern initialen Aufwand. Du musst ein Skript schreiben, testen und konfigurieren. Das dauert eben seine Zeit: Mal ein paar Minuten, mal sitzt man eben ein paar Stunden dran. Für eine einmalige Aktion lohnt sich das meist nicht.
Hooks können die Arbeit verlangsamen. Jeder Hook braucht Zeit zum Ausführen. Wenn Du zehn Hooks konfiguriert hast, die bei jeder Dateiänderung laufen, und jeder Hook eine Sekunde braucht, wartest Du zehn Sekunden. Das addiert sich über den Tag.
Ich hatte in einem Projekt einen Hook, der bei jeder Änderung eine externe API abfragte, um zu prüfen, ob die geänderte Datei in einem anderen System verwendet wird. Der Hook brauchte drei bis fünf Sekunden, je nach Netzwerk. Das war zu langsam. Ich habe den Hook später so umgebaut, dass er nur bei Änderungen in bestimmten Verzeichnissen läuft, was die Verzögerung deutlich reduzierte.
Fehlerhafte Hooks können Probleme verursachen. Falls ein Hook abstürzt oder eine Aktion fälschlicherweise blockiert, stehst Du unter Umständen vor einem Hindernis. Das Debugging kann aufwendig sein, besonders wenn Du mit Shell-Skripten oder komplexen Programmiersprachen arbeitest.
Wann Hooks wirklich sinnvoll sind
Hooks lohnen sich besonders in diesen Situationen:
- Wiederholte Aufgaben: Wenn Du dieselbe Sicherungsmaßnahme oder Prüfung immer wieder durchführen musst.
- Compliance-Anforderungen: Wenn gesetzliche oder betriebliche Vorschriften lückenlose Protokolle verlangen.
- Kritische Projekte: Wenn Fehler schwerwiegende Folgen haben und Backups unverzichtbar sind.
- Team-Arbeit: Wenn mehrere Personen nach denselben Standards arbeiten sollen.
- Langfristige Projekte: Wenn Du über Wochen oder Monate an etwas arbeitest und Nachvollziehbarkeit wichtig ist.
In regulierten Branchen wie dem Gesundheitswesen oder der Finanzindustrie können Hooks als Teil einer umfassenderen Compliance-Strategie sehr wertvoll sein. Die Anforderung, Änderungen nachvollziehbar zu dokumentieren, rechtfertigt den Aufwand der Einrichtung. Wichtig: Hooks allein erfüllen keine regulatorischen Anforderungen wie DSGVO, MDR oder BaFin-Vorgaben, können aber ein sinnvoller Baustein sein.
Wann Hooks übertrieben sind
Hooks sind meist nicht die richtige Wahl in diesen Fällen:
- Einmalige Experimente: Wenn Du etwas einmal ausprobierst und danach nie wieder brauchst.
- Sehr einfache Projekte: Wenn das gesamte Projekt aus drei Dateien besteht und Du alleine daran arbeitest.
- Lernprojekte: Wenn Du gerade dabei bist, eine neue Technologie zu lernen, und viele Fehler machst.
- Schnelle Prototypen: Wenn Du in kurzer Zeit eine Idee testen möchtest und Perfektion keine Rolle spielt.
Die Abwägung treffen
Eine Faustregel, die ich für mich entwickelt habe: Wenn ich eine bestimmte Aktion mehr als zehnmal manuell durchführen würde, denke ich über einen Hook nach. Wenn die Aktion kritisch ist, setze ich die Schwelle niedriger an.
Ein weiteres Kriterium ist die Fehlertoleranz. Wenn ein vergessenes Backup katastrophale Folgen hätte, rechtfertigt das einen Hook. Wenn ein Fehler harmlos ist und leicht korrigiert werden kann, verzichte ich darauf.
Iterative Einführung von Hooks
Du musst nicht sofort ein komplexes Hook-System aufbauen. Ich empfehle, mit einem einzigen, einfachen Hook zu starten. Etwa einem Logging-Hook, der nur protokolliert, was passiert. Wenn das gut funktioniert, kannst Du weitere Hooks hinzufügen.
Dieser iterative Ansatz hat mehrere Vorteile. Du lernst die Technologie schrittweise kennen. Du siehst schnell erste Ergebnisse. Und falls etwas schiefgeht, hast Du nur einen Hook zu überprüfen, nicht zehn.
In meinen Projekten habe ich meistens mit einem SessionStart-Hook begonnen, der einfach nur ein Protokoll anlegt. Danach kam ein PreToolUse-Hook für Backups. Erst später habe ich komplexere Hooks für Sicherheitsprüfungen oder Performance-Tracking hinzugefügt.
Performance im Blick behalten
Je mehr Hooks Du einrichtest, desto wichtiger wird es, auf die Performance zu achten. Ein Hook, der zwei Sekunden braucht, fällt kaum auf. Fünf Hooks, die je zwei Sekunden brauchen, bedeuten zehn Sekunden Wartezeit pro Aktion. Das kann störend sein.
Ich überwache die Ausführungszeiten meiner Hooks und optimiere diejenigen, die zu langsam sind. Manchmal reicht es schon, einen Hook nur für bestimmte Dateitypen oder Verzeichnisse laufen zu lassen, statt für alle Aktionen.
Das Verhältnis von Aufwand zu Nutzen
Letztlich geht es um die Frage: Überwiegt der Nutzen den Aufwand? Bei einem Backup-Hook ist die Antwort für mich klar ja. Der initiale Aufwand von vielleicht zwei Stunden zahlt sich bereits nach wenigen Tagen aus. Bei einem Hook, der eine exotische Sonderprüfung durchführt, die nur einmal im Monat relevant ist, wäre die Antwort meist nein.
Bewährte Praktiken für robuste Hooks
Die Entwicklung von Hooks folgt einigen bewährten Mustern, die ich über mehrere Projekte hinweg gelernt habe. Diese Praktiken helfen dabei, Hooks zu schreiben, die zuverlässig laufen, wartbar bleiben und keine unerwarteten Probleme verursachen.
Keep it simple: Einfachheit geht vor
Der wichtigste Grundsatz lautet: Halte Deine Hooks so einfach wie möglich. Ein Hook sollte eine klar definierte Aufgabe erfüllen und nichts anderes. Wenn Du merkst, dass ein Hook mehrere verschiedene Dinge tut, teile ihn lieber in mehrere separate Hooks auf.
Ganz zu Beginn hatte ich einen UNIVERSAL-Hook, der gleichzeitig ein Backup erstellen, die Datei auf Syntaxfehler prüfen und eine Benachrichtigung per E-Mail versenden sollte. Das Skript wurde schnell unübersichtlich. Als später ein Fehler auftrat, brauchte ich eine Stunde, um herauszufinden, welcher Teil des Hooks das Problem verursachte. Inzwischen nutze ich drei separate Hooks für diese Aufgaben.
Defensive Fehlerbehandlung einbauen
Dein Hook sollte davon ausgehen, dass Dinge schiefgehen können. Dateien existieren eventuell nicht, Verzeichnisse haben keine Schreibrechte, Netzwerkverbindungen brechen ab. Gute Hooks fangen solche Fehler ab und reagieren sinnvoll darauf.
#!/usr/bin/env python3
import json
import sys
import os
data = json.load(sys.stdin)
try:
tool_input = data.get("tool_input", {})
file_path = tool_input.get("file_path", "")
# Prüfen, ob die Datei existiert
if not file_path or not os.path.exists(file_path):
print("Datei nicht gefunden, kein Backup erstellt", file=sys.stderr)
print(json.dumps({"suppressOutput": True}))
sys.exit(0) # Kein Fehler, einfach nichts tun
# Backup erstellen...
except Exception as e:
# Fehler protokollieren, aber nicht blockieren
print(f"Hook-Fehler: {str(e)}", file=sys.stderr)
print(json.dumps({"suppressOutput": False}))
sys.exit(0) # Weiter arbeiten trotz Fehler
Dieser Hook prüft zunächst, ob die Datei überhaupt existiert. Falls nicht, bricht er ab, ohne einen Fehler zu melden. Das ist sinnvoll, weil es Situationen gibt, in denen noch keine Datei existiert, etwa beim Erstellen einer neuen Datei.
Testen vor dem produktiven Einsatz
Bevor Du einen Hook in Deinem echten Projekt einsetzt, teste ihn gründlich in einer Testumgebung. Erstelle ein separates Testverzeichnis, richte den Hook dort ein und probiere verschiedene Szenarien durch.
Ich teste meine Hooks üblicherweise mit diesen Szenarien:
- Normale Dateiänderung: Funktioniert der Hook wie erwartet?.
- Nicht existierende Datei: Stürzt der Hook ab oder behandelt er das sauber?.
- Sehr große Datei: Dauert der Hook zu lange oder geht ihm der Speicher aus?.
- Fehlende Berechtigungen: Was passiert, wenn das Zielverzeichnis nicht beschreibbar ist?.
Diese Tests haben mir mehrfach geholfen, Probleme zu finden, bevor sie in der echten Arbeit auftraten.
Timeouts realistisch setzen
Setze den Timeout-Wert nicht zu knapp, aber auch nicht übertrieben großzügig. Ein guter Richtwert ist das Doppelte der erwarteten Ausführungszeit. Wenn Dein Hook normalerweise drei Sekunden braucht, setze den Timeout auf sechs Sekunden.
Falls ein Hook regelmäßig den Timeout erreicht, ist das ein Zeichen, dass etwas nicht stimmt. Möglicherweise ist der Hook zu komplex oder greift auf langsame externe Ressourcen zu. Optimiere den Hook oder überdenke sein Design.
Dokumentiere, was der Hook tut
Schreibe direkt am Anfang Deines Hook-Skripts einen Kommentar, der erklärt, was der Hook tut, bei welchen Ereignissen er läuft und welche Voraussetzungen er hat. Das hilft Dir selbst, wenn Du Monate später an den Hook zurückkehrst, und es hilft anderen im Team.
#!/usr/bin/env python3
"""
Backup-Hook für kritische Konfigurationsdateien
Ereignis: PreToolUse (Edit, Write)
Funktion: Erstellt ein Backup aller Dateien in /projekt/config/
Speicherort: /projekt/backups/
Namensschema: dateiname.backup.YYYYMMDD_HHMMSS
Voraussetzungen:
- Schreibrechte in /projekt/backups/
- Python 3.6 oder höher
"""
import json
import sys
# ... Rest des Skripts
Diese wenigen Zeilen können später viel Zeit sparen. Ich habe schon öfter vor einem alten Hook-Skript gestanden und mich gefragt, warum ich es damals so geschrieben habe. Gute Dokumentation beantwortet solche Fragen sofort.
Sensible Daten schützen
Falls Dein Hook mit sensiblen Informationen arbeitet, etwa Passwörtern oder API-Schlüsseln, schreibe diese niemals direkt ins Skript. Nutze stattdessen Umgebungsvariablen oder separate Konfigurationsdateien, die außerhalb des Projekts liegen.
Ein Hook, der ein Backup in einen Cloud-Speicher hochlädt, sollte die Zugangsdaten nicht im Klartext enthalten. Falls das Skript versehentlich in ein öffentliches Repository gelangt, wären die Zugangsdaten kompromittiert.
Performance im Blick behalten
Hooks sollten schnell sein. Alles über zwei Sekunden Ausführungszeit fällt dem Benutzer auf und kann störend sein. Wenn Dein Hook länger braucht, überlege, ob Du ihn optimieren kannst.
Manchmal reicht es schon, den Hook nur für bestimmte Dateitypen oder Verzeichnisse laufen zu lassen. Ein Backup-Hook muss nicht bei jeder Textdatei laufen, sondern nur bei Konfigurationsdateien. Eine entsprechende Filterung im Matcher oder im Skript selbst kann die Ausführungszeit deutlich reduzieren.
Vorsicht beim Universal-Matcher
Der Matcher "*" führt einen Hook bei jeder einzelnen Aktion aus, egal welches Werkzeug Claude Code verwendet. Das erscheint zunächst praktisch, kann aber mehrere Probleme verursachen.
Erstens die Performance: Wenn der Hook bei jedem Bash-Kommando, jeder Dateiänderung und jeder Suche läuft, addiert sich die Wartezeit schnell. Ein Hook, der eine Sekunde braucht, bedeutet bei hundert Aktionen hundert Sekunden zusätzliche Wartezeit.
Zweitens die Sicherheit: Ein Logging-Hook mit Universal-Matcher protokolliert eventuell sensible Daten. Wenn Claude Code etwa ein Passwort temporär in eine Konfigurationsdatei schreibt oder einen API-Schlüssel in einem Bash-Kommando verwendet, landet das im Protokoll. Falls das Protokoll später in falsche Hände gerät, sind diese Daten kompromittiert.
Drittens das Debugging: Wenn ein Hook bei jeder Aktion läuft und plötzlich ein Fehler auftritt, ist es schwierig herauszufinden, welche spezifische Aktion das Problem verursacht hat. Ein gezielter Matcher wie "Edit" oder "Write" macht Fehler leichter nachvollziehbar.
Ich setze den Universal-Matcher nur für sehr einfache Hooks ein, etwa für ein minimales Logging, das nur Ereignistyp und Zeitstempel protokolliert. Für alle anderen Fälle bevorzuge ich spezifische Matcher.
Die Regel der kleinen Schritte
Wenn Du einen neuen Hook entwickelst, baue ihn schrittweise auf. Starte mit einem minimalen Skript, das nur eine Meldung ausgibt. Teste, ob das funktioniert. Dann füge die eigentliche Logik hinzu. Teste wieder. Füge Fehlerbehandlung hinzu. Teste erneut.
Dieser iterative Ansatz verhindert, dass Du am Ende ein komplexes Skript hast, das an zehn Stellen gleichzeitig fehlerhaft sein könnte. Bei jedem Schritt weißt Du genau, dass alles bis hierher funktioniert. Das macht Fehler leichter zu finden.
Ich nutze diese Methode bei allen neuen Hooks. Selbst wenn ich denke, dass ich die Logik im Kopf habe, starte ich mit einem minimalen Skript und baue es dann aus. Das hat mir schon mehrfach geholfen, Fehler früh zu erkennen.
Versionierung für Hook-Skripte
Behandle Deine Hook-Skripte wie Code und versioniere sie. Falls Du Git oder ein anderes Versionskontrollsystem nutzt, speichere Deine Hooks dort. So kannst Du Änderungen nachvollziehen und bei Bedarf zu einer früheren Version zurückkehren.
Ich speichere meine Hooks in einem separaten Repository, das ich mit dem Hauptprojekt verknüpfe. So kann ich Hooks über mehrere Projekte hinweg wiederverwenden und Verbesserungen zentral pflegen.
Logging nicht übertreiben
Hooks sollten protokollieren, was sie tun, aber nicht zu ausführlich. Eine Zeile pro Ausführung reicht meistens. Falls Du jedes Detail protokollierst, wird das Logfile schnell riesig und unübersichtlich.
Ein gutes Logging-Format enthält Zeitstempel, Ereignis, Aktion und gegebenenfalls den betroffenen Dateipfad. Mehr braucht es selten. Bei Fehlern darf das Logging natürlich ausführlicher sein, damit Du den Fehler nachvollziehen kannst.
tl;dr: Claude Code Hooks ist etwas für (im positivsten Sinne) faule, effiziente Menschen mit einem großen Hang für smarte Prozesse.
Ich hoffe, Du konntest einen ersten Überblick über Claude Code Hooks erhalten. Von den Grundlagen über praktische Beispiele bis hin zu bewährten Praktiken.
Kurz & knapp:
Hooks sind im Kern ein Automatisierungswerkzeug. Sie führen definierte Aktionen zu bestimmten Zeitpunkten aus, ohne dass Du daran denken musst. Das macht sie besonders wertvoll für wiederkehrende Aufgaben wie Backups, Protokollierung oder Sicherheitsprüfungen.
Die Stärke von Hooks liegt in ihrer Zuverlässigkeit. Ein gut konfigurierter Hook läuft jedes Mal, konsistent und vorhersagbar. Das unterscheidet sie von manuellen Prozessen oder von Anweisungen in CLAUDE.md-Dateien, die durch Kontextkomprimierung verloren gehen können.
Gleichzeitig erfordern Hooks einen bewussten Umgang. Sie können die Arbeit verlangsamen, wenn sie zu komplex sind. Sie können Probleme verursachen, wenn sie fehlerhaft sind. Die Kunst besteht darin, das richtige Maß zu finden.
Der erste Schritt: Klein anfangen
Falls Du jetzt überlegst, Hooks in Deinen Projekten einzusetzen, empfehle ich, mit einem einzigen, einfachen Hook zu starten. Ein Logging-Hook, der nur protokolliert, welche Aktionen Claude Code durchführt, ist ein guter Einstieg. Er ist schnell implementiert, hat kaum Performance-Impact und gibt Dir sofort einen Mehrwert.
Wenn dieser erste Hook läuft und Du siehst, dass er funktioniert, kannst Du weitere hinzufügen. Vielleicht einen Backup-Hook für besonders wichtige Dateien. Oder einen Hook, der vor Änderungen an Produktionssystemen eine Bestätigung verlangt.
Ich bin in meinen eigenen Projekten genau diesen Weg gegangen. Der erste Hook war ein simpler SessionStart-Hook, der nur eine Zeile in eine Logdatei schrieb. Inzwischen habe ich ein ganzes System von Hooks aufgebaut, aber ich habe jeden einzeln hinzugefügt und getestet, bevor ich den nächsten implementiert habe.
Realistische Erwartungen setzen
Hooks sind kein Allheilmittel. Sie ersetzen nicht eine saubere Projektstruktur, gründliches Testen oder durchdachte Prozesse. Sie sind ein zusätzliches Werkzeug, das bestimmte Aufgaben einfacher und zuverlässiger macht.
Erwarte nicht, dass ein Hook alle Probleme löst. Er kann Dich nicht davor bewahren, einen Fehler zu machen. Er kann aber dafür sorgen, dass Du nach einem Fehler schnell zur vorherigen Version zurückkehren kannst, weil ein Backup existiert.
In regulierten Umgebungen, etwa im Gesundheitswesen oder der Finanzbranche, können Hooks als Teil einer Compliance-Architektur sehr wertvoll sein. Sie helfen dabei, Nachvollziehbarkeit und Kontrolle zu gewährleisten, ersetzen aber keine vollständigen Audit-Systeme mit Rollenmodellen, Zugriffskontrollen und Unveränderbarkeit. In kleineren Projekten oder Experimenten können sie übertrieben sein.
Wann Du auf Hooks verzichten kannst
Nicht jedes Projekt braucht Hooks. Bei sehr einfachen Projekten, bei einmaligen Experimenten oder beim Lernen neuer Technologien stehen Hooks eventuell mehr im Weg, als sie helfen.
Ich nutze Hooks nicht bei allen meinen Projekten. Bei schnellen Prototypen oder beim Ausprobieren neuer Ideen verzichte ich bewusst darauf. Der Overhead wäre größer als der Nutzen. Erst wenn ein Projekt eine gewisse Reife erreicht und ich regelmäßig daran arbeite, richte ich Hooks ein.
Die Balance zwischen Automatisierung und Kontrolle
Hooks nehmen Dir Arbeit ab, aber sie nehmen Dir auch ein Stück Kontrolle. Du musst darauf vertrauen, dass der Hook das Richtige tut. Deshalb ist es wichtig, Hooks gründlich zu testen und zu dokumentieren.
Dein Startpunkt: Der minimale Logging-Hook
Falls Du jetzt direkt loslegen möchtest, hier ist ein minimaler Logging-Hook, den Du als Basis nutzen kannst:
#!/usr/bin/env python3
import json
import sys
from datetime import datetime
data = json.load(sys.stdin)
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
event = data.get("hook_event_name", "Unbekannt")
tool = data.get("tool_name", "Unbekannt")
with open("/tmp/claude-hooks.log", "a") as log:
log.write(f"{timestamp} | {event} | {tool}\n")
print(json.dumps({"suppressOutput": True}))
sys.exit(0)
Speichere dieses Skript, mache es ausführbar, konfiguriere es in Deiner settings.json und starte Claude Code neu. Danach hast Du einen funktionierenden Hook, der alle Aktionen protokolliert. Von dort aus kannst Du experimentieren und erweitern.
Ausblick: Hooks als Teil einer robusten Arbeitsumgebung
Hooks sind ein Baustein in einer umfassenderen Strategie für zuverlässige Software-Entwicklung. Zusammen mit Versionskontrolle, automatisierten Tests und guten Entwicklungsprozessen bilden sie ein Sicherheitsnetz.
Die Technologie entwickelt sich weiter. Eventuell werden zukünftige Versionen von Claude Code zusätzliche Hook-Typen oder erweiterte Funktionen bieten. Die Grundprinzipien bleiben jedoch wahrscheinlich gleich: Definiere Ereignisse, reagiere darauf, automatisiere wiederkehrende Aufgaben.
Claude Code Hooks geben Dir die Möglichkeit, Deinen Arbeitsablauf nach Deinen eigenen Bedürfnissen zu gestalten. Du entscheidest, welche Sicherheitsmaßnahmen wichtig sind, welche Protokolle Du brauchst und welche Prüfungen durchgeführt werden sollen.
Der initiale Aufwand mag zunächst abschreckend wirken. Die langfristigen Vorteile überwiegen jedoch in vielen Projekten deutlich. Ein zuverlässiges Backup-System, lückenlose Protokolle und automatische Sicherheitsprüfungen zahlen sich über die Zeit aus (bei mir sind ein gutes Dutzend unterschiedliche Hook-Funktionen in jedem Projekt mittlerweile Standard.)
Ich hoffe, dieser Überblick hat Dir geholfen, Hooks besser zu verstehen und einzuschätzen, ob sie für Deine Projekte sinnvoll sind. Falls Du Dich für die Einrichtung entscheidest, wünsche ich Dir viel Erfolg beim Experimentieren.
Liebe Grüße, Dein Karl