Système de Hooks
Automatisez vos workflows Claude Code avec PreToolUse, PostToolUse et Stop. Auto-format, notifications, rapports de session et patterns avancés.
Qu'est-ce qu'un hook ?
Les hooks sont des commandes shell déclenchées automatiquement par Claude Code à des moments précis du cycle d'exécution. Pensez-y comme des écouteurs d'événements au niveau du terminal : Claude effectue une action, votre hook réagit.
Contrairement aux MCP (qui étendent les capacités de Claude) ou aux Skills (qui définissent des comportements), les hooks interceptent le flux d'exécution pour y injecter une logique externe.
Depuis quelle version ?
Les hooks sont disponibles depuis Claude Code 1.x. Vérifiez votre version avec claude --version et mettez à jour via npm update -g @anthropic-ai/claude-code.
Les 4 types de hooks
Claude Code expose quatre points d'ancrage dans son cycle de vie :
| Type | Déclenchement | Usage typique |
|---|---|---|
PreToolUse | Avant l'exécution d'un outil | Valider les paramètres, bloquer des actions |
PostToolUse | Après l'exécution d'un outil | Auto-format, notifications, logs |
Stop | Quand Claude termine la session | Rapport de session, nettoyage |
Notification | Quand Claude envoie une notification | Alertes Slack, emails |
Configuration dans settings.json
Les hooks se déclarent dans votre fichier settings.json (~/.claude/settings.json pour global, ou .claude/settings.json pour un projet) :
{"hooks": {"PreToolUse": [{"matcher": "Bash","hooks": [{"type": "command","command": "echo 'Validation avant bash...' && exit 0"}]}],"PostToolUse": [{"matcher": "Write","hooks": [{"type": "command","command": "prettier --write \"$CLAUDE_TOOL_OUTPUT_FILE\" 2>/dev/null || true"}]}],"Stop": [{"hooks": [{"type": "command","command": "echo 'Session terminée' >> ~/.claude/session.log"}]}]}}
Structure d'un hook
hooks:
<TypeDeHook>: # PreToolUse | PostToolUse | Stop | Notification
- matcher: "<outil>" # Nom de l'outil à intercepter (optionnel pour Stop/Notification)
hooks:
- type: "command" # Seul type disponible actuellement
command: "..." # Commande shell exécutée
Le matcher accepte le nom exact d'un outil Claude Code : Bash, Write, Edit, Read, WebFetch, etc. Il est omis pour Stop et Notification.
Variables d'environnement disponibles
Vos commandes de hook reçoivent plusieurs variables d'environnement injectées par Claude Code :
| Variable | Disponible dans | Contenu |
|---|---|---|
CLAUDE_TOOL_NAME | PreToolUse, PostToolUse | Nom de l'outil (Bash, Write, etc.) |
CLAUDE_TOOL_INPUT | PreToolUse | Paramètres JSON de l'outil |
CLAUDE_TOOL_OUTPUT | PostToolUse | Résultat de l'outil (stdout) |
CLAUDE_TOOL_OUTPUT_FILE | PostToolUse (Write, Edit) | Chemin du fichier écrit ou modifié |
CLAUDE_SESSION_ID | Tous | Identifiant unique de la session |
Exemples concrets
PreToolUse : valider les paramètres d'une commande shell
Ce hook bloque toute commande rm -rf sur des chemins dangereux :
{"hooks": {"PreToolUse": [{"matcher": "Bash","hooks": [{"type": "command","command": "echo $CLAUDE_TOOL_INPUT | python3 -c \"import sys, json; cmd = json.load(sys.stdin).get('command', ''); exit(1 if 'rm -rf /' in cmd else 0)\""}]}]}}
Codes de sortie
Si votre hook retourne un code de sortie non nul (exit 1), Claude Code interrompt l'action et signale l'erreur à l'utilisateur. Utilisez exit 0 pour laisser l'action se poursuivre.
PostToolUse : auto-format avec Prettier
Formate automatiquement chaque fichier écrit par Claude Code :
{"hooks": {"PostToolUse": [{"matcher": "Write","hooks": [{"type": "command","command": "[ -f \"$CLAUDE_TOOL_OUTPUT_FILE\" ] && npx prettier --write \"$CLAUDE_TOOL_OUTPUT_FILE\" 2>/dev/null || true"}]},{"matcher": "Edit","hooks": [{"type": "command","command": "[ -f \"$CLAUDE_TOOL_OUTPUT_FILE\" ] && npx prettier --write \"$CLAUDE_TOOL_OUTPUT_FILE\" 2>/dev/null || true"}]}]}}
PostToolUse : notification Slack après un commit
Créez d'abord le script de notification :
#!/bin/bash# ~/.claude/hooks/notify-slack.shTOOL_INPUT=$(echo "$CLAUDE_TOOL_INPUT" | python3 -c "import sys, json; d = json.load(sys.stdin); print(d.get('command', ''))")# Déclenche uniquement sur git commitif echo "$TOOL_INPUT" | grep -q "git commit"; thenCOMMIT_MSG=$(git log --oneline -1 2>/dev/null || echo "Commit créé")curl -s -X POST "$SLACK_WEBHOOK_URL" \-H 'Content-type: application/json' \-d "{\"text\": \":white_check_mark: Claude Code a créé un commit : \`$COMMIT_MSG\`\"}" > /dev/nullfiexit 0
Puis configurez le hook dans settings.json :
{"hooks": {"PostToolUse": [{"matcher": "Bash","hooks": [{"type": "command","command": "bash ~/.claude/hooks/notify-slack.sh"}]}]}}
Sécurité des webhooks
Ne mettez jamais l'URL du webhook Slack directement dans settings.json. Utilisez une variable d'environnement : export SLACK_WEBHOOK_URL="https://hooks.slack.com/..." dans votre ~/.bashrc ou ~/.zshrc.
Stop : générer un rapport de session
Créez le script de rapport :
#!/bin/bash# ~/.claude/hooks/session-report.shLOG_FILE=~/.claude/sessions/$(date +%Y-%m-%d).logmkdir -p ~/.claude/sessions{echo "=== Session $(date '+%Y-%m-%d %H:%M:%S') ==="echo "Session ID: $CLAUDE_SESSION_ID"echo "Répertoire: $(pwd)"echo "Branche Git: $(git branch --show-current 2>/dev/null || echo 'N/A')"echo ""} >> "$LOG_FILE"exit 0
Puis dans settings.json :
{"hooks": {"Stop": [{"hooks": [{"type": "command","command": "bash ~/.claude/hooks/session-report.sh"}]}]}}
Patterns avancés
Hooks conditionnels par type de fichier
N'appliquer Prettier que sur les fichiers TypeScript et JavaScript :
#!/bin/bash# ~/.claude/hooks/format-if-ts.shFILE="$CLAUDE_TOOL_OUTPUT_FILE"if [[ "$FILE" =~ \.(ts|tsx|js|jsx|json|css|scss)$ ]]; thennpx prettier --write "$FILE" 2>/dev/nullfiexit 0
Hooks chaînés : lint + format + test
Exécute une chaîne de vérifications après chaque écriture de fichier :
#!/bin/bash# ~/.claude/hooks/quality-chain.shFILE="$CLAUDE_TOOL_OUTPUT_FILE"if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; thenexit 0fi# Étape 1 : Formatnpx prettier --write "$FILE" 2>/dev/null || true# Étape 2 : Lint (sans bloquer)npx eslint --fix "$FILE" 2>/dev/null || true# Étape 3 : Vérification TypeScript (sans bloquer)if [[ "$FILE" =~ \.(ts|tsx)$ ]]; thennpx tsc --noEmit 2>/dev/null || truefiexit 0
Hook de validation de secrets
Bloque toute écriture contenant des patterns de secrets :
#!/bin/bash# ~/.claude/hooks/check-secrets.sh# Hook PreToolUse sur Write/EditFILE_CONTENT=$(echo "$CLAUDE_TOOL_INPUT" | python3 -c "import sys, jsond = json.load(sys.stdin)print(d.get('content', '') + d.get('new_string', ''))" 2>/dev/null)# Patterns à bloquer (clés API courantes)PATTERNS=("sk-[a-zA-Z0-9]{48}""AKIA[0-9A-Z]{16}""AIza[0-9A-Za-z-_]{35}""ghp_[a-zA-Z0-9]{36}")for pattern in "${PATTERNS[@]}"; doif echo "$FILE_CONTENT" | grep -qE "$pattern"; thenecho "ERREUR : Secret détecté dans le contenu (pattern: $pattern)" >&2exit 1fidoneexit 0
Troubleshooting
Mon hook ne se déclenche pas
- Vérifiez le nom exact du matcher (sensible à la casse :
Bash, pasbash) - Rechargez Claude Code : fermez et rouvrez la session
- Validez le JSON de votre
settings.json:
cat ~/.claude/settings.json | python3 -m json.tool
Mon hook bloque toutes les actions
Un exit 1 inattendu peut bloquer Claude. Ajoutez un || true sur les commandes non critiques :
# Mauvais : peut bloquer si npx n'est pas installénpx prettier --write "$FILE"# Bon : ne bloque pas même en cas d'erreurnpx prettier --write "$FILE" 2>/dev/null || true
Déboguer un hook
Loggez la sortie de votre hook pour analyser son comportement :
#!/bin/bash# Ajoutez ces lignes en début de script pour le debugexec 2>> ~/.claude/hooks.logset -x # Active le mode trace (chaque commande est loggée)# Votre code de hook...
Le hook est trop lent
Les hooks bloquent l'exécution de Claude Code. Pour des opérations longues, utilisez l'exécution en arrière-plan :
#!/bin/bash# Lance la notification de manière asynchrone(curl -s -X POST "$SLACK_WEBHOOK_URL" -d '{"text":"Done!"}' > /dev/null 2>&1) &exit 0 # Retourne immédiatement
Prochaines étapes
Les hooks sont puissants en autonome, mais atteignent leur plein potentiel combinés au mode headless pour les pipelines CI/CD.