← Tous les articles

Tutoriel des hooks Claude Code : 5 hooks de production à partir de zéro

Part 5 of New to Claude Code

Tiré du guide: Claude Code Comprehensive Guide

Claude Code exécute la bonne action dans la grande majorité des cas. Les cas limites qui subsistent : un force-push sur main, votre formateur ignoré, du code commité alors qu’il ne passe pas le lint. Les hooks éliminent ces cas limites en installant des garde-fous déterministes à 31 points du cycle de vie du workflow de Claude (en août 2026).1 Ce tutoriel fait partie de ma série AI engineering consacrée à la construction de systèmes d’agents de qualité production. Ils se déclenchent à chaque fois, sans exception, quelle que soit la formulation du prompt ou le comportement du modèle.

TL;DR : les hooks sont des commandes shell déclenchées par les événements du cycle de vie de Claude Code.1 Les hooks PreToolUse inspectent les actions et les bloquent (code de sortie 2 = blocage, code 0 = autorisation).2 Les hooks PostToolUse valident et formatent après coup. Vous les configurez dans .claude/settings.json avec un matcher (un nom d’outil exact, une liste séparée par des | ou une expression régulière) et un tableau hooks imbriqué.3 Le tutoriel ci-dessous construit cinq hooks de production : formateur automatique, garde-fou de sécurité, lanceur de tests, alerte de notification et contrôle qualité avant commit.

À retenir

  • Développeurs solo : commencez par le formateur automatique (hook 1) et le garde-fou de sécurité (hook 2). Ces deux hooks évitent les erreurs les plus fréquentes de Claude Code sans aucune maintenance continue.
  • Responsables d’équipe : versionnez vos hooks dans le .claude/settings.json du dépôt. Chaque membre de l’équipe bénéficie automatiquement des mêmes garde-fous et des mêmes contrôles qualité.
  • Ingénieurs sécurité : le code de sortie 2 bloque l’action.2 Le code de sortie 1 se contente de journaliser un avertissement. Tout hook de sécurité PreToolUse doit utiliser exit 2, faute de quoi il n’impose rien.

Qu’est-ce qu’un hook ?

Les hooks sont des commandes shell exécutées lors d’événements précis du cycle de vie d’une session Claude Code. Elles tournent en dehors du LLM, sous forme de simples scripts déclenchés par les actions de Claude, et non de prompts interprétés par le modèle.

Quatre grandes catégories couvrent les usages les plus courants (Claude Code documente 31 types d’événements en août 2026) :1

  • Événements de session : SessionStart se déclenche au début d’une session, SessionEnd à sa fermeture, et Stop chaque fois que Claude termine une réponse (pas seulement à la fin de la session). Utilisez-les pour l’initialisation, le nettoyage et les notifications.
  • Événements d’outil : PreToolUse et PostToolUse se déclenchent avant et après l’utilisation d’un outil par Claude (écrire un fichier, lancer une commande bash ou rechercher dans le code). Ce sont les hooks les plus puissants, car ils peuvent inspecter et bloquer des actions précises.
  • Événements de notification : Notification se déclenche lorsque Claude produit une notification. Pratique pour router les alertes vers Slack, vers les notifications du bureau ou vers des systèmes de journalisation.
  • Événements de sous-agent : SubagentStop se déclenche lorsqu’un sous-agent (lancé via l’outil Agent) a terminé.4 Les hooks se déclenchent aussi pour les actions des sous-agents : vos garde-fous s’appliquent donc de façon récursive.

La sémantique des codes de sortie compte.2 Le code 0 signifie succès (on continue). Le code 2 signifie que l’action est bloquée. Le code 1 correspond à une erreur de hook non bloquante : l’action se poursuit malgré tout. Tout hook critique pour la sécurité doit utiliser exit 2 pour que son garde-fou s’applique réellement.

Le modèle mental : trois types de garanties

Avant d’écrire le moindre hook, demandez-vous : de quel type de garantie ai-je besoin ?

Les garanties de formatage assurent la cohérence après coup. Les hooks PostToolUse sur Write/Edit lancent votre formateur après chaque modification de fichier. Ce que produit le modèle n’a aucune importance, puisque le formateur normalise tout. Ces hooks sont idempotents et peuvent tourner sans risque à chaque édition.

Les garanties de sûreté empêchent les actions dangereuses avant leur exécution. Les hooks PreToolUse sur Bash inspectent les commandes et bloquent les motifs destructeurs avec le code de sortie 2. Ces hooks doivent être rapides (moins de 500 ms), car ils filtrent chaque appel d’outil correspondant, et ils doivent utiliser le code 2 (et non le code 1), parce que le code 1 se contente d’avertir sans bloquer.

Les garanties de qualité valident l’état à des points de décision. Les hooks PreToolUse sur les commandes git commit lancent votre linter ou votre suite de tests et bloquent le commit si les contrôles échouent. Contrairement aux hooks de formatage, qui se déclenchent à chaque édition, les hooks de qualité n’interviennent qu’à des moments précis, ce qui maintient le surcoût au minimum.

L’ancêtre conceptuel, ce sont les hooks Git8: pre-commit, pre-push et post-commit remplissent les trois mêmes rôles. Les hooks de Claude Code étendent le motif des opérations Git à chaque action d’outil de l’agent. Je décortique cette évolution dans every hook is a scar : chaque hook existe parce que quelque chose a mal tourné en son absence.


Bases de la configuration des hooks

Les hooks vivent dans vos fichiers de paramètres :

  • Au niveau du projet : .claude/settings.json à la racine de votre dépôt (partagé avec votre équipe)3
  • Au niveau de l’utilisateur : ~/.claude/settings.json (vos hooks personnels, appliqués partout)3

La structure JSON :

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/your/script.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/another-script.sh"
          }
        ]
      }
    ]
  }
}

Chaque entrée comporte un matcher qui filtre des noms d’outils comme Bash, Write, Edit, Read, Glob, Grep ou Agent, ainsi qu’un tableau hooks de définitions. La sémantique du matcher, d’après la référence : "*", "" ou un matcher absent correspondent à tout ; une valeur composée de lettres, de chiffres, de _, de -, de |, de virgules et d’espaces est un nom exact ou une liste, si bien que Write|Edit correspond aux deux outils (le tiret bas compte pour les noms d’outils MCP comme mcp__github__search_code) ; tout le reste est traité comme une expression régulière non ancrée. La correspondance est sensible à la casse – bash ne correspond jamais à Bash. Chaque hook précise un type ("command" pour les commandes shell) et la commande à lancer via command.

Vous pouvez consulter les hooks enregistrés avec le navigateur /hooks en lecture seule au sein d’une session ; pour ajouter, modifier ou supprimer un hook, éditez directement le JSON de paramètres.5

Lorsqu’un hook se déclenche, Claude Code fournit le contexte sous forme d’objet JSON sur stdin : le nom de l’outil, l’entrée de l’outil (dont file_path pour les opérations sur fichier) et les métadonnées de session.6 Votre script lit stdin – généralement avec jq – pour décider. Quelques variables d’environnement apportent aussi du contexte – $CLAUDE_PROJECT_DIR pour résoudre les chemins, $CLAUDE_EFFORT pour le niveau d’effort courant – mais les champs propres à chaque outil, comme le chemin du fichier, n’arrivent que sur stdin : il n’existe aucune variable $FILE_PATH par outil.


5 hooks concrets

Chaque hook ci-dessous résout un problème réel rencontré en utilisant Claude Code comme outil de développement principal. Tous les exemples reprennent le schéma imbriqué correct de la référence des hooks7.

1. Formatage automatique à l’édition d’un fichier

Claude écrit du code fonctionnellement correct qui enfreint parfois les règles de formatage de votre projet. J’ai d’abord ajouté « lance toujours black après avoir modifié un fichier Python » à mon CLAUDE.md, mais la consigne ne fonctionnait que dans 80 % des cas environ. Le modèle sautait parfois l’étape de formatage lorsqu’il se concentrait sur une modification complexe portant sur plusieurs fichiers. Un hook PostToolUse supprime totalement cette incohérence : votre formateur tourne après chaque écriture de fichier, quoi que le modèle ait décidé de faire.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'FILE=$(jq -r \".tool_input.file_path // empty\"); if [[ \"$FILE\" == *.py ]]; then black --quiet \"$FILE\" 2>/dev/null; elif [[ \"$FILE\" == *.js || \"$FILE\" == *.ts ]]; then npx prettier --write \"$FILE\" 2>/dev/null; fi'"
          }
        ]
      }
    ]
  }
}

Le hook lit l’entrée JSON de l’outil sur stdin et en extrait .tool_input.file_path avec jq – cet objet stdin est le seul endroit où figure le chemin du fichier, puisque Claude Code ne définit aucune variable d’environnement par outil. Il vérifie ensuite l’extension et lance le formateur adéquat : black pour les fichiers Python, prettier pour les fichiers JavaScript et TypeScript. Le 2>/dev/null supprime les sorties parasites, de sorte que vous ne voyiez que les vraies erreurs.

Sur les projets plus vastes, déplacez la commande en ligne dans un script autonome, par souci de lisibilité.

2. Garde-fou de sécurité pour les commandes dangereuses

Les hooks PreToolUse sur l’outil Bash inspectent la commande que Claude s’apprête à lancer et la bloquent si elle correspond à un motif dangereux. J’ai écrit la première version de ce hook après que Claude a fait un force-push sur main pendant une session de refactoring. (J’explore les implications plus larges de l’autonomie des agents dans anatomy of a claw et Claude Code as infrastructure.) On avait demandé au modèle de « pousser les changements », ce qu’il a interprété comme git push --force origin main parce que la branche avait divergé. La correction a pris quelques secondes ; l’incident a motivé un garde-fou permanent.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r \".tool_input.command\"); if echo \"$CMD\" | grep -qE \"rm\\s+-rf\\s+/|git\\s+push\\s+(-f|--force)\\s+(origin\\s+)?main|git\\s+reset\\s+--hard|DROP\\s+TABLE|:\\(\\)\\s*\\{\\s*:\"; then echo \"BLOCKED: Dangerous command detected: $CMD\" >&2; exit 2; fi'"
          }
        ]
      }
    ]
  }
}

Lorsque ce hook se termine avec le code 2, Claude Code annule la commande en attente. Le message d’erreur s’affiche à la fois dans votre terminal et dans le contexte de Claude : le modèle comprend donc pourquoi l’action a échoué et propose une solution plus sûre.

Motifs bloqués : - rm -rf / (suppression récursive depuis la racine) - git push --force main et git push -f main (force-push sur la branche main) - git reset --hard (destruction du travail non commité) - DROP TABLE (destruction accidentelle de la base de données) - Fork bombs (le motif reconnaît l’amorce :(){, ce qui couvre les variantes avec et sans espace)

Adaptez cette liste à votre environnement. Les bases de données de production réclament des motifs SQL destructeurs. Les déploiements pilotés en CLI réclament des garde-fous sur les commandes de déploiement.

3. Lancement des tests après modification

Dès que Claude modifie un fichier Python, lancez automatiquement les tests concernés. Une exécution immédiate attrape les régressions avant qu’elles ne s’accumulent sur trois ou quatre modifications suivantes.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'FILE=$(jq -r \".tool_input.file_path // empty\"); if [[ \"$FILE\" == *.py && \"$FILE\" != *test_* ]]; then TEST_FILE=\"tests/test_$(basename \"$FILE\")\"; if [[ -f \"$TEST_FILE\" ]]; then if ! OUT=$(python -m pytest \"$TEST_FILE\" -x --tb=short 2>&1); then echo \"TESTS FAILED after editing $FILE:\" >&2; echo \"$OUT\" | tail -20 >&2; exit 2; fi; fi; fi'"
          }
        ]
      }
    ]
  }
}

Le hook extrait du JSON reçu sur stdin le chemin du fichier modifié, vérifie qu’il s’agit bien d’un fichier source Python (et non d’un fichier de test), cherche le fichier de test correspondant selon la convention de nommage à préfixe test_, puis le lance s’il existe. L’option -x s’arrête au premier échec et tail -20 garde une sortie concise. C’est le exit 2 en cas d’échec qui rend le hook utile : un hook PostToolUse ne peut pas défaire la modification déjà effectuée, mais le code 2 transmet à Claude, sur stderr, la sortie des tests en échec, et Claude répare la casse avant de continuer. Une version qui se contente d’afficher l’échec avec un code 0 l’envoie dans le journal de débogage, que personne ne regarde.

Remarque : le hook ci-dessus suppose un répertoire tests/ plat et un nommage à préfixe test_. Pour les projets qui reflètent l’arborescence des sources (par exemple tests/api/test_users.py face à src/api/users.py), remplacez la ligne TEST_FILE par :

TEST_FILE="tests/$(echo "$FILE" | sed 's|.*/src/||; s|\([^/]*\)\.py$|test_\1.py|')"

Le hook de lancement des tests se révèle particulièrement précieux lors des sessions de refactoring où Claude touche plusieurs fichiers. Sans retour immédiat, les erreurs s’accumulent : Claude modifie le fichier A, casse les tests du fichier B, puis modifie le fichier C en se fondant sur l’état cassé de B. Le temps que vous découvriez l’échec, trois fichiers sont à réparer au lieu d’un. Lancer les tests après chaque édition attrape la première cassure immédiatement.

4. Notification quand Claude a terminé

Un tour de Claude Code un peu long peut durer plusieurs minutes. Plutôt que de surveiller le terminal, faites-vous notifier dès que Claude a fini de répondre. (Stop se déclenche à la fin de chaque réponse – pour un hook à la fermeture réelle de la session, enregistrez plutôt SessionEnd.)

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude finished responding\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

La variante macOS ci-dessus s’appuie sur osascript pour déclencher une notification native. Sous Linux, remplacez la ligne osascript par notify-send "Claude Code" "Finished responding". Pour des notifications Slack, utilisez un webhook :

curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H 'Content-type: application/json' \
  -d '{"text": "Claude Code finished responding"}'

J’utilise la variante Slack pour les tâches de fond lancées avec & <task> (le mode arrière-plan de Claude Code). La notification de bureau couvre les sessions interactives.

5. Contrôle qualité avant commit

Avant que Claude ne lance git commit, vérifiez que le code passe le lint. Un garde-fou de lint avant commit attrape ce que le formatage seul laisse passer : imports inutilisés, variables non définies, erreurs de typage.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r \".tool_input.command\"); if echo \"$CMD\" | grep -qE \"^git\\s+commit\"; then if ! LINT_OUTPUT=$(ruff check . --select E,F,W 2>&1); then echo \"LINT FAILED -- fix before committing:\" >&2; echo \"$LINT_OUTPUT\" >&2; exit 2; fi; fi'"
          }
        ]
      }
    ]
  }
}

Le garde-fou qualité ne s’active que si la commande Bash commence par git commit. Il lance ruff (un linter Python rapide) avec les règles d’erreur, pyflakes et d’avertissement. En cas de problème, le hook bloque le commit (code 2) et Claude voit la sortie du lint, ce qui l’amène généralement à corriger puis à réessayer.

Vous pouvez empiler plusieurs contrôles qualité : mypy pour le typage, bandit pour l’analyse de sécurité, ou les scripts de validation propres à votre projet. Les hooks PreToolUse sur les commandes Bash vous donnent un garde-fou programmable avant toute action shell.


PreToolUse et PostToolUse dans .claude/settings.json : la référence

Si vous cherchiez la forme de configuration de PreToolUse/PostToolUse et que vous atterrissez ici, voici la version compacte. Les deux événements s’imbriquent sous la clé hooks de .claude/settings.json (projet) ou de ~/.claude/settings.json (utilisateur) ; les portées se combinent, les gestionnaires identiques étant dédoublonnés. Un seul bloc qui câble les deux événements :3

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": ".claude/hooks/guard.sh" }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{ "type": "command", "command": ".claude/hooks/format.sh" }]
      }
    ]
  }
}

Le contrat en trois lignes : les deux événements livrent le JSON de l’outil sur stdin (.tool_input.command pour Bash, .tool_input.file_path pour Write/Edit – il n’existe pas de variable d’environnement par outil).6 PreToolUse se déclenche avant l’appel de l’outil et peut le bloquer avec le code 2. PostToolUse se déclenche une fois l’outil réussi – il ne peut pas défaire l’action, mais le code 2 renvoie sa sortie stderr à Claude, qui corrige alors ce que le hook a signalé.2

Pour la documentation complète des deux événements – champs de sortie JSON, permissionDecision, updatedInput, délais d’expiration – la référence officielle est code.claude.com/docs/en/hooks ; la section hooks de mon guide Claude Code couvre le même terrain avec des motifs éprouvés sur le terrain.

Vous avez deviné un nom d’événement ? La correspondance

Les événements de hook que l’on cherche, face à ce que Claude Code déclenche réellement :1

Si vous avez deviné… L’événement réel
onStart / onSessionStart SessionStart
onFinish / onEnd / onStop Stop (se déclenche quand Claude termine chaque réponse) ou SessionEnd (fermeture de la session)
onToolUse / beforeToolUse PreToolUse
afterToolUse PostToolUse
onPrompt / onUserMessage UserPromptSubmit
onError PostToolUseFailure (erreurs d’outil) ou StopFailure (erreurs d’API)

Il existe trente et un événements au total – le tableau des événements du guide les recense tous.

Un hook PreToolUse, PostToolUse et Stop dans une seule configuration

Les trois événements les plus recherchés, câblés ensemble – un garde-fou de commandes, un formateur et une notification de fin :

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": ".claude/hooks/guard-bash.sh" }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{ "type": "command", "command": "bash -c 'FILE=$(jq -r \".tool_input.file_path // empty\"); [[ \"$FILE\" == *.py ]] && black --quiet \"$FILE\" || true'" }]
      }
    ],
    "Stop": [
      {
        "hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude finished responding\" with title \"Claude Code\"'" }]
      }
    ]
  }
}

guard-bash.sh, c’est le garde-fou de sécurité du hook 2 déplacé dans un script autonome : enregistrez le corps du one-liner bash -c du hook 2 (tout ce qui se trouve entre les guillemets simples extérieurs) sous .claude/hooks/guard-bash.sh, ajoutez un shebang #!/bin/bash et rendez-le exécutable avec chmod +x – ou reprenez le script tout prêt du même nom dans Claude Code Hooks Explained. Chaque événement conserve sa propre sémantique : le garde-fou PreToolUse peut opposer son veto aux commandes (code 2), le formateur PostToolUse tourne après chaque édition correspondante, et le hook Stop se déclenche à la fin de chaque réponse – sans matcher : Stop n’est pas un événement d’outil, il n’y a donc rien à filtrer.1


Conseils de débogage des hooks

Les hooks échouent en silence plus souvent qu’on ne le croit. Cinq techniques que j’utilise pour les déboguer :

  1. Testez d’abord les scripts isolément. Injectez un JSON d’exemple à la main dans votre script : echo '{"tool_input":{"command":"git commit -m test"}}' | bash your-hook.sh. S’il échoue en dehors de Claude Code, il échouera aussi à l’intérieur.
  2. Sachez où part réellement stderr. Stderr n’atteint le contexte de Claude que si le hook se termine avec le code 2 ; avec un code 0, il atterrit dans le journal de débogage, et pour les autres codes non nuls, seule une mention d’erreur de hook apparaît dans la transcription. Pendant le développement, lancez claude --debug (ou /debug en cours de session) et surveillez le journal de débogage, là où atterrit la sortie des hooks terminés en 0.
  3. Surveillez les échecs de jq. Si votre chemin JSON est faux, jq9 renvoie null en silence et vos conditions ne se vérifieront jamais. Testez vos expressions jq sur de vraies entrées d’outil.
  4. Vérifiez les codes de sortie. Le code 2 bloque les actions. Le code 1 se contente d’avertir. Un hook PreToolUse qui utilise exit 1 par mégarde n’impose rien tout en donnant l’illusion de fonctionner. Partez d’une posture permissive (code 0 par défaut) et réservez exit 2 aux motifs explicitement bloqués.
  5. Gardez vos hooks rapides. Les hooks tournent de façon synchrone. Un hook qui prend 5 secondes ajoute 5 secondes à chaque utilisation d’outil correspondante. Je maintiens tous mes hooks sous 2 secondes, idéalement sous 500 millisecondes.

L’erreur la plus fréquente sur les hooks : écrire un garde-fou de sécurité avec exit 1 au lieu de exit 2. Le hook a l’air de marcher pendant les tests, puisque le message d’avertissement s’affiche dans le terminal. Mais le code 1 est un avertissement non bloquant. La commande dangereuse s’exécute quand même. J’ai vu cette erreur dans les configurations de hooks de trois équipes différentes, chacune persuadée d’avoir bloqué les force-pushes. Testez chaque hook de sécurité en déclenchant le motif bloqué et en vérifiant que l’action a bien été empêchée, et pas seulement signalée.


Étapes suivantes

Ces cinq hooks couvrent les fondamentaux : formatage, sécurité, tests, notifications et garde-fous qualité. Une fois ces motifs bien en main, vous pouvez construire des hooks pour l’injection de contexte (ajouter des consignes propres au projet au démarrage d’une session), les garde-fous de récursion (empêcher les boucles infinies de sous-agents) et l’orchestration de workflows (enchaîner des processus en plusieurs étapes).

Pour l’architecture des hooks, le cycle de vie complet à 31 événements et les motifs avancés, consultez la section hooks de mon Claude Code guide complet, ou le parcours événement par événement dans Claude Code Hooks Explained.

J’ai également raconté les origines de mes 95 hooks de production dans Claude Code Hooks: Why Each of My 95 Hooks Exists, qui revient sur les incidents ayant motivé chacun d’eux.


Références


FAQ

Les hooks peuvent-ils empêcher Claude Code d’exécuter une commande ?

Oui. Les hooks PreToolUse bloquent n’importe quelle action d’outil en se terminant avec le code 2. Claude Code annule l’action en attente et montre au modèle la sortie stderr du hook. Le code 1 est une erreur de hook non bloquante : l’action se poursuit. La distinction entre les codes compte : tout hook de sécurité doit utiliser exit 2, et non exit 1.2 Claude voit le motif du refus et propose une solution plus sûre.

Où placer les fichiers de configuration des hooks ?

Les configurations de hooks vont dans .claude/settings.json pour les hooks au niveau du projet (versionnés dans votre dépôt, partagés avec votre équipe) ou dans ~/.claude/settings.json pour les hooks au niveau de l’utilisateur (personnels, appliqués à tous les projets). Quand les deux existent, les hooks se combinent au lieu de s’écraser : chaque hook correspondant, quelle que soit sa portée, s’exécute, les gestionnaires identiques étant dédoublonnés. Je recommande des chemins absolus pour les fichiers de script, afin d’éviter les problèmes de répertoire courant.

Les hooks fonctionnent-ils avec les sous-agents ?

Oui. Les hooks se déclenchent aussi pour les actions des sous-agents.4 Si Claude lance un sous-agent via l’outil Agent, vos hooks PreToolUse et PostToolUse s’exécutent pour chaque outil qu’utilise ce sous-agent. Sans application récursive, un sous-agent pourrait contourner vos garde-fous. L’événement SubagentStop vous permet de lancer un nettoyage ou une validation dès qu’un sous-agent achève sa tâche.4

Combien de hooks, c’est trop ?

C’est la performance qui contraint, pas le nombre. Chaque hook tourne de façon synchrone : le temps d’exécution total s’ajoute donc à chaque appel d’outil correspondant. Je fais tourner 95 hooks répartis entre les paramètres utilisateur et projet sans latence perceptible, parce que chaque hook s’achève en moins de 200 ms. Le seuil que je surveille : si un hook PostToolUse ajoute plus de 500 ms à chaque édition de fichier, la session paraît poussive. Profilez vos hooks avec time avant de les déployer. Dix hooks rapides valent mieux que deux lents.


  1. Anthropic, “Hooks reference — Hook events.” code.claude.com/docs/en/hooks#hook-events 

  2. Anthropic, “Hooks reference — Exit code output.” code.claude.com/docs/en/hooks#exit-code-output 

  3. Anthropic, “Hooks reference — Configuration.” code.claude.com/docs/en/hooks#configuration 

  4. Anthropic, “Hooks reference — Hook events” (SubagentStart/SubagentStop). code.claude.com/docs/en/hooks#hook-events 

  5. Anthropic, “Hooks reference — Configuration” (le menu /hooks). code.claude.com/docs/en/hooks#configuration 

  6. Anthropic, “Hooks reference — Hook input and output.” code.claude.com/docs/en/hooks#hook-input-and-output 

  7. Anthropic, “Hooks reference — Configuration” (le schéma de hook imbriqué). code.claude.com/docs/en/hooks#configuration 

  8. Documentation Git, “Customizing Git: Git Hooks.” git-scm.com/book/en/v2/Customizing-Git-Git-Hooks 

  9. Manuel jq, “Command-line JSON processor.” jqlang.github.io/jq/manual 

Articles connexes

Les hooks de Claude Code expliqués : la couche déterministe autour de votre agent

Les hooks de Claude Code exécutent des commandes shell aux événements du cycle de vie — c'est garanti. Chaque événement,…

24 min de lecture

Hooks Claude Code : pourquoi chacun de mes 95 hooks existe

J'ai construit 95 hooks pour Claude Code. Chacun existe parce que quelque chose a mal tourné. Voici leurs origines et l'…

12 min de lecture