Was sind Hooks?
Hooks sind Shell-Befehle, die Claude Code automatisch zu bestimmten Zeitpunkten ausführt — unabhängig davon, was Claude gerade macht. Sie laufen im Hintergrund und können:
- Jeden Bash-Befehl vor der Ausführung loggen oder blockieren
- Nach jeder Dateiänderung automatisch linting starten
- Am Session-Ende einen Git-Commit erstellen
- Bei jedem Tool-Aufruf Metriken sammeln
Hooks sind seit Anfang 2026 offiziell dokumentiert und in allen Claude Code Versionen ab 1.x verfügbar. In Deutschland sind sie kaum bekannt — die meisten Nutzer kennen nur CLAUDE.md und Tool-Konfiguration.
Die vier Hook-Typen
| Hook-Typ | Wann ausgeführt | Typischer Einsatz |
|---|---|---|
| PreToolUse | Bevor Claude ein Tool aufruft (Bash, Edit, Write…) | Logging, Validierung, Blockierung gefährlicher Befehle |
| PostToolUse | Nachdem ein Tool-Aufruf abgeschlossen ist | Linting, Tests, Auto-Commit nach Dateiänderungen |
| Stop | Wenn Claude eine Antwort beendet hat | Session-Cleanup, Zusammenfassung, Heartbeat-Reset |
| Notification | Bei internen Claude-Benachrichtigungen | Desktop-Alerts, Telegram-Pings, Slack-Nachrichten |
Hooks konfigurieren
Hooks werden in der settings.json konfiguriert. Je nach Scope gibt es drei Speicherorte:
# 1. Global (gilt für alle Projekte)
~/.claude/settings.json
# 2. Projekt-lokal (gilt nur im aktuellen Projekt)
.claude/settings.json
# 3. Projekt-lokal, nicht in Git (sensitive Hooks)
.claude/settings.local.json
Die Grundstruktur einer Hook-Konfiguration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo \"Claude führt Bash aus: $CLAUDE_TOOL_INPUT\" >> /tmp/bash.log"
}
]
}
]
}
}
Das matcher-Feld akzeptiert Tool-Namen ("Bash", "Edit", "Write") oder "*" für alle Tools. Der Befehl bekommt Umgebungsvariablen mit Kontext:
| Variable | Inhalt |
|---|---|
$CLAUDE_TOOL_NAME | Name des aufgerufenen Tools (z.B. "Bash") |
$CLAUDE_TOOL_INPUT | JSON mit den Tool-Parametern |
$CLAUDE_SESSION_ID | Aktuelle Session-ID |
$CLAUDE_CWD | Aktuelles Arbeitsverzeichnis |
7 praktische Hook-Beispiele
1. Vollständiges Bash-Logging
Jeder Bash-Befehl, den Claude ausführt, wird mit Timestamp in eine Log-Datei geschrieben. Unverzichtbar für Audits und Debugging.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "echo \"[$(date -u +%H:%M:%S)] BASH: $CLAUDE_TOOL_INPUT\" >> /logs/agent.log"
}]
}]
}
}
2. Auto-Lint nach Dateiänderungen
Nach jedem Edit oder Write führt Claude automatisch ESLint aus. Keine manuellen Lint-Befehle mehr.
{
"hooks": {
"PostToolUse": [{
"matcher": "Edit",
"hooks": [{
"type": "command",
"command": "cd $CLAUDE_CWD && npx eslint --fix $(echo $CLAUDE_TOOL_INPUT | jq -r '.file_path') 2>&1 || true"
}]
}]
}
}
3. Gefährliche Befehle blockieren
Exit-Code 2 aus einem PreToolUse-Hook blockiert den Tool-Aufruf vollständig. Nützlich um destruktive Befehle zu verhindern.
# hook-guard.sh
#!/bin/bash
CMD=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.command // ""')
# rm -rf auf wichtige Verzeichnisse verhindern
if echo "$CMD" | grep -qE "rm -rf.*(home|root|var|etc)"; then
echo "BLOCKED: Gefährlicher rm-Befehl verweigert" >&2
exit 2
fi
# git push --force auf main/master verhindern
if echo "$CMD" | grep -qE "git push.+--force.+(main|master)"; then
echo "BLOCKED: Force-Push auf main/master verboten" >&2
exit 2
fi
exit 0
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "bash /home/user/hooks/hook-guard.sh"
}]
}]
}
}
4. Auto-Commit bei Session-Ende
Der Stop-Hook wird aufgerufen wenn Claude fertig ist. Perfekt für automatische Commits nach jeder Arbeitssession.
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "cd $CLAUDE_CWD && git add -A && git diff --staged --quiet || git commit -m '[auto] Claude Session $(date +%Y-%m-%d-%H%M)'"
}]
}]
}
}
5. Tests nach jedem Schreibvorgang
Nach jedem Write auf Test-Dateien läuft pytest automatisch. Claude sieht das Ergebnis und kann sofort iterieren.
# test-runner-hook.sh
#!/bin/bash
FILE=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.file_path // ""')
# Nur für Python-Dateien
if [[ "$FILE" == *.py ]]; then
cd $CLAUDE_CWD
python -m pytest tests/ -x -q --tb=short 2>&1 | tail -20
fi
{
"hooks": {
"PostToolUse": [{
"matcher": "Write",
"hooks": [{
"type": "command",
"command": "bash /home/user/hooks/test-runner-hook.sh"
}]
}]
}
}
6. Telegram-Benachrichtigung bei Abschluss
Nach jeder Claude-Antwort (Stop-Hook) wird eine Telegram-Nachricht geschickt. Ideal für lang laufende Agentenaufgaben.
# telegram-notify.sh
#!/bin/bash
BOT_TOKEN="$TELEGRAM_BOT_TOKEN"
CHAT_ID="$TELEGRAM_CHAT_ID"
MSG="✅ Claude fertig in $CLAUDE_CWD — $(date +%H:%M)"
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=${MSG}" > /dev/null
7. Heartbeat-System für autonome Agenten
In Multi-Agent-Systemen muss jeder Agent regelmäßig seinen Status melden. Ein Stop-Hook aktualisiert automatisch die Heartbeat-Datei.
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "python3 -c \"import json,time; open('/tmp/agent_heartbeat.json','w').write(json.dumps({'epoch':int(time.time()),'status':'idle','session':'$CLAUDE_SESSION_ID'}))\""
}]
}]
}
}
Sicherheit und Exit-Codes
Hooks haben direkten Einfluss auf Claude Code. Die wichtigsten Regeln:
0 — Hook erfolgreich, Claude fährt fort
1 — Hook-Fehler, wird an Claude gemeldet (aber Claude fährt fort)
2 — Tool-Aufruf wird BLOCKIERT (nur PreToolUse)
- Hooks laufen mit deinen Berechtigungen — sie können alles, was du im Terminal kannst
- Keine Schleifen — ein Hook darf nicht Claude triggern, der wieder den Hook triggert
- Timeout: Hooks haben ein Standard-Timeout von 60 Sekunden
- Sensitive Hooks (mit API-Keys) in
settings.local.jsonlegen — nicht in Git einchecken - Stdout des Hooks wird Claude als Kontext übergeben — nutze es für Feedback
Hooks + CLAUDE.md kombinieren
Die mächtigste Kombination: Hooks übernehmen deterministisches Verhalten, CLAUDE.md definiert das Reasoning. Beispiel aus unserer Produktions-Infrastruktur:
# CLAUDE.md (Verhaltensebene)
## Commit-Regeln
- Nach jedem abgeschlossenen Task committen
- Format: [rolle] task-N: kurze Beschreibung
- Niemals mehr als 5 Dateien pro Commit
# settings.json (Enforcement-Ebene)
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "bash ~/.claude/hooks/auto-commit.sh"
}]
}],
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "bash ~/.claude/hooks/bash-guard.sh"
}]
}]
}
}
Das Ergebnis: CLAUDE.md sagt Claude wie es denken soll, Hooks stellen sicher dass bestimmte Aktionen immer passieren — unabhängig vom Reasoning.
Hooks in echten Agenten-Systemen erleben
In unserem Kurs zeigen wir, wie wir Hooks in einer Produktions-Infrastruktur mit 20+ Agenten einsetzen — Heartbeat-System, Auto-Commits, Safety-Guards und Telegram-Alerts inklusive.
14 Tage kostenlos testen →Häufige Fehler mit Hooks
1. Hook blockiert Claude dauerhaft
Ein fehlerhafter PreToolUse-Hook der immer Exit-Code 2 zurückgibt, blockiert alle Tool-Aufrufe. Lösung: Hooks immer lokal testen bevor sie aktiviert werden. bash hook-script.sh direkt im Terminal ausführen.
2. Sensitive Daten in settings.json
API-Keys direkt in der Hook-Konfiguration landen schnell im Git. Besser: Umgebungsvariablen in settings.local.json und diese Datei in .gitignore.
3. Hook-Output überlädt Claudes Kontext
Wenn ein Hook sehr viel Output produziert, wird dieser als Kontext an Claude übergeben — und belegt Context-Window. Hooks sollten daher nur relevante, kurze Ausgaben produzieren. Verbose-Output umleiten: command >> /log/file 2>&1; echo "OK"