Hooks Claude Code : automatiser les contrôles de qualité
Les hooks interceptent chaque action de Claude Code pour linter, tester et sécuriser automatiquement. 5 hooks concrets à copier-coller dans votre projet.
Vous utilisez Claude Code tous les jours. Il écrit du bon code, refactorise, génère des tests. Mais entre deux tâches, qui vérifie que le linter passe ? Que les tests tournent encore ? Qu’aucune clé API ne s’est glissée dans un commit ?
Personne. Ou plutôt : vous, quand vous y pensez. Et vous n’y pensez pas toujours.
Les hooks résolvent ce problème. Ce sont des commandes shell qui s’exécutent automatiquement à des moments précis du cycle de vie de Claude Code. Vous n’avez plus à y penser : la vérification a lieu à chaque fois.
Qu’est-ce qu’un hook ?
Un hook est une commande qui se déclenche quand Claude Code effectue une action. Quatre événements sont disponibles :
PreToolUse: avant que Claude exécute un outil (Bash, Edit, Write…)PostToolUse: après l’exécution d’un outilNotification: quand Claude envoie une notificationStop: quand Claude termine un tour de conversation
La configuration se fait dans .claude/settings.json (niveau projet, versionné dans le dépôt) ou dans ~/.claude/settings.json (niveau global, personnel). Voici la structure JSON :
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "your-script.sh"
}
]
}
]
}
}
Le hook reçoit le contexte via stdin : un JSON contenant le nom de l’outil, les paramètres d’entrée et les informations de session. Le code de sortie détermine le comportement : exit 0 = continuer, exit 2 = bloquer l’action. Tout ce qui est écrit sur stderr est renvoyé à Claude, qui peut alors corriger son action.
5 hooks concrets
Hook 1 : Bloquer les commandes dangereuses
Un rm -rf / ou un git push --force sur main, cela arrive. Surtout quand c’est un agent autonome qui tape les commandes. Ce hook intercepte les commandes Bash avant leur exécution et bloque celles qui contiennent un motif dangereux.
Événement : PreToolUse | Matcher : Bash
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 -c \"\nimport sys, json\ndata = json.load(sys.stdin)\ncmd = data.get('tool_input', {}).get('command', '')\nblocked = ['rm -rf /', 'git push --force', 'git push -f', 'DROP TABLE', 'DROP DATABASE', ':(){:|:&};:']\nfor b in blocked:\n if b in cmd:\n print(f'BLOCKED: commande dangereuse détectée ({b})', file=sys.stderr)\n sys.exit(2)\n\""
}
]
}
]
}
}
Si la commande contient un motif bloqué, le script retourne exit 2. Claude reçoit le message d’erreur et reformule sa commande.
Hook 2 : Linter automatique après chaque édition
Chaque fois que Claude modifie un fichier, ESLint tourne automatiquement dessus. Si le linter trouve des erreurs, Claude les voit dans stderr et corrige immédiatement.
Événement : PostToolUse | Matcher : Edit
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'FILE=$(echo $CLAUDE_FILE_PATH); if [[ \"$FILE\" == *.js || \"$FILE\" == *.ts || \"$FILE\" == *.tsx ]]; then npx eslint --fix \"$FILE\" 2>&1; fi'"
}
]
}
]
}
}
Adaptez la commande à vos langages : ruff check pour Python, rubocop -a pour Ruby, gofmt pour Go. Le principe reste le même.
Hook 3 : Vérifier les secrets avant commit
Ce hook intercepte toute commande git commit et examine les fichiers indexés à la recherche de motifs suspects : clés API, jetons, mots de passe en dur.
Événement : PreToolUse | Matcher : Bash
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 -c \"\nimport sys, json, subprocess, re\ndata = json.load(sys.stdin)\ncmd = data.get('tool_input', {}).get('command', '')\nif 'git commit' not in cmd:\n sys.exit(0)\nresult = subprocess.run(['git', 'diff', '--cached', '--diff-filter=ACM'], capture_output=True, text=True)\npatterns = [r'AKIA[0-9A-Z]{16}', r'sk-[a-zA-Z0-9]{20,}', r'ghp_[a-zA-Z0-9]{36}', r'password\\s*=\\s*[\\\"\\'][^\\\"\\']+']\nfor p in patterns:\n matches = re.findall(p, result.stdout)\n if matches:\n print(f'BLOCKED: secret potentiel détecté dans les fichiers staged: {matches[0][:20]}...', file=sys.stderr)\n sys.exit(2)\n\""
}
]
}
]
}
}
Ce hook ne remplace pas gitleaks ou trufflehog dans votre CI. C’est une première ligne de défense qui intercepte les erreurs évidentes avant qu’elles ne quittent votre machine.
Hook 4 : Tests automatiques après modification
Quand Claude modifie un fichier source, ce hook cherche le fichier de test correspondant et le lance. Si les tests échouent, Claude reçoit le résultat et corrige.
Événement : PostToolUse | Matcher : Write
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "bash -c 'FILE=$(echo $CLAUDE_FILE_PATH); TEST_FILE=$(echo \"$FILE\" | sed \"s/\\.ts/.test.ts/\" | sed \"s/src\\//src\\/__tests__\\//\"); if [ -f \"$TEST_FILE\" ]; then npx jest \"$TEST_FILE\" --no-coverage 2>&1 | tail -20; fi'"
}
]
}
]
}
}
Le tail -20 est important : il évite de noyer Claude sous 500 lignes de sortie Jest. Le résumé des échecs suffit pour qu’il comprenne et corrige.
Hook 5 : Notification Slack quand l’agent termine
Claude Code peut tourner longtemps en arrière-plan sur une tâche complexe. Ce hook envoie une notification Slack quand il a fini, avec un résumé de ce qui a été fait.
Événement : Stop
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 -c \"\nimport sys, json, urllib.request\ndata = json.load(sys.stdin)\nstop_reason = data.get('stop_reason', 'unknown')\npayload = json.dumps({'text': f'Claude Code a terminé. Raison: {stop_reason}'}).encode()\nreq = urllib.request.Request('YOUR_SLACK_WEBHOOK_URL', data=payload, headers={'Content-Type': 'application/json'})\nurllib.request.urlopen(req)\n\""
}
]
}
]
}
}
Remplacez YOUR_SLACK_WEBHOOK_URL par votre webhook Slack. Vous pouvez enrichir le message avec le nombre de fichiers modifiés, le dernier commit, ou tout autre contexte utile.
Niveau projet ou niveau global
Deux emplacements, deux usages :
.claude/settings.json (dans le repo) : hooks spécifiques au projet. Versionnés dans Git et partagés avec l’équipe. Le linter du projet, les conventions de test, les contraintes d’architecture.
~/.claude/settings.json (home) : hooks personnels, appliqués à tous vos projets. Les garde-fous de sécurité (blocage de commandes dangereuses, détection de secrets), les notifications Slack.
Dans nos projets, la règle est simple : les hooks de sécurité sont globaux, les hooks de qualité sont dans le repo. Un nouveau développeur qui clone le projet hérite automatiquement des conventions de l’équipe. Et ses hooks personnels de sécurité restent actifs quel que soit le projet.
Limites et bonnes pratiques
Les hooks sont synchrones et bloquants. Un hook lent ralentit chaque action de Claude Code. Gardez-les rapides : un linter sur un fichier, pas une suite de tests complète. Réservez les vérifications lourdes au PostToolUse ou au Stop. C’est d’ailleurs l’un des avantages de Claude Code face à ses concurrents. Notre comparatif des agents CLI 2026 détaille les différences de personnalisation entre les outils.
Ne remplacez pas votre CI/CD. Les hooks sont une première ligne de défense locale. Ils interceptent les erreurs évidentes avant qu’elles ne quittent votre machine. Votre pipeline CI reste indispensable pour les tests d’intégration, les analyses de sécurité approfondies et le déploiement.
Testez vos hooks manuellement. Avant de les activer, lancez le script à la main avec un JSON d’entrée simulé. Un hook qui plante sans rien signaler est pire que l’absence de hook.
Commencez petit. Deux hooks suffisent pour démarrer : un blocage de commandes dangereuses (global) et un linter automatique (projet). Ajoutez-en au fur et à mesure des besoins réels, pas des besoins imaginés.
Sources
Vous déployez Claude Code dans votre équipe ? Formez vos développeurs aux agents IA →
Les hooks sont propres à Claude Code : pour voir ce que proposent Gemini CLI, Codex, Hermes et OpenClaw, lisez le comparatif 2026 →
Questions fréquentes
Qu'est-ce qu'un hook dans Claude Code ?
Un hook est une commande shell qui s'exécute automatiquement à un moment précis du cycle de vie de Claude Code : avant un outil (PreToolUse), après (PostToolUse), à la notification ou en fin de tour (Stop). La configuration se fait dans .claude/settings.json et le code de sortie détermine le comportement : exit 0 pour continuer, exit 2 pour bloquer l'action.
Comment bloquer les commandes dangereuses de Claude Code ?
Avec un hook PreToolUse sur le matcher Bash : un script lit la commande via stdin, détecte les motifs dangereux (rm -rf /, git push --force, DROP TABLE) et retourne exit 2 pour bloquer. Claude reçoit le message d'erreur sur stderr et reformule sa commande. Ce garde-fou se place au niveau global pour couvrir tous vos projets.
Les hooks Claude Code remplacent-ils la CI/CD ?
Non. Les hooks sont une première ligne de défense locale qui intercepte les erreurs évidentes (secrets, lint, tests unitaires ciblés) avant qu'elles ne quittent votre machine. Votre pipeline CI reste indispensable pour les tests d'intégration, les analyses de sécurité approfondies et le déploiement.
Quels hooks Claude Code installer en premier ?
Deux suffisent pour démarrer : un blocage de commandes dangereuses au niveau global (~/.claude/settings.json) et un linter automatique au niveau projet (.claude/settings.json, versionné dans le dépôt). Gardez les hooks rapides car ils sont synchrones et bloquants, puis ajoutez-en selon les besoins réels.