Skip to content

Lab 2.5 : Construire des Garde-fous avec les Hooks

Module : 2.5 - Hooks | ← SlidesDurée : 30 minutes Projet Exemple : node-express-mongoose-demo

Lab Optionnel/Bonus

Objectifs d'Apprentissage

À la fin de ce lab, vous serez capable de :

  • Configurer des hooks déterministes dans .claude/settings.json
  • Créer des hooks de rapport qui fournissent un retour non bloquant (Niveau 1)
  • Implémenter des hooks de garde-fou qui bloquent les motifs de code interdits (Niveau 2)
  • Construire des portes d'approbation pour les opérations à haut risque (Niveau 3)
  • Parser l'entrée JSON des hooks en utilisant jq dans des scripts shell

Prérequis

  • jq installé sur votre système (brew install jq ou sudo apt install jq)
  • Labs 2.1-2.4 complétés (ou familiarité avec les bases de Claude Code)
  • Le projet exemple node-express-mongoose-demo configuré

Comment Fonctionnent les Hooks

Les hooks sont des commandes shell configurées dans .claude/settings.json. Ils s'exécutent automatiquement lorsque Claude déclenche des événements spécifiques.

  • Entrée : Les hooks reçoivent du JSON sur stdin avec tool_name, tool_input, et le contexte de session.
  • Sortie : Code de sortie 0 = autoriser, code de sortie 2 = bloquer. Les hooks peuvent également produire du JSON structuré sur stdout.
  • STDERR : Les messages d'erreur écrits sur stderr sont affichés à Claude lorsqu'un hook bloque.

Configuration

bash
# Naviguer vers le projet exemple
cd sample-projects/node-express-mongoose-demo

# Vérifier que jq est installé
jq --version

# Créer un répertoire pour vos scripts de hook
mkdir -p .claude/hooks

# Démarrer Claude Code
claude

Tâche 1 : Créer un Hook de Rapport PostToolUse

Durée : 8 minutes

Niveau 1 : Rapport. Créer un hook qui détecte les commentaires TODO dans les fichiers que Claude écrit. Il avertit mais ne bloque pas — l'action a déjà eu lieu.

Étape 1 : Créer le script du hook

Créer un fichier à .claude/hooks/check-todos.sh :

bash
#!/bin/bash
# Read JSON from stdin
INPUT=$(cat)

# Extract file_path from tool input
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if [ -n "$FILE_PATH" ] && [ -f "$FILE_PATH" ]; then
  if grep -q "TODO" "$FILE_PATH"; then
    echo "WARNING: File $FILE_PATH contains TODO comments. Track these in the backlog." >&2
  fi
fi

# PostToolUse: action already happened, exit 0
exit 0

Le rendre exécutable :

bash
chmod +x .claude/hooks/check-todos.sh

Étape 2 : Configurer le hook dans .claude/settings.json

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/check-todos.sh"
          }
        ]
      }
    ]
  }
}

Étape 3 : Redémarrer Claude et tester

Create a file called todo-test.js with a function that adds two numbers.
Include a TODO comment about adding input validation later.

Claude écrit le fichier. Le hook s'exécute après l'écriture et affiche l'avertissement TODO.

Critères de réussite :

  • [ ] Script du hook créé et exécutable
  • [ ] settings.json configuré avec le hook PostToolUse
  • [ ] L'avertissement apparaît après que Claude a écrit un fichier contenant "TODO"
  • [ ] L'écriture n'est PAS bloquée (PostToolUse ne peut pas bloquer)

Tâche 2 : Créer un Hook de Garde-fou PreToolUse

Durée : 10 minutes

Niveau 2 : Garde-fous. Créer un hook qui BLOQUE les écritures contenant des instructions console.log. Claude voit l'erreur et s'adapte automatiquement.

Étape 1 : Créer le script de garde-fou

Créer .claude/hooks/block-console-log.sh :

bash
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

# Only check Write tool (content is available in tool_input)
if [ "$TOOL_NAME" != "Write" ]; then
  exit 0
fi

CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // empty')

if echo "$CONTENT" | grep -q "console.log"; then
  echo "BLOCKED: console.log statements are forbidden. Use a proper logger instead." >&2
  exit 2  # Exit code 2 = block the action
fi

exit 0

Le rendre exécutable :

bash
chmod +x .claude/hooks/block-console-log.sh

Étape 2 : Mettre à jour .claude/settings.json

Ajouter la section PreToolUse à côté du PostToolUse existant :

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/check-todos.sh"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-console-log.sh"
          }
        ]
      }
    ]
  }
}

Étape 3 : Redémarrer Claude et tester

Create a file called debug-test.js that logs "hello world" using console.log.

Observez ce qui se passe : Claude essaie d'écrire -> le hook le bloque (exit 2) -> Claude voit le message d'erreur -> Claude réécrit sans console.log.

Critères de réussite :

  • [ ] Script du hook créé et exécutable
  • [ ] L'écriture d'un fichier avec console.log est bloquée
  • [ ] Claude voit le message stderr et s'adapte automatiquement
  • [ ] Le fichier réécrit évite console.log

Tâche 3 : Créer une Porte d'Approbation PreToolUse

Durée : 7 minutes

Niveau 3 : Porte d'approbation. Exiger une confirmation humaine explicite avant que Claude ne modifie les modèles de base de données ou les migrations.

Étape 1 : Créer le script de la porte

Créer .claude/hooks/db-approval-gate.sh :

bash
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# Check if the file path touches database-related code
if [[ "$FILE_PATH" == *"models/"* ]] || [[ "$FILE_PATH" == *"migration"* ]] || [[ "$FILE_PATH" == *"schema"* ]]; then
  # Output JSON to request human approval
  cat <<'GATE'
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "ask",
    "permissionDecisionReason": "This modifies database-related code. Please review and approve."
  }
}
GATE
  exit 0
fi

exit 0

Le rendre exécutable :

bash
chmod +x .claude/hooks/db-approval-gate.sh

Étape 2 : Ajouter à la section PreToolUse dans .claude/settings.json

json
"PreToolUse": [
  {
    "matcher": "Write",
    "hooks": [
      {
        "type": "command",
        "command": ".claude/hooks/block-console-log.sh"
      }
    ]
  },
  {
    "matcher": "Write|Edit",
    "hooks": [
      {
        "type": "command",
        "command": ".claude/hooks/db-approval-gate.sh"
      }
    ]
  }
]

Étape 3 : Redémarrer Claude et tester

Add a new field called 'lastLogin' of type Date to the User model in app/models/user.js.

Claude tente l'écriture -> le hook détecte un chemin models/ -> on vous demande d'approuver ou de refuser.

Critères de réussite :

  • [ ] Script du hook créé et exécutable
  • [ ] La modification d'un fichier dans app/models/ déclenche une demande d'approbation humaine
  • [ ] Vous pouvez approuver ou refuser le changement

Tâche 4 : Tester les Trois Niveaux

Durée : 5 minutes

Passez en revue les trois garde-fous en séquence pour vérifier qu'ils fonctionnent ensemble.

Test 1 : Rapporteur (Niveau 1)

Create a file utils/helpers.js with a helper function. Add a TODO comment.

Attendu : Le fichier est écrit. L'avertissement concernant le TODO apparaît.

Test 2 : Garde-fou (Niveau 2)

Add console.log debugging to utils/helpers.js.

Attendu : L'écriture est bloquée. Claude réessaie sans console.log.

Test 3 : Porte d'Approbation (Niveau 3)

Add a 'createdAt' timestamp field to the Article model.

Attendu : On vous demande d'approuver le changement de modèle.

Critères de réussite :

  • [ ] Les trois hooks sont déclenchés dans l'ordre attendu
  • [ ] Le rapporteur avertit mais autorise
  • [ ] Le garde-fou bloque et Claude récupère
  • [ ] La porte demande une approbation humaine

Dépannage des Hooks

Si un hook ne fonctionne pas, vérifiez ces problèmes courants :

ProblèmeCauseCorrection
Le hook ne se déclenche pasJSON invalide dans settings.jsonValider avec `cat .claude/settings.json
Le hook ne se déclenche pasScript non exécutableLancer chmod +x .claude/hooks/votre-script.sh
Le hook ne se déclenche pasMauvais matcherVérifier que le nom de l'outil correspond (ex: Write et non write)
L'analyse JSON échouejq non installéInstaller : brew install jq ou apt install jq
Le blocage ne fonctionne pasMauvais code de sortieUtiliser exit 2 (pas exit 1) pour les blocages PreToolUse
Aucune erreur affichéeÉcriture sur stdout au lieu de stderrUtiliser >&2 pour les messages d'erreur dans les hooks bloquants

Conseil pour le test manuel : Vous pouvez tester un script de hook directement :

bash
echo '{"tool_name":"Write","tool_input":{"file_path":"test.js","content":"console.log(1)"}}' | .claude/hooks/block-console-log.sh
echo $?  # Devrait afficher 2

Conseils

  • Gardez les hooks rapides. Des hooks lents rendent Claude poussif.
  • Utilisez stderr pour les messages d'erreur (>&2) — Claude lit stderr lorsqu'un hook bloque.
  • Utilisez stdout pour le JSON structuré — pour des décisions comme permissionDecision: "ask".
  • Testez les scripts manuellement d'abord avant de les ajouter à settings.json.
  • Commencez par le Niveau 1 (rapport). Passez au Niveau 2/3 uniquement si nécessaire.

Objectifs Bonus

Si vous finissez en avance :

  1. Auto-formateur : Créer un hook PostToolUse qui lance npx prettier --write sur chaque fichier touché par Claude.
  2. Scanner de secrets : Créer un hook PreToolUse qui bloque les écritures contenant des motifs comme AKIA (clés AWS) ou -----BEGIN.*PRIVATE KEY.
  3. Garde de branche : Créer un hook PreToolUse sur l'outil Bash qui bloque git push vers main.

Livrables

À la fin de ce lab, vous devriez avoir :

  1. Trois scripts de hook dans .claude/hooks/ (rapporteur, garde-fou, porte)
  2. Un fichier .claude/settings.json avec les trois niveaux configurés
  3. La preuve que chaque niveau fonctionne : avertissements, blocages et demandes d'approbation

Prochaines Étapes

Après avoir terminé ce lab, passez au Lab 2.7 : Mini-Projet de Modernisation - le projet final du Jour 2.

Claude for Coders Training Course