KURSE / CLAUDE-CODE / MODUL 9

Hooks : des garde-fous et automatismes qui s'exécutent à coup sûr

⚠ Diese Seite ist noch nicht uebersetzt. Anzeige auf Englisch.
← Claude Code: vom Einsteiger zum Experten
Modul 9/12 Fortgeschritten 20 min

Hooks : des garde-fous et automatismes qui s'exécutent à coup sûr

Automatisez formatage, protections et notifications dans Claude Code grâce aux hooks : événements, codes de sortie, recettes prêtes à l'emploi et débogage.

Ziele dieses Moduls
  • Configurer un hook dans settings.json en choisissant l'événement et le matcher adaptés
  • Bloquer les actions dangereuses avec un hook PreToolUse et le code de sortie 2
  • Automatiser le formatage du code et les notifications de fin de tâche

Vous avez déjà écrit dans votre CLAUDE.md : « pense à formater le code après chaque modification » ? Parfois Claude le fait. Parfois il oublie. Une consigne en langage naturel reste une probabilité, jamais une certitude. Dans ce module, vous allez transformer vos consignes en automatismes : les hooks exécutent vos propres commandes, à coup sûr, aux moments clés de chaque session.

Ce que vous allez apprendre

  • Comprendre pourquoi un hook est plus fiable qu’une consigne écrite
  • Choisir le bon événement du cycle de vie : PreToolUse, PostToolUse, Stop et les autres
  • Écrire un hook complet dans settings.json : événement, matcher, commande
  • Bloquer une action dangereuse grâce au code de sortie 2
  • Mettre en place trois recettes concrètes : formatage automatique, protection des secrets, notifications

Demander gentiment n’est pas une garantie

Posons le décor. Depuis plusieurs modules, vous savez donner à Claude Code des consignes durables dans le fichier CLAUDE.md. Et cela fonctionne bien. Mais soyons honnêtes : une consigne écrite est une demande, pas un contrat. Claude la lit, la comprend, et la suit… la plupart du temps. Quand la session s’allonge et que le contexte se remplit, il peut passer à côté. Ce n’est pas un caprice : un modèle de langage raisonne en probabilités, comme nous l’expliquons dans notre dossier IA.

Un hook change complètement la donne. Le mot anglais signifie « crochet » : un point d’accroche dans le cycle de vie de Claude Code, c’est-à-dire la suite d’étapes que traverse chaque session — démarrage, prompt, outils, réponse, fin. Sur chacun de ces points d’accroche, vous pouvez brancher une commande shell : une instruction exécutée par votre terminal, exactement comme si vous l’aviez tapée vous-même. La différence est fondamentale. Ce n’est plus Claude qui décide de formater votre code. C’est Claude Code, le logiciel, qui exécute votre commande. Automatiquement. À chaque fois. Sans exception.

Une image du quotidien : la consigne « pense à fermer la porte » dépend de la mémoire de chacun. Le groom de porte, ce bras mécanique qui la referme tout seul, ne dépend de personne. Un hook, c’est le groom de porte de votre projet. Et si un terme technique vous échappe en cours de route, gardez notre glossaire ouvert dans un onglet.

Neuf événements pour agir au bon moment

Un hook s’accroche toujours à un événement : un moment précis du cycle de vie. Petit rappel au passage : un outil, dans Claude Code, c’est une capacité concrète de l’agent — lire un fichier, en écrire un, lancer une commande. Voici les principaux événements, avec un cas d’usage typique pour chacun.

ÉvénementQuand se déclenche-t-il ?Cas d’usage typique
PreToolUseJuste avant qu’un outil s’exécute — peut bloquer l’actionInterdire la modification de fichiers sensibles
PostToolUseJuste après qu’un outil a réussiFormater ou vérifier le fichier modifié
UserPromptSubmitQuand vous validez un promptInjecter du contexte, filtrer certaines demandes
NotificationQuand Claude Code réclame votre attentionNotification sur le bureau
StopQuand Claude a fini de répondreNotification de fin, vérification globale
SubagentStopQuand un sous-agent termine sa tâcheJournaliser le travail délégué
PreCompactAvant le compactage du contexteSauvegarder la transcription complète
SessionStartAu démarrage ou à la reprise d’une sessionCharger l’état du projet, la branche git
SessionEndÀ la fermeture de la sessionNettoyage, journal de bord

Retenez surtout le duo star. PreToolUse est un vigile : il voit l’action arriver et peut lui barrer la route. PostToolUse est un concierge : il passe derrière et remet tout en ordre. La quasi-totalité de vos hooks utiliseront l’un ou l’autre.

L’anatomie d’un hook dans settings.json

Les hooks se déclarent dans settings.json, le fichier de configuration que vous connaissez depuis le module sur les permissions. Trois emplacements possibles : ~/.claude/settings.json pour vos réglages personnels, .claude/settings.json pour le projet, et .claude/settings.local.json pour vos réglages de projet non partagés.

La structure a trois étages. L’événement, d’abord. Puis le matcher — littéralement « celui qui fait correspondre » — un filtre qui précise quels outils déclenchent le hook. Enfin, la ou les commandes. Regardez ce squelette :

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "votre-commande-ici" }
        ]
      }
    ]
  }
}

Le matcher Edit|Write se lit « Edit ou Write » : le hook se déclenche pour l’outil d’édition comme pour l’outil d’écriture de fichiers. Un nom seul, comme Bash, cible un outil précis. Un matcher vide, ou une étoile, cible tout.

Au moment de s’exécuter, votre commande reçoit un colis : une description au format JSON — du texte structuré, lisible par les machines — envoyée sur son entrée standard, le canal appelé stdin par lequel un programme reçoit des données. Voici à quoi ressemble ce colis pour un PreToolUse :

{
  "session_id": "abc123",
  "cwd": "/home/vous/mon-projet",
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": { "file_path": "/home/vous/mon-projet/.env" }
}

Tout y est : quel outil, quel fichier, quelle session. Votre commande dispose de 60 secondes par défaut pour faire son travail ; ce délai se règle hook par hook si besoin.

💡 Astuce — pour lire ce JSON dans un script, l’outil jq est votre meilleur ami. C’est un petit utilitaire en ligne de commande qui extrait n’importe quel champ d’un JSON. Par exemple, jq -r ‘.tool_input.file_path’ renvoie le chemin du fichier concerné. Toutes nos recettes s’appuient dessus.

💡 Astuce — placez vos hooks d’équipe dans .claude/settings.json, versionné avec git : chaque membre du projet hérite des mêmes garde-fous, sans rien configurer.

Le contrat des codes de sortie

Comment votre commande répond-elle à Claude Code ? Par son code de sortie : le nombre qu’un programme renvoie en se terminant, sa façon de dire « mission accomplie » ou « problème ». Le contrat tient en trois lignes, et il faut le connaître par cœur.

Code 0 : tout va bien. L’action suit son cours normalement.

Code 2 : stop. Sur un PreToolUse, l’action est bloquée avant même de commencer. Et surtout, tout ce que votre script a écrit sur stderr — la sortie d’erreur, le canal réservé aux messages de problème — est transmis à Claude. Il lit votre message, comprend le refus, et adapte sa stratégie. C’est un dialogue, pas seulement un mur.

Tous les autres codes : erreur non bloquante. Le souci est signalé, mais l’action n’est pas empêchée.

⚠️ Piège courant — le code 1, réflexe classique en shell pour dire « erreur », ne bloque rien du tout dans un hook. Si votre garde-fou laisse passer des actions qu’il devrait interdire, vérifiez ce point en premier : seul exit 2 bloque.

Pour les cas plus fins, il existe une sortie JSON avancée : au lieu d’un simple code, votre script imprime un JSON qui décide explicitement allow (autoriser), deny (refuser) ou ask (demander confirmation à l’utilisateur). Gardez cette carte pour plus tard : les codes de sortie couvrent déjà l’immense majorité des besoins.

💡 Astuce — soignez vos messages sur stderr. « Modification refusée : ce fichier contient des secrets, propose une autre approche » aide Claude bien davantage qu’un laconique « interdit ».

Trois recettes prêtes à l’emploi

Passons de la théorie à la pratique, avec trois recettes que vous pourrez réutiliser dans tous vos projets.

Recette 1 : formatage automatique après chaque modification

Prettier est un formateur de code très répandu dans l’écosystème JavaScript : il réindente et harmonise le style d’un fichier, toujours de la même manière. Objectif : le lancer après chaque fichier touché. Événement PostToolUse, matcher Edit|Write, et une commande en deux maillons : jq extrait le chemin du fichier depuis le JSON reçu, puis prettier le formate.

Dans .claude/settings.json :

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

Le maillon xargs fait le pont : il prend le chemin sorti par jq et le donne en argument à prettier. Désormais, chaque fichier modifié par Claude ressort formaté. Sans exception, et sans y penser.

Recette 2 : des fichiers intouchables

Deuxième besoin, côté sécurité : interdire toute modification de vos fichiers sensibles. Le fichier .env, qui stocke vos variables d’environnement — clés d’API, mots de passe de base de données. Les fichiers de credentials, c’est-à-dire d’identifiants. Le dossier secrets/. Créez un petit script .claude/hooks/protege-secrets.sh :

#!/bin/bash
# Bloque toute écriture sur les fichiers sensibles
FICHIER=$(jq -r '.tool_input.file_path // empty')

if echo "$FICHIER" | grep -qE '\.env|credentials|secrets/'; then
  echo "Refusé : $FICHIER est un fichier sensible, ne pas le modifier." >&2
  exit 2
fi
exit 0

Rendez-le exécutable avec chmod +x, puis branchez-le sur PreToolUse :

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protege-secrets.sh"
          }
        ]
      }
    ]
  }
}

La variable CLAUDE_PROJECT_DIR pointe vers la racine de votre projet : le hook fonctionne quel que soit le dossier courant. Sous Windows, ce script bash s’exécute via Git Bash ou WSL. Désormais, si Claude tente d’écrire dans .env, le vigile dit non — et Claude reçoit votre message d’explication.

Recette 3 : être prévenu au bon moment

Troisième recette, côté confort. Claude travaille parfois plusieurs minutes en autonomie. Pendant ce temps, vous faites autre chose — et vous ratez le moment où il attend votre feu vert. Deux événements règlent cela : Notification, quand Claude Code réclame votre attention, et Stop, quand la réponse est terminée. Voici la version macOS, avec la commande osascript qui affiche une notification système :

{
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude attend votre réponse\" with title \"Claude Code\"'"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Tâche terminée\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Sous Linux, remplacez la commande par notify-send suivi du titre et du message. Sous Windows, n’importe quelle commande PowerShell d’affichage de notification fera le même travail. Plus besoin de surveiller le terminal du coin de l’œil : c’est lui qui vous appelle.

Configurer, déboguer… et rester prudent

Deux réflexes pour piloter tout cela. Premier réflexe : la commande /hooks, tapée dans la session, affiche tous les hooks actifs — événement, matcher, commande, et leur provenance : réglages personnels, projet ou local. C’est le moyen le plus sûr de vérifier qu’une modification a bien été prise en compte.

Deuxième réflexe : lancez claude —debug pour voir vos hooks vivre. Ce mode détaillé affiche chaque hook exécuté, le JSON qu’il reçoit et son code de sortie. Quand un hook ne se déclenche pas comme prévu, c’est votre première escale : neuf fois sur dix, le coupable est un matcher mal orthographié ou un script non exécutable.

Un dernier mot, le plus important du module. Un hook est une commande arbitraire, exécutée avec vos droits d’utilisateur. Elle peut lire vos fichiers, en supprimer, appeler Internet. C’est sa force. C’est aussi son risque.

⚠️ Piège courant — vous clonez un dépôt trouvé en ligne et l’ouvrez avec Claude Code : les hooks définis dans son .claude/settings.json sont des commandes écrites par quelqu’un d’autre, exécutées chez vous, avec vos droits. Prenez trente secondes pour relire ce fichier avant de travailler dans un projet que vous n’avez pas créé. Trente secondes qui peuvent éviter de gros dégâts.

À vous de jouer

Place à la pratique : installez les deux garde-fous du module et vérifiez qu’ils tiennent leurs promesses.

  1. Dans un projet de test contenant du JavaScript, créez le fichier .claude/settings.json et copiez-y la recette 1, avec PostToolUse et prettier. Vérifiez que jq est disponible sur votre machine.
  2. Lancez claude, puis demandez une petite modification volontairement mal indentée dans un fichier. Ouvrez ce fichier : il est parfaitement formaté. Le concierge est passé derrière.
  3. Créez le script .claude/hooks/protege-secrets.sh de la recette 2, rendez-le exécutable avec chmod +x, puis ajoutez le bloc PreToolUse dans votre settings.json.
  4. Créez un fichier .env factice contenant une fausse clé, par exemple API_KEY=test123. Demandez ensuite à Claude d’ajouter une variable DEBUG=true dans ce fichier .env.
  5. Observez le refus : l’écriture est bloquée, et Claude vous explique qu’il ne peut pas modifier ce fichier — il a reçu votre message stderr. Le garde-fou fonctionne vraiment.
  6. Pour finir, relancez la même expérience avec claude —debug et regardez, en direct, le hook recevoir son JSON et renvoyer son code 2.

En résumé

  • Une consigne en langage naturel est une probabilité ; un hook est une certitude : votre commande shell, exécutée automatiquement à un moment précis du cycle de vie.
  • Les événements clés : PreToolUse avant un outil — le seul moment pour bloquer —, PostToolUse après, plus UserPromptSubmit, Notification, Stop, SubagentStop, PreCompact, SessionStart et SessionEnd.
  • Un hook se déclare dans settings.json : un événement, un matcher comme Edit|Write, une commande ; il reçoit un JSON descriptif sur stdin et dispose de 60 secondes par défaut.
  • Le contrat des codes de sortie : 0 tout va bien, 2 bloque et renvoie stderr à Claude, tout le reste signale sans bloquer.
  • Trois recettes à réutiliser partout : formatage prettier en PostToolUse, protection des secrets en PreToolUse, notifications sur Notification et Stop.
  • /hooks affiche vos hooks, claude —debug les montre en action — et on relit toujours les hooks d’un dépôt cloné avant de s’y installer.

Vos garde-fous montent désormais la garde tout seuls. Au prochain module, vous allez apprendre à déléguer : des sous-agents spécialisés, chacun avec sa mission et son propre contexte, qui travaillent pour vous — parfois même en parallèle.

Testen Sie Ihr Wissen

0 / 5
  1. Votre hook PreToolUse détecte un problème et se termine avec le code de sortie 1. Que se passe-t-il ?

  2. Vous voulez lancer prettier automatiquement après chaque fichier modifié par Claude. Quelle combinaison choisir ?

  3. Un hook PreToolUse bloque une écriture avec exit 2 et un message sur stderr. Que fait Claude ?

  4. Vous clonez un dépôt public et l'ouvrez avec Claude Code. Pourquoi relire son fichier .claude/settings.json avant de travailler ?

  5. Vous voulez une notification sur votre bureau quand Claude a terminé de répondre. Quel événement utiliser ?