Configurer votre premier hook
Pour créer un hook, ajoutez un blochooks à un fichier de paramètres. Cette procédure crée un hook de notification de bureau, afin que vous soyez alerté chaque fois que Claude attend votre entrée au lieu de regarder le terminal.
Ajouter le hook à vos paramètres
Ouvrez Si votre fichier de paramètres a déjà une clé Vous pouvez également demander à Claude d’écrire le hook pour vous en décrivant ce que vous voulez dans le CLI.
~/.claude/settings.json et ajoutez un hook Notification. L’exemple ci-dessous utilise osascript pour macOS ; consultez Être notifié lorsque Claude a besoin d’une entrée pour les commandes Linux et Windows.hooks, ajoutez Notification comme frère des clés d’événement existantes plutôt que de remplacer l’objet entier. Chaque nom d’événement est une clé à l’intérieur du seul objet hooks :Vérifier la configuration
Tapez
/hooks pour ouvrir le navigateur des hooks. Vous verrez une liste de tous les événements de hook disponibles, avec un nombre à côté de chaque événement qui a des hooks configurés. Sélectionnez Notification pour confirmer que votre nouveau hook apparaît dans la liste. La sélection du hook affiche ses détails : l’événement, le matcher, le type, le fichier source et la commande.Ce que vous pouvez automatiser
Les hooks vous permettent d’exécuter du code à des points clés du cycle de vie de Claude Code : formater les fichiers après les modifications, bloquer les commandes avant leur exécution, envoyer des notifications lorsque Claude a besoin d’une entrée, injecter du contexte au démarrage de la session, et bien plus. Pour la liste complète des événements de hook, consultez la référence des Hooks. Chaque exemple inclut un bloc de configuration prêt à l’emploi que vous ajoutez à un fichier de paramètres. Les modèles les plus courants :- Être notifié lorsque Claude a besoin d’une entrée
- Formater automatiquement le code après les modifications
- Bloquer les modifications des fichiers protégés
- Réinjecter le contexte après compaction
- Auditer les modifications de configuration
- Recharger l’environnement lorsque le répertoire ou les fichiers changent
- Approuver automatiquement les invites de permission spécifiques
Être notifié lorsque Claude a besoin d’une entrée
Recevez une notification de bureau chaque fois que Claude termine son travail et a besoin de votre entrée, afin que vous puissiez passer à d’autres tâches sans vérifier le terminal. Ce hook utilise l’événementNotification, qui se déclenche lorsque Claude attend une entrée ou une permission. Chaque onglet ci-dessous utilise la commande de notification native de la plateforme. Ajoutez ceci à ~/.claude/settings.json :
- macOS
- Linux
- Windows (PowerShell)
Si aucune notification n'apparaît
Si aucune notification n'apparaît
osascript achemine les notifications via l’application Script Editor intégrée. Si Script Editor n’a pas la permission de notification, la commande échoue silencieusement, et macOS ne vous demandera pas de l’accorder. Exécutez ceci dans Terminal une fois pour que Script Editor apparaisse dans vos paramètres de notification :Formater automatiquement le code après les modifications
Exécutez automatiquement Prettier sur chaque fichier que Claude modifie, afin que le formatage reste cohérent sans intervention manuelle. Ce hook utilise l’événementPostToolUse avec un matcher Edit|Write, il s’exécute donc uniquement après les outils d’édition de fichiers. La commande extrait le chemin du fichier modifié avec jq et le transmet à Prettier. Ajoutez ceci à .claude/settings.json à la racine de votre projet :
Les exemples Bash sur cette page utilisent
jq pour l’analyse JSON. Installez-le avec brew install jq (macOS), apt-get install jq (Debian/Ubuntu), ou consultez les téléchargements de jq.Bloquer les modifications des fichiers protégés
Empêchez Claude de modifier les fichiers sensibles comme.env, package-lock.json, ou n’importe quoi dans .git/. Claude reçoit un retour expliquant pourquoi la modification a été bloquée, afin qu’il puisse ajuster son approche.
Cet exemple utilise un fichier de script séparé que le hook appelle. Le script vérifie le chemin du fichier cible par rapport à une liste de modèles protégés et quitte avec le code 2 pour bloquer la modification.
Rendre le script exécutable (macOS/Linux)
Les scripts de hook doivent être exécutables pour que Claude Code les exécute :
Réinjecter le contexte après compaction
Lorsque la fenêtre de contexte de Claude se remplit, la compaction résume la conversation pour libérer de l’espace. Cela peut perdre des détails importants. Utilisez un hookSessionStart avec un matcher compact pour réinjecter le contexte critique après chaque compaction.
Tout texte que votre commande écrit sur stdout est ajouté au contexte de Claude. Cet exemple rappelle à Claude les conventions du projet et le travail récent. Ajoutez ceci à .claude/settings.json à la racine de votre projet :
echo par n’importe quelle commande qui produit une sortie dynamique, comme git log --oneline -5 pour afficher les commits récents. Pour injecter du contexte au démarrage de chaque session, envisagez d’utiliser CLAUDE.md à la place. Pour les variables d’environnement, consultez CLAUDE_ENV_FILE dans la référence.
Auditer les modifications de configuration
Suivez quand les fichiers de paramètres ou de skills changent pendant une session. L’événementConfigChange se déclenche lorsqu’un processus externe ou un éditeur modifie un fichier de configuration, afin que vous puissiez enregistrer les modifications pour la conformité ou bloquer les modifications non autorisées.
Cet exemple ajoute chaque modification à un journal d’audit. Ajoutez ceci à ~/.claude/settings.json :
user_settings, project_settings, local_settings, policy_settings, ou skills. Pour bloquer une modification de prendre effet, quittez avec le code 2 ou retournez {"decision": "block"}. Consultez la référence ConfigChange pour le schéma d’entrée complet.
Recharger l’environnement lorsque le répertoire ou les fichiers changent
Certains projets définissent des variables d’environnement différentes selon le répertoire dans lequel vous vous trouvez. Des outils comme direnv le font automatiquement dans votre shell, mais l’outil Bash de Claude ne récupère pas ces modifications de lui-même. L’association d’un hookSessionStart avec un hook CwdChanged corrige cela. SessionStart charge les variables pour le répertoire dans lequel vous lancez, et CwdChanged les recharge chaque fois que Claude change de répertoire. Les deux écrivent dans CLAUDE_ENV_FILE, que Claude Code exécute comme un préambule de script avant chaque commande Bash. Ajoutez ceci à ~/.claude/settings.json :
direnv allow une fois dans chaque répertoire qui a un .envrc afin que direnv soit autorisé à le charger. Si vous utilisez devbox ou nix à la place de direnv, le même modèle fonctionne avec devbox shellenv ou devbox global shellenv à la place de direnv export bash.
Pour réagir à des fichiers spécifiques au lieu de chaque changement de répertoire, utilisez FileChanged avec un matcher listant les noms de fichiers à surveiller, séparés par |. Pour construire la liste de surveillance, cette valeur est divisée en noms de fichiers littéraux plutôt qu’évaluée comme une regex. Consultez FileChanged pour savoir comment la même valeur filtre également les groupes de hooks qui s’exécutent lorsqu’un fichier change. Cet exemple surveille .envrc et .env dans le répertoire de travail :
watchPaths, et les détails de CLAUDE_ENV_FILE.
Approuver automatiquement les invites de permission spécifiques
Ignorez la boîte de dialogue d’approbation pour les appels d’outils que vous autorisez toujours. Cet exemple approuve automatiquementExitPlanMode, l’outil que Claude appelle lorsqu’il termine de présenter un plan et demande de procéder, afin que vous ne soyez pas invité à chaque fois qu’un plan est prêt.
Contrairement aux exemples de code de sortie ci-dessus, l’approbation automatique nécessite que votre hook écrive une décision JSON sur stdout. Un hook PermissionRequest se déclenche lorsque Claude Code est sur le point d’afficher une boîte de dialogue de permission, et retourner "behavior": "allow" y répond en votre nom.
Le matcher limite le hook à ExitPlanMode uniquement, afin qu’aucune autre invite ne soit affectée. Ajoutez ceci à ~/.claude/settings.json :
updatedPermissions avec une entrée setMode. La valeur mode est n’importe quel mode de permission comme default, acceptEdits, ou bypassPermissions, et destination: "session" l’applique pour la session actuelle uniquement.
bypassPermissions ne s’applique que si la session a été lancée avec le mode bypass déjà disponible : --dangerously-skip-permissions, --permission-mode bypassPermissions, --allow-dangerously-skip-permissions, ou permissions.defaultMode: "bypassPermissions" dans les paramètres, et non désactivé par permissions.disableBypassPermissionsMode. Il n’est jamais persisté en tant que defaultMode.acceptEdits, votre hook écrit ce JSON sur stdout :
.* ou laisser le matcher vide approuverait automatiquement chaque invite de permission, y compris les écritures de fichiers et les commandes shell. Consultez la référence PermissionRequest pour l’ensemble complet des champs de décision.
Comment fonctionnent les hooks
Les événements de hook se déclenchent à des points spécifiques du cycle de vie de Claude Code. Lorsqu’un événement se déclenche, tous les hooks correspondants s’exécutent en parallèle, et les commandes de hook identiques sont automatiquement dédupliquées. Le tableau ci-dessous montre chaque événement et quand il se déclenche :| Event | When it fires |
|---|---|
SessionStart | When a session begins or resumes |
UserPromptSubmit | When you submit a prompt, before Claude processes it |
UserPromptExpansion | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
PreToolUse | Before a tool call executes. Can block it |
PermissionRequest | When a permission dialog appears |
PermissionDenied | When a tool call is denied by the auto mode classifier. Return {retry: true} to tell the model it may retry the denied tool call |
PostToolUse | After a tool call succeeds |
PostToolUseFailure | After a tool call fails |
Notification | When Claude Code sends a notification |
SubagentStart | When a subagent is spawned |
SubagentStop | When a subagent finishes |
TaskCreated | When a task is being created via TaskCreate |
TaskCompleted | When a task is being marked as completed |
Stop | When Claude finishes responding |
StopFailure | When the turn ends due to an API error. Output and exit code are ignored |
TeammateIdle | When an agent team teammate is about to go idle |
InstructionsLoaded | When a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded during a session |
ConfigChange | When a configuration file changes during a session |
CwdChanged | When the working directory changes, for example when Claude executes a cd command. Useful for reactive environment management with tools like direnv |
FileChanged | When a watched file changes on disk. The matcher field specifies which filenames to watch |
WorktreeCreate | When a worktree is being created via --worktree or isolation: "worktree". Replaces default git behavior |
WorktreeRemove | When a worktree is being removed, either at session exit or when a subagent finishes |
PreCompact | Before context compaction |
PostCompact | After context compaction completes |
Elicitation | When an MCP server requests user input during a tool call |
ElicitationResult | After a user responds to an MCP elicitation, before the response is sent back to the server |
SessionEnd | When a session terminates |
PreToolUse retournant deny annule l’appel d’outil peu importe ce que les autres retournent. Un hook retournant ask force l’invite de permission même si le reste retourne allow. Le texte de additionalContext est conservé de chaque hook et transmis à Claude ensemble.
Chaque hook a un type qui détermine comment il s’exécute. La plupart des hooks utilisent "type": "command", qui exécute une commande shell. Trois autres types sont disponibles :
"type": "http": POST les données d’événement vers une URL. Consultez Hooks HTTP."type": "prompt": évaluation LLM à un seul tour. Consultez Hooks basés sur des invites."type": "agent": vérification multi-tour avec accès aux outils. Les hooks d’agent sont expérimentaux et peuvent changer. Consultez Hooks basés sur des agents.
Lire l’entrée et retourner la sortie
Les hooks communiquent avec Claude Code via stdin, stdout, stderr et les codes de sortie. Lorsqu’un événement se déclenche, Claude Code transmet les données spécifiques à l’événement en JSON à stdin de votre script. Votre script lit ces données, fait son travail, et dit à Claude Code quoi faire ensuite via le code de sortie.Entrée du hook
Chaque événement inclut des champs communs commesession_id et cwd, mais chaque type d’événement ajoute des données différentes. Par exemple, lorsque Claude exécute une commande Bash, un hook PreToolUse reçoit quelque chose comme ceci sur stdin :
UserPromptSubmit obtiennent le texte prompt à la place, les hooks SessionStart obtiennent la source (startup, resume, clear, compact), et ainsi de suite. Consultez Champs d’entrée communs dans la référence pour les champs partagés, et la section de chaque événement pour les schémas spécifiques à l’événement.
Sortie du hook
Votre script dit à Claude Code quoi faire ensuite en écrivant sur stdout ou stderr et en quittant avec un code spécifique. Par exemple, un hookPreToolUse qui veut bloquer une commande :
- Exit 0 : l’action se poursuit. Pour les hooks
UserPromptSubmitetSessionStart, tout ce que vous écrivez sur stdout est ajouté au contexte de Claude. - Exit 2 : l’action est bloquée. Écrivez une raison sur stderr, et Claude la reçoit comme retour afin qu’il puisse s’ajuster.
- Tout autre code de sortie : l’action se poursuit. La transcription affiche un avis
<hook name> hook errorsuivi de la première ligne de stderr ; le stderr complet va au journal de débogage.
Sortie JSON structurée
Les codes de sortie vous donnent deux options : autoriser ou bloquer. Pour plus de contrôle, quittez 0 et imprimez un objet JSON sur stdout à la place.Utilisez exit 2 pour bloquer avec un message stderr, ou exit 0 avec JSON pour un contrôle structuré. Ne les mélangez pas : Claude Code ignore JSON lorsque vous quittez 2.
PreToolUse peut refuser un appel d’outil et dire à Claude pourquoi, ou l’escalader à l’utilisateur pour approbation :
"deny", Claude Code annule l’appel d’outil et renvoie permissionDecisionReason à Claude. Ces valeurs permissionDecision sont spécifiques à PreToolUse :
"allow": ignorer l’invite de permission interactive. Les règles de refus et d’ask, y compris les listes de refus gérées par l’entreprise, s’appliquent toujours"deny": annuler l’appel d’outil et envoyer la raison à Claude"ask": afficher l’invite de permission à l’utilisateur comme d’habitude
"defer", est disponible en mode non-interactif avec le drapeau -p. Elle quitte le processus avec l’appel d’outil préservé afin qu’un wrapper SDK Agent puisse collecter l’entrée et reprendre. Consultez Différer un appel d’outil pour plus tard dans la référence.
Retourner "allow" ignore l’invite interactive mais ne remplace pas les règles de permission. Si une règle de refus correspond à l’appel d’outil, l’appel est bloqué même lorsque votre hook retourne "allow". Si une règle d’ask correspond, l’utilisateur est toujours invité. Cela signifie que les règles de refus de n’importe quel périmètre de paramètres, y compris les paramètres gérés, ont toujours la priorité sur les approbations de hook.
D’autres événements utilisent des modèles de décision différents. Par exemple, les hooks PostToolUse et Stop utilisent un champ decision: "block" au niveau supérieur, tandis que PermissionRequest utilise hookSpecificOutput.decision.behavior. Consultez le tableau récapitulatif dans la référence pour une ventilation complète par événement.
Pour les hooks UserPromptSubmit, utilisez additionalContext à la place pour injecter du texte dans le contexte de Claude. Les hooks basés sur des invites (type: "prompt") gèrent la sortie différemment : consultez Hooks basés sur des invites.
Filtrer les hooks avec des matchers
Sans matcher, un hook se déclenche à chaque occurrence de son événement. Les matchers vous permettent de réduire cela. Par exemple, si vous voulez exécuter un formateur uniquement après les modifications de fichiers (pas après chaque appel d’outil), ajoutez un matcher à votre hookPostToolUse :
"Edit|Write" se déclenche uniquement lorsque Claude utilise l’outil Edit ou Write, pas lorsqu’il utilise Bash, Read, ou tout autre outil. Consultez Modèles de matcher pour savoir comment les noms simples et les expressions régulières sont évalués.
Chaque type d’événement correspond à un champ spécifique :
| Événement | Ce que le matcher filtre | Exemples de valeurs de matcher |
|---|---|---|
PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied | nom de l’outil | Bash, Edit|Write, mcp__.* |
SessionStart | comment la session a démarré | startup, resume, clear, compact |
SessionEnd | pourquoi la session s’est terminée | clear, resume, logout, prompt_input_exit, bypass_permissions_disabled, other |
Notification | type de notification | permission_prompt, idle_prompt, auth_success, elicitation_dialog |
SubagentStart | type d’agent | Bash, Explore, Plan, ou noms d’agents personnalisés |
PreCompact, PostCompact | ce qui a déclenché la compaction | manual, auto |
SubagentStop | type d’agent | mêmes valeurs que SubagentStart |
ConfigChange | source de configuration | user_settings, project_settings, local_settings, policy_settings, skills |
StopFailure | type d’erreur | rate_limit, authentication_failed, billing_error, invalid_request, server_error, max_output_tokens, unknown |
InstructionsLoaded | raison du chargement | session_start, nested_traversal, path_glob_match, include, compact |
Elicitation | nom du serveur MCP | vos noms de serveur MCP configurés |
ElicitationResult | nom du serveur MCP | mêmes valeurs que Elicitation |
FileChanged | noms de fichiers littéraux à surveiller (consultez FileChanged) | .envrc|.env |
UserPromptSubmit, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, CwdChanged | pas de support de matcher | se déclenche toujours à chaque occurrence |
- Enregistrer chaque commande Bash
- Correspondre aux outils MCP
- Nettoyer à la fin de la session
Correspond uniquement aux appels d’outil
Bash et enregistre chaque commande dans un fichier. L’événement PostToolUse se déclenche après la fin de la commande, donc tool_input.command contient ce qui a été exécuté. Le hook reçoit les données d’événement en JSON sur stdin, et jq -r '.tool_input.command' extrait juste la chaîne de commande, que >> ajoute au fichier journal :Filtrer par nom d’outil et arguments avec le champ if
Le champ
if nécessite Claude Code v2.1.85 ou ultérieur. Les versions antérieures l’ignorent et exécutent le hook à chaque appel correspondant.if utilise la syntaxe des règles de permission pour filtrer les hooks par nom d’outil et arguments ensemble, afin que le processus du hook ne soit généré que lorsque l’appel d’outil correspond, ou lorsqu’une commande Bash est trop complexe à analyser. Cela va au-delà du matcher, qui filtre au niveau du groupe par nom d’outil uniquement.
Par exemple, pour exécuter un hook uniquement lorsque Claude utilise des commandes git plutôt que toutes les commandes Bash :
git *, ou lorsque la commande est trop complexe à analyser en sous-commandes. Pour les commandes composées comme npm test && git push, Claude Code évalue chaque sous-commande et déclenche le hook car git push correspond. Le champ if accepte les mêmes modèles que les règles de permission : "Bash(git *)", "Edit(*.ts)", et ainsi de suite. Pour correspondre à plusieurs noms d’outils, utilisez des gestionnaires séparés chacun avec sa propre valeur if, ou correspondez au niveau du matcher où l’alternation par pipe est supportée.
if ne fonctionne que sur les événements d’outils : PreToolUse, PostToolUse, PostToolUseFailure, et PermissionRequest. L’ajouter à tout autre événement empêche le hook de s’exécuter.
Configurer l’emplacement du hook
L’endroit où vous ajoutez un hook détermine son périmètre :| Emplacement | Périmètre | Partageable |
|---|---|---|
~/.claude/settings.json | Tous vos projets | Non, local à votre machine |
.claude/settings.json | Projet unique | Oui, peut être commité au repo |
.claude/settings.local.json | Projet unique | Non, gitignored |
| Paramètres de politique gérés | À l’échelle de l’organisation | Oui, contrôlé par l’administrateur |
Plugin hooks/hooks.json | Lorsque le plugin est activé | Oui, fourni avec le plugin |
| Skill ou agent frontmatter | Pendant que le skill ou l’agent est actif | Oui, défini dans le fichier du composant |
/hooks dans Claude Code pour parcourir tous les hooks configurés regroupés par événement. Pour désactiver tous les hooks à la fois, définissez "disableAllHooks": true dans votre fichier de paramètres.
Si vous modifiez les fichiers de paramètres directement pendant que Claude Code s’exécute, l’observateur de fichiers récupère normalement les modifications de hook automatiquement.
Hooks basés sur des invites
Pour les décisions qui nécessitent un jugement plutôt que des règles déterministes, utilisez les hookstype: "prompt". Au lieu d’exécuter une commande shell, Claude Code envoie votre invite et les données d’entrée du hook à un modèle Claude (Haiku par défaut) pour prendre la décision. Vous pouvez spécifier un modèle différent avec le champ model si vous avez besoin de plus de capacité.
Le seul travail du modèle est de retourner une décision oui/non en JSON :
"ok": true: l’action se poursuit"ok": false: l’action est bloquée. La"reason"du modèle est renvoyée à Claude afin qu’il puisse s’ajuster.
Stop pour demander au modèle si toutes les tâches demandées sont complètes. Si le modèle retourne "ok": false, Claude continue à travailler et utilise la reason comme sa prochaine instruction :
Hooks basés sur des agents
Lorsque la vérification nécessite d’inspecter des fichiers ou d’exécuter des commandes, utilisez les hookstype: "agent". Contrairement aux hooks d’invite qui font un seul appel LLM, les hooks d’agent génèrent un subagent qui peut lire des fichiers, rechercher du code et utiliser d’autres outils pour vérifier les conditions avant de retourner une décision.
Les hooks d’agent utilisent le même format de réponse "ok" / "reason" que les hooks d’invite, mais avec un délai d’expiration par défaut plus long de 60 secondes et jusqu’à 50 tours d’utilisation d’outils.
Cet exemple vérifie que les tests réussissent avant de permettre à Claude de s’arrêter :
Hooks HTTP
Utilisez les hookstype: "http" pour POST les données d’événement vers un point de terminaison HTTP au lieu d’exécuter une commande shell. Le point de terminaison reçoit le même JSON qu’un hook de commande recevrait sur stdin, et retourne les résultats via le corps de la réponse HTTP en utilisant le même format JSON.
Les hooks HTTP sont utiles lorsque vous voulez qu’un serveur web, une fonction cloud ou un service externe gère la logique du hook : par exemple, un service d’audit partagé qui enregistre les événements d’utilisation d’outils dans une équipe.
Cet exemple poste chaque utilisation d’outil vers un service de journalisation local :
hookSpecificOutput appropriés. Les codes de statut HTTP seuls ne peuvent pas bloquer les actions.
Les valeurs d’en-tête supportent l’interpolation de variables d’environnement en utilisant la syntaxe $VAR_NAME ou ${VAR_NAME}. Seules les variables listées dans le tableau allowedEnvVars sont résolues ; toutes les autres références $VAR restent vides.
Pour les options de configuration complètes et la gestion des réponses, consultez Hooks HTTP dans la référence.
Limitations et dépannage
Limitations
- Les hooks de commande communiquent uniquement via stdout, stderr et les codes de sortie. Ils ne peuvent pas déclencher directement des commandes
/ou des appels d’outils. Le texte retourné viaadditionalContextest injecté comme un rappel système que Claude lit en tant que texte brut. Les hooks HTTP communiquent via le corps de la réponse à la place. - Le délai d’expiration du hook est de 10 minutes par défaut, configurable par hook avec le champ
timeout(en secondes). - Les hooks
PostToolUsene peuvent pas annuler les actions puisque l’outil a déjà été exécuté. - Les hooks
PermissionRequestne se déclenchent pas en mode non-interactif (-p). Utilisez les hooksPreToolUsepour les décisions de permission automatisées. - Les hooks
Stopse déclenchent chaque fois que Claude termine sa réponse, pas seulement à la fin de la tâche. Ils ne se déclenchent pas sur les interruptions de l’utilisateur. Les erreurs API déclenchent StopFailure à la place. - Lorsque plusieurs hooks PreToolUse retournent
updatedInputpour réécrire les arguments d’un outil, le dernier à terminer gagne. Puisque les hooks s’exécutent en parallèle, l’ordre est non-déterministe. Évitez d’avoir plus d’un hook modifier l’entrée du même outil.
Hooks et modes de permission
Les hooks PreToolUse se déclenchent avant toute vérification du mode de permission. Un hook qui retournepermissionDecision: "deny" bloque l’outil même en mode bypassPermissions ou avec --dangerously-skip-permissions. Cela vous permet d’appliquer une politique que les utilisateurs ne peuvent pas contourner en changeant leur mode de permission.
L’inverse n’est pas vrai : un hook retournant "allow" ne contourne pas les règles de refus des paramètres. Les hooks peuvent renforcer les restrictions mais pas les assouplir au-delà de ce que les règles de permission permettent.
Hook ne se déclenche pas
Le hook est configuré mais ne s’exécute jamais.- Exécutez
/hookset confirmez que le hook apparaît sous l’événement correct - Vérifiez que le modèle de matcher correspond exactement au nom de l’outil (les matchers sont sensibles à la casse)
- Vérifiez que vous déclenchez le bon type d’événement (par exemple,
PreToolUsese déclenche avant l’exécution de l’outil,PostToolUsese déclenche après) - Si vous utilisez des hooks
PermissionRequesten mode non-interactif (-p), passez àPreToolUseà la place
Erreur du hook dans la sortie
Vous voyez un message comme « PreToolUse hook error : … » dans la transcription.- Votre script a quitté avec un code non-zéro de manière inattendue. Testez-le manuellement en piping du JSON d’exemple :
- Si vous voyez « command not found », utilisez des chemins absolus ou
$CLAUDE_PROJECT_DIRpour référencer les scripts - Si vous voyez « jq: command not found », installez
jqou utilisez Python/Node.js pour l’analyse JSON - Si le script ne s’exécute pas du tout, rendez-le exécutable :
chmod +x ./my-hook.sh
/hooks n’affiche aucun hook configuré
Vous avez modifié un fichier de paramètres mais les hooks n’apparaissent pas dans le menu.
- Les modifications de fichiers sont normalement récupérées automatiquement. Si elles n’ont pas apparues après quelques secondes, l’observateur de fichiers peut avoir manqué la modification : redémarrez votre session pour forcer un rechargement.
- Vérifiez que votre JSON est valide (les virgules finales et les commentaires ne sont pas autorisés)
- Confirmez que le fichier de paramètres est au bon emplacement :
.claude/settings.jsonpour les hooks de projet,~/.claude/settings.jsonpour les hooks globaux
Le hook Stop s’exécute indéfiniment
Claude continue à travailler dans une boucle infinie au lieu de s’arrêter. Votre script de hook Stop doit vérifier s’il a déjà déclenché une continuation. Analysez le champstop_hook_active de l’entrée JSON et quittez tôt s’il est true :
Validation JSON échouée
Claude Code affiche une erreur d’analyse JSON même si votre script de hook produit du JSON valide. Lorsque Claude Code exécute un hook, il génère un shell qui source votre profil (~/.zshrc ou ~/.bashrc). Si votre profil contient des instructions echo inconditionnelles, cette sortie est ajoutée au début de votre JSON du hook :
$- contient les drapeaux du shell, et i signifie interactif. Les hooks s’exécutent dans des shells non-interactifs, donc l’echo est ignoré.
Techniques de débogage
La vue de transcription, basculée avecCtrl+O, affiche un résumé d’une ligne pour chaque hook qui s’est déclenché : le succès est silencieux, les erreurs de blocage affichent stderr, et les erreurs sans blocage affichent un avis <hook name> hook error suivi de la première ligne de stderr.
Pour les détails d’exécution complets incluant les hooks qui ont correspondu, leurs codes de sortie, stdout et stderr, lisez le journal de débogage. Démarrez Claude Code avec claude --debug-file /tmp/claude.log pour écrire dans un chemin connu, puis tail -f /tmp/claude.log dans un autre terminal. Si vous avez démarré sans ce drapeau, exécutez /debug en milieu de session pour activer la journalisation et trouver le chemin du journal.
En savoir plus
- Référence des Hooks : schémas d’événements complets, format de sortie JSON, hooks asynchrones et hooks d’outils MCP
- Considérations de sécurité : examinez avant de déployer les hooks dans des environnements partagés ou de production
- Exemple de validateur de commande Bash : implémentation de référence complète