Les hooks Claude Code sont des commandes que Claude Code exécute de lui-même à des moments fixes d’une session : avant un appel d’outil, après une modification de fichier, à l’envoi d’un prompt, quand Claude s’arrête ou a besoin de votre attention. Vous les définissez sous la clé hooks de settings.json. Un hook peut ajouter du contexte, formater un fichier, ou bloquer une action en sortant avec le code 2 ou en renvoyant une décision JSON. Contrairement aux instructions de CLAUDE.md, un hook s’exécute toujours, car c’est l’infrastructure qui le lance, pas le modèle.
Ce guide couvre les événements qui comptent, le format de configuration, les matchers, les codes de sortie et la sortie JSON, trois hooks à copier dès aujourd’hui, et les notes de sécurité à lire avant d’en ajouter. Les faits viennent de la référence des hooks et du guide des hooks officiels. Si vous voulez seulement la définition courte, voir l’entrée du glossaire sur les hooks Claude Code.
Pourquoi utiliser des hooks plutôt que des instructions
Vous pouvez écrire « lance toujours Prettier après une modification » dans CLAUDE.md, et Claude le fera en général. En général est le problème. Les instructions sont des conseils que le modèle pèse face à tout le reste de son contexte. Les hooks sont du code qui s’exécute à chaque déclenchement de l’événement.
Les hooks sont donc l’outil adapté à trois types de règles :
- Ce qui doit toujours arriver, comme le formatage, le lint ou la journalisation.
- Ce qui ne doit jamais arriver, comme modifier
.envou lancerrm -rfdans le mauvais dossier. - Ce que vous voulez savoir, comme Claude qui attend une réponse à une demande de permission alors que vous êtes dans une autre fenêtre.
Gardez les conseils de style et la connaissance du projet dans CLAUDE.md et mettez les règles strictes dans des hooks.
Les événements de hook que vous utiliserez vraiment
La référence liste plus de trente événements, et la liste grandit à chaque version. La plupart des configurations réelles en utilisent une poignée :
| Événement | Quand il se déclenche | Peut-il bloquer ? |
|---|---|---|
PreToolUse | Avant l’exécution d’un appel d’outil | Oui, bloque l’appel |
PostToolUse | Après la réussite d’un appel d’outil | Non, l’outil a déjà tourné ; stderr va à Claude |
UserPromptSubmit | À l’envoi d’un prompt | Oui, le prompt n’atteint jamais Claude |
Notification | Quand Claude Code envoie une notification, comme une demande de permission ou une attente d’inactivité | Non |
Stop | Quand Claude termine sa réponse | Oui, Claude continue de travailler |
SubagentStart / SubagentStop | Quand un subagent démarre ou se termine | Seulement SubagentStop |
SessionStart | Au démarrage, à la reprise, à /clear ou à la compaction | Non, mais stdout devient du contexte |
PreCompact | Avant la compaction du contexte | Oui, bloque la compaction |
PermissionRequest | Quand une boîte de dialogue de permission va s’afficher | Via JSON uniquement, pas par la sortie 2 |
SessionEnd | À la fin de la session | Non |
PreToolUse et PostToolUse couvrent la plupart des besoins. Notification et Stop servent à « prévenez-moi quand c’est fini ou bloqué ».
Comment configurer les hooks dans settings.json
Les hooks vivent dans les mêmes fichiers de réglages que les permissions :
| Fichier | Portée | Partagé via git ? |
|---|---|---|
~/.claude/settings.json | Tous vos projets | Non |
.claude/settings.json | Un projet | Oui |
.claude/settings.local.json | Un projet, vous seul | Non (ignoré par git) |
| Réglages de politique gérée | Toute l’organisation | Définis par les administrateurs |
Les plugins peuvent fournir des hooks dans hooks/hooks.json, et les skills et subagents peuvent définir des hooks dans leur frontmatter.
La structure a trois niveaux : l’événement, un groupe de matchers et une liste de gestionnaires.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write",
"timeout": 30
}
]
}
]
}
}
Le type d’un gestionnaire peut être command (une commande shell), http (un POST vers une URL), mcp_tool (un outil d’un serveur MCP que vous avez connecté), prompt (une vérification oui/non rapide par un modèle) ou agent (une vérification expérimentale par un subagent). Le délai par défaut est de 600 secondes pour les gestionnaires command, HTTP et MCP tool, de 30 secondes pour les hooks prompt et de 60 pour les hooks agent.
Chaque hook reçoit du JSON sur stdin. Les champs courants sont session_id, transcript_path, cwd, permission_mode et hook_event_name. Les événements d’outil ajoutent tool_name, tool_input et tool_use_id. Votre script lit ce JSON, en général avec jq, et décide quoi faire. La variable d’environnement CLAUDE_PROJECT_DIR pointe vers la racine du projet, pratique pour référencer des scripts stockés dans le dépôt.
Tapez /hooks dans Claude Code pour parcourir ce qui est chargé et le fichier d’où vient chaque hook. Le navigateur est en lecture seule : on modifie les hooks en éditant le JSON.
Matchers : quels appels d’outil un hook voit
Le matcher décide quels appels déclenchent un hook. Pour les événements d’outil, il porte sur le nom de l’outil :
| Matcher | Signification |
|---|---|
"*", "" ou pas de matcher | Tous les appels |
"Bash" | Exactement l’outil Bash |
"Edit|Write" | Edit ou Write (une liste) |
"mcp__memory__.*" | Tous les outils du serveur MCP memory |
"mcp__.*__write.*" | Tout outil MCP dont le nom commence par write |
La règle est simple. Si le matcher ne contient que des lettres, des chiffres, _, -, des espaces, des virgules ou |, c’est un nom exact ou une liste de noms. Tout autre caractère en fait une expression régulière JavaScript. Les outils MCP s’appellent mcp__<server>__<tool>.
Certains événements ignorent le matcher, dont UserPromptSubmit et Stop, faute de quoi comparer. D’autres comparent autre chose qu’un nom d’outil. SessionStart compare la manière dont la session a démarré (startup, resume, clear, compact), et Notification le type de notification, comme permission_prompt ou idle_prompt.
Les événements d’outil acceptent aussi un champ if avec la syntaxe des règles de permission, si bien qu’un hook Bash peut ne s’exécuter que pour, par exemple, "Bash(git *)". La documentation le décrit comme un filtre au mieux : gardez la vraie vérification dans votre script.
Codes de sortie et sortie JSON
Un hook command répond à Claude Code de deux façons : le code de sortie, et du JSON facultatif sur stdout.
| Code de sortie | Ce qui se passe |
|---|---|
0 | Succès. stdout est analysé comme JSON s’il s’agit d’un seul objet JSON. Pour UserPromptSubmit et SessionStart, le texte brut sur stdout est ajouté au contexte de Claude. |
2 | Erreur bloquante. stderr est la raison. Sur PreToolUse l’appel est annulé, sur UserPromptSubmit le prompt est rejeté, sur Stop Claude continue. |
Tout autre code, y compris 1 | Erreur non bloquante. Claude Code la note et poursuit. |
Le piège est le code de sortie 1. Beaucoup de scripts échouent avec 1 par défaut, et cela ne bloque rien. Si vous voulez dire « stop », sortez avec 2.
Pour un contrôle plus fin, sortez avec 0 et affichez du JSON. Un hook PreToolUse peut autoriser, refuser ou demander :
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Use rg instead of grep for better performance"
}
}
permissionDecision accepte allow, deny, ask ou defer. Un hook peut aussi réécrire l’appel avec updatedInput, ou transmettre du texte supplémentaire à Claude avec additionalContext. Les champs valables pour tout événement incluent continue: false (arrêter Claude complètement, avec un stopReason) et systemMessage (un avertissement qui vous est montré).
Quand plusieurs hooks correspondent, ils s’exécutent en parallèle et la réponse la plus restrictive l’emporte : deny bat defer, defer bat ask, ask bat allow. Un allow d’un hook ne passe pas outre une règle deny de vos permissions.
Exemple 1 : formater les fichiers après chaque modification
C’est le hook par lequel la plupart des gens commencent. Il lance Prettier sur tout fichier que Claude écrit ou modifie :
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
Remplacez-le par ruff format, gofmt -w ou rustfmt pour d’autres langages. Comme le formateur s’exécute après la modification, Claude voit le fichier formaté à sa prochaine lecture, et vous ne voyez plus de diffs de pur style en revue.
Exemple 2 : bloquer les commandes dangereuses et les fichiers protégés
Un hook PreToolUse est l’endroit pour les limites strictes. Ce script, adapté du guide officiel, bloque les modifications de fichiers sensibles. Enregistrez-le sous .claude/hooks/protect-files.sh :
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
exit 2
fi
done
exit 0
Rendez-le exécutable avec chmod +x .claude/hooks/protect-files.sh, puis enregistrez-le :
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
Le même schéma marche pour les commandes shell. Faites correspondre Bash, lisez .tool_input.command, et sortez avec 2 quand elle contient ce que vous ne voulez jamais, comme rm -rf /, git push --force ou DROP TABLE. Gardez en tête qu’une vérification par chaîne se contourne facilement : voyez-la comme une ceinture de sécurité, pas comme une serrure.
Exemple 3 : recevoir une notification de bureau
Les tâches longues s’arrêtent pour vous attendre plus souvent qu’on ne le voudrait. Un hook Notification vous prévient tout de suite. Sur macOS :
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
Sous Linux, utilisez plutôt notify-send 'Claude Code' 'Claude Code needs your attention'. Mettez le matcher à permission_prompt si seules les demandes de permission vous intéressent, ou ajoutez un hook Stop avec la même commande pour savoir quand Claude a fini.
D’autres schémas utiles
- Réinjecter du contexte après la compaction. Un hook
SessionStartavec le matchercompactpeut faire unechod’un court rappel de vos règles. Sa sortie stdout est ajoutée au nouveau contexte. - Auditer les changements de configuration. Un hook
ConfigChangepeut ajouter chaque changement de réglages à un fichier journal. - Contrôle qualité sur Stop. Un hook
Stoppeut lancer vos tests et sortir avec 2 en renvoyant les échecs, pour que Claude continue de corriger. Vérifiez le champstop_hook_activede l’entrée pour éviter une boucle infinie. Claude Code passe aussi outre un hook Stop après plusieurs blocages d’affilée. - Approuver automatiquement un prompt sûr. Un hook
PermissionRequestpeut répondre à une boîte de dialogue précise avec{"behavior": "allow"}dans son objet de décision. Gardez le matcher étroit.
Notes de sécurité avant d’ajouter des hooks
Les hooks s’exécutent comme des commandes shell avec les droits de votre utilisateur, sans demander. C’est tout l’intérêt, et aussi le risque.
- Lisez les hooks avant de faire confiance à un dépôt. Le
.claude/settings.jsond’un projet peut embarquer des hooks. Relisez-les comme vous relisez un scriptpostinstall. - Mettez vos variables entre guillemets. L’entrée d’un hook vient du modèle, et le modèle lit des fichiers et des pages web qui peuvent contenir de l’injection de prompt. Utilisez
"$VAR", n’évaluez jamais l’entrée avec eval, et préférezjqà un analyseur maison. - Utilisez des chemins absolus ou relatifs au projet avec
$CLAUDE_PROJECT_DIR, pour qu’un hook ne dépende pas du dossier courant. - Gardez les hooks rapides. Un hook
PreToolUselent ralentit chaque appel d’outil. Définissez untimeout. - Les hooks ne sont pas un bac à sable. Un hook deny bloque les appels même sous
--dangerously-skip-permissions, ce qui est utile, mais un agent déterminé ou confus peut atteindre le même résultat autrement. Combinez hooks, règles deny et isolation, comme expliqué dans la sécurité des agents de code IA et ignorer les permissions en sécurité. - Connaissez les interrupteurs.
"disableAllHooks": truedésactive les hooks, et les administrateurs peuvent définirallowManagedHooksOnlydans les réglages gérés pour bloquer les hooks utilisateur et projet.
Quand un hook se comporte mal, lancez Claude Code avec claude --debug, ou écrivez le journal dans un fichier avec --debug-file /tmp/claude.log, pour voir le matcher, le code de sortie et la sortie de chaque hook.
Comment AgentVera utilise les hooks
AgentVera est une application de bureau qui exécute Claude Code, Codex, Gemini CLI et d’autres CLI de code côte à côte. Les hooks sont une grande part de son fonctionnement avec Claude Code.
- Vos hooks restent les vôtres. AgentVera passe ses propres hooks à chaque processus Claude Code avec l’option
--settings. Claude Code les fusionne avec les hooks de vos fichiers de réglages, et votresettings.jsonn’est pas modifié. - L’état des agents vient des hooks. L’état que chaque agent affiche dans l’application est lu à partir des événements de hook de la CLI elle-même, pas deviné d’après le texte du terminal.
- Les smart tools sont des hooks. La fonction smart tools ajoute quatre hooks aux agents Claude Code locaux : elle bloque les lectures répétées d’un même fichier, ne lance que les tests concernés par une modification, vérifie les erreurs juste après une modification et partage les résultats entre agents. Ils sont activés par défaut et vous pouvez les désactiver dans Settings → “Token saving”.
- Pas besoin de script de notification. Notifications et approbations réunit dans une seule file tous les agents en attente d’approbation, envoie des notifications de bureau quand l’application est en arrière-plan, et peut vous alerter sur votre téléphone via Telegram.
Qwen Code reçoit aussi les hooks d’AgentVera, car son système de hooks suit les événements et le format JSON de Claude Code.
Pour conclure
Commencez par un formateur PostToolUse et une garde PreToolUse, vérifiez-les avec /hooks et --debug, et n’en ajoutez que lorsqu’une règle est sans cesse enfreinte. Sortez avec 2 pour bloquer, affichez du JSON quand il vous faut plus de contrôle, et traitez chaque hook comme du code qui s’exécute avec vos permissions.
Pour aller plus loin :
Pour essayer AgentVera, commencez par la page d’accueil.