Claude Code Hooks: Event-basierte Automatisierung
Hooks automatisieren Aktionen bei bestimmten Events. Lernen Sie alle Hook-Types, Exit-Code-Verhalten und praktische Beispiele für Auto-Formatting, Testing und Security.
Hooks sind das Enforcement-Feature in Claude Code. Während CLAUDE.md Empfehlungen gibt, garantieren Hooks, dass bestimmte Aktionen immer passieren - Auto-Formatting, Security-Checks, Tests.
Was sind Hooks?
Ein Hook ist ein Script oder Command, das bei einem bestimmten Event automatisch ausgeführt wird:
[Claude will Datei editieren]
↓
[PreToolUse Hook: Security Check]
↓
[Check OK → Edit wird ausgeführt]
↓
[PostToolUse Hook: Auto-Format]
↓
[Formatierte Datei gespeichert]
Der Unterschied zu CLAUDE.md:
| CLAUDE.md | Hooks |
|---|---|
| "Bitte formatiere nach dem Edit" | Formatierung passiert garantiert |
| Advisory | Deterministic |
| Claude kann vergessen | System führt aus |
Alle Hook-Events
Session-Events
| Event | Wann | Typische Nutzung |
|---|---|---|
SessionStart | Session beginnt | Env-Setup, Logging |
SessionEnd | Session endet | Cleanup, Reporting |
User-Events
| Event | Wann | Typische Nutzung |
|---|---|---|
UserPromptSubmit | User sendet Prompt | Input-Validierung, Logging |
Tool-Events
| Event | Wann | Typische Nutzung |
|---|---|---|
PreToolUse | Vor Tool-Ausführung | Validierung, Blocking, Modifikation |
PostToolUse | Nach erfolgreicher Ausführung | Formatting, Testing, Notifications |
PostToolUseFailure | Nach fehlgeschlagener Ausführung | Error-Logging, Alerts |
PermissionRequest | Bei Permission-Dialog | Auto-Accept/Deny Logik |
Agent-Events
| Event | Wann | Typische Nutzung |
|---|---|---|
SubagentStart | Subagent wird gestartet | Logging, Context-Setup |
SubagentStop | Subagent ist fertig | Validierung, Cleanup |
Stop | Claude ist fertig | Finale Checks, Notifications |
System-Events
| Event | Wann | Typische Nutzung |
|---|---|---|
PreCompact | Vor Context-Komprimierung | State-Saving |
Notification | Claude sendet Notification | Custom Alerts |
Konfiguration
Locations
Hooks können an verschiedenen Stellen konfiguriert werden:
| Location | Datei | Scope |
|---|---|---|
| User | ~/.claude/settings.json | Alle Projekte |
| Project | .claude/settings.json | Dieses Projekt (committen) |
| Local | .claude/settings.local.json | Persönlich (nicht committen) |
Grundstruktur
{
"hooks": {
"EventName": [
{
"matcher": "ToolPattern",
"hooks": [
{
"type": "command",
"command": "your-script.sh",
"timeout": 60
}
]
}
]
}
}
Matcher Patterns
| Pattern | Bedeutung |
|---|---|
"Write" | Exakt das Write-Tool |
"Edit|Write" | Edit ODER Write |
"Notebook.*" | Alle Notebook-Tools |
"*" | Alle Tools |
Exit-Code Verhalten
Der Exit-Code Ihres Scripts bestimmt, was passiert:
| Exit Code | Verhalten |
|---|---|
| 0 | Erfolg. stdout wird im Verbose-Mode angezeigt |
| 2 | Blocking Error. stderr wird an Claude zurückgegeben |
| Andere | Non-blocking Error. stderr im Verbose-Mode |
Exit Code 2 ist der Schlüssel - damit können Sie Aktionen blockieren und Claude informieren:
#!/bin/bash
# .claude/hooks/protect-production.sh
if [[ "$FILE" == *"production"* ]]; then
echo "BLOCKED: Production files sind geschützt!" >&2
exit 2
fi
exit 0
PreToolUse: Aktionen kontrollieren
Einfaches Blocking
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/protect-paths.sh"
}
]
}
]
}
}
Script .claude/hooks/protect-paths.sh:
#!/bin/bash
PROTECTED_PATHS=(
".env"
"credentials"
"secrets"
"production.config"
)
for pattern in "${PROTECTED_PATHS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "BLOCKED: $FILE_PATH ist geschützt!" >&2
exit 2
fi
done
exit 0
JSON-Output für erweiterte Kontrolle
PreToolUse Hooks können JSON zurückgeben für feinere Kontrolle:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Docs-Datei auto-approved",
"updatedInput": {
"file_path": "/corrected/path/file.ts"
},
"additionalContext": "Hinweis: Dies ist eine Docs-Datei."
}
}
| Feld | Werte | Beschreibung |
|---|---|---|
permissionDecision | allow, deny, ask | Automatische Entscheidung |
permissionDecisionReason | String | Grund für die Entscheidung |
updatedInput | Object | Modifizierte Tool-Parameter |
additionalContext | String | Extra-Info für Claude |
Beispiel: Auto-Approve für Docs
#!/bin/bash
# .claude/hooks/auto-approve-docs.sh
if [[ "$FILE_PATH" == *.md ]] || [[ "$FILE_PATH" == *"/docs/"* ]]; then
cat << EOF
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Documentation auto-approved"
}
}
EOF
fi
exit 0
PostToolUse: Nach Aktionen reagieren
Auto-Formatting
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/auto-format.sh"
}
]
}
]
}
}
Script:
#!/bin/bash
# .claude/hooks/auto-format.sh
FILE="$FILE_PATH"
case "$FILE" in
*.ts|*.tsx|*.js|*.jsx)
npx prettier --write "$FILE" 2>/dev/null
;;
*.py)
black "$FILE" 2>/dev/null
;;
*.go)
gofmt -w "$FILE" 2>/dev/null
;;
esac
exit 0
Auto-Testing
#!/bin/bash
# .claude/hooks/auto-test.sh
FILE="$FILE_PATH"
# Finde zugehörige Test-Datei
TEST_FILE="${FILE%.ts}.test.ts"
if [[ -f "$TEST_FILE" ]]; then
npm test -- "$TEST_FILE" --passWithNoTests 2>&1
fi
exit 0
Prompt-based Hooks
Für Stop und SubagentStop Events können Sie LLM-basierte Hooks nutzen:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Prüfe ob alle Aufgaben erledigt sind: $ARGUMENTS",
"timeout": 30
}
]
}
]
}
}
Das LLM (Haiku) evaluiert und gibt zurück:
{
"ok": true,
"reason": "Alle Tasks wurden erfolgreich abgeschlossen."
}
Oder bei Problemen:
{
"ok": false,
"reason": "Tests wurden nicht ausgeführt."
}
Environment Variables
Hooks erhalten Kontext über Umgebungsvariablen:
| Variable | Beschreibung |
|---|---|
CLAUDE_PROJECT_DIR | Absoluter Pfad zum Projekt-Root |
CLAUDE_CODE_REMOTE | true wenn Remote/Web-Session |
CLAUDE_ENV_FILE | (SessionStart) Pfad für persistente Env-Vars |
Tool-spezifische Variablen
Je nach Tool sind zusätzliche Variablen verfügbar:
Edit/Write:
FILE_PATH- Pfad zur bearbeiteten Datei
Bash:
COMMAND- Ausgeführter Befehl
Praktische Hook-Sammlung
1. Branch Protection
#!/bin/bash
# Verhindere Commits auf main/master
BRANCH=$(git branch --show-current)
if [[ "$BRANCH" == "main" || "$BRANCH" == "master" ]]; then
echo "BLOCKED: Direkte Commits auf $BRANCH nicht erlaubt!" >&2
exit 2
fi
exit 0
2. Commit Message Validation
#!/bin/bash
# Prüfe Conventional Commits Format
MESSAGE="$1"
PATTERN="^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}"
if ! [[ "$MESSAGE" =~ $PATTERN ]]; then
echo "BLOCKED: Commit Message muss Conventional Commits Format folgen!" >&2
echo "Format: type(scope): description" >&2
exit 2
fi
exit 0
3. Security Scanning
#!/bin/bash
# Scanne auf Secrets
if grep -r "PRIVATE_KEY\|API_KEY\|SECRET" "$FILE_PATH" 2>/dev/null; then
echo "WARNING: Mögliche Secrets gefunden in $FILE_PATH" >&2
# exit 2 # Uncomment um zu blockieren
fi
exit 0
4. Dependency Check
#!/bin/bash
# Prüfe auf bekannte Vulnerabilities nach package.json Änderung
if [[ "$FILE_PATH" == *"package.json"* ]]; then
npm audit --audit-level=high 2>&1
if [[ $? -ne 0 ]]; then
echo "WARNING: npm audit hat Vulnerabilities gefunden" >&2
fi
fi
exit 0
5. Documentation Reminder
#!/bin/bash
# Erinnere an Docs-Updates bei API-Änderungen
if [[ "$FILE_PATH" == *"/api/"* ]]; then
echo "REMINDER: API geändert - bitte auch Docs aktualisieren" >&2
fi
exit 0
Debugging Hooks
Verbose Mode
claude --verbose
Zeigt stdout aller Hooks (auch bei Exit 0).
Logging in Hooks
#!/bin/bash
# Logging zu File
LOG_FILE="$CLAUDE_PROJECT_DIR/.claude/hooks.log"
echo "[$(date)] Hook ausgeführt: $0" >> "$LOG_FILE"
echo " FILE_PATH: $FILE_PATH" >> "$LOG_FILE"
Häufige Fehler
| Problem | Lösung |
|---|---|
| Hook wird nicht ausgeführt | Pfad prüfen, chmod +x |
| Exit 2 blockiert nicht | stderr nutzen, nicht stdout |
| Env-Vars leer | Prüfen ob Event sie bereitstellt |
| Timeout | timeout Feld erhöhen |
Best Practices
1. Schnelle Hooks
Hooks sollten schnell sein (< 5 Sekunden). Lange Hooks blockieren den Workflow.
2. Fail-Safe
#!/bin/bash
# Nicht blockieren bei eigenem Fehler
if ! command -v prettier &> /dev/null; then
# Prettier nicht installiert - nicht blockieren
exit 0
fi
prettier --write "$FILE_PATH"
3. Klare Fehlermeldungen
echo "BLOCKED: .env Dateien dürfen nicht committet werden!" >&2
echo "Hinweis: Nutze .env.example als Template" >&2
exit 2
4. Dokumentation
Dokumentieren Sie Ihre Hooks für das Team:
## Konfigurierte Hooks
| Event | Hook | Zweck |
|-------|------|-------|
| PreToolUse (Edit) | protect-paths.sh | Schützt kritische Dateien |
| PostToolUse (Edit) | auto-format.sh | Formatiert Code |
| Stop | verify-tests.sh | Prüft Test-Coverage |
Fazit
Hooks transformieren "sollte" in "muss". Auto-Formatting, Security-Checks, Test-Execution - was früher Disziplin erforderte, passiert jetzt automatisch.
Starten Sie mit einem einfachen PostToolUse Hook für Formatting. Wenn Sie den Workflow verinnerlicht haben, erweitern Sie auf Security und Testing.
Weiterführende Artikel:
- Claude Code: Der komplette Überblick - Alle Features
- Claude Code Skills erstellen - Wiederverwendbare Workflows
- Claude Code Agents verstehen - Sub-Agenten
- CLAUDE.md Best Practices - Projekt-Konfiguration
Nächster Schritt: Sie möchten Hooks für Ihr CI/CD-Setup entwickeln? Wir helfen bei Konzeption und Implementierung. Mehr über unsere DevOps-Dienstleistungen.


