Advanced (Mis à jour: 01/06/2026)

Guide Claude Code Hooks : contrôles sûrs avant et après le travail

Guide pratique Claude Code Hooks pour débutants : bloquer les commandes risquées, journaliser, formater et lancer les tests.

Guide Claude Code Hooks : contrôles sûrs avant et après le travail

Les Claude Code Hooks sont des contrôles automatiques exécutés avant ou après une action de Claude Code. Au lieu de répéter dans chaque prompt “n’exécute pas de commande dangereuse”, “formate le fichier” ou “lance les tests”, tu peux intégrer ces règles directement dans le workflow du projet.

Le modèle mental le plus simple est le suivant : PreToolUse est le frein, PostToolUse est l’entretien, UserPromptSubmit est le registre d’entrée, et Stop est la vérification avant de sortir. Les Hooks ne remplacent pas la revue humaine, les permissions ni la CI. Ils rendent simplement les contrôles répétitifs plus difficiles à oublier.

Cet article suit la référence officielle des Claude Code Hooks et la documentation officielle des settings. Pour préparer le contexte du projet, lis aussi les bonnes pratiques CLAUDE.md. Pour le modèle de permissions, complète avec le guide des permissions Claude Code.

Les 4 événements à apprendre d’abord

Claude Code propose plusieurs événements de Hooks, mais la plupart des équipes gagnent déjà beaucoup avec ces quatre-là.

ÉvénementUsage principalExemple
UserPromptSubmitAvant que le prompt arrive à ClaudeEnregistrer la demande, repérer des secrets, ajouter un contexte léger
PreToolUseJuste avant l’exécution d’un outilBloquer une commande Bash destructrice ou une action de production
PostToolUseAprès une action réussieLancer formatter, lint ou tests liés
StopQuand Claude va terminer sa réponseVérifier les conflits, sauvegarder un résumé, rappeler une vérification manquante

Utilise PreToolUse quand l’action ne doit pas arriver. Utilise PostToolUse quand l’action est déjà faite et doit être nettoyée ou vérifiée. Utilise UserPromptSubmit pour observer la qualité des demandes. Utilise Stop pour éviter qu’une session se termine avec un problème évident.

Les règles partagées vivent souvent dans .claude/settings.json. Les essais personnels sont plus sûrs dans .claude/settings.local.json. En équipe, documente quels Hooks bloquent, lesquels enregistrent seulement, et qui les maintient.

Configuration minimale à copier

La configuration suivante enregistre les prompts, bloque les commandes Bash dangereuses, lance des vérifications après édition et conserve un résumé de fin.

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/log-prompt.mjs"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/block-dangerous-command.mjs"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/run-quality-checks.mjs",
            "timeout": 120
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/stop-summary.mjs"
          }
        ]
      }
    ]
  }
}

Le détail important est le tableau hooks imbriqué. La structure actuelle définit un événement, éventuellement un matcher, puis des handlers comme type: "command". Des exemples anciens placent encore command directement à côté de matcher; ce n’est pas le format à reprendre aujourd’hui.

Use case 1 : bloquer les commandes dangereuses avec PreToolUse

Le premier use case concret est la sécurité des commandes. Quand Claude Code travaille vite, le moment dangereux n’est pas après l’exécution, mais juste avant. PreToolUse peut lire la commande Bash et refuser une action clairement risquée.

Enregistre ce fichier sous .claude/hooks/block-dangerous-command.mjs.

import fs from "node:fs";

const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
const command = String(input.tool_input?.command || "");

const denyPatterns = [
  /rm\s+-rf\s+(\/|\*|\.|\$HOME)/i,
  /cat\s+\.env(\.|$|\s)/i,
  /printenv/i,
  /aws\s+.*\s+delete-/i,
  /gcloud\s+.*\s+delete/i,
  /kubectl\s+delete\s+(namespace|deployment|secret)/i,
  /DROP\s+DATABASE/i
];

const matched = denyPatterns.find((pattern) => pattern.test(command));

if (matched) {
  console.log(JSON.stringify({
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: `Blocked by project hook: ${matched}`
    }
  }));
  process.exit(0);
}

Ce script n’est pas un produit de sécurité complet. Une expression régulière peut être contournée. Mais il bloque déjà les erreurs évidentes : afficher .env, supprimer un grand dossier, détruire une ressource cloud, supprimer des objets Kubernetes ou lancer une commande SQL destructrice. Pour un vrai contrôle de production, ajoute les permissions Claude Code, les branches protégées, la CI et l’approbation humaine.

Use case 2 : journaliser les demandes avec UserPromptSubmit

Le deuxième use case est l’observabilité du prompt. Beaucoup de sessions ratées ne commencent pas par un modèle faible, mais par une demande floue : “corrige”, “nettoie”, “fais mieux”. En gardant la demande, tu peux comprendre quelles formulations produisent un bon résultat.

Enregistre ce fichier sous .claude/hooks/log-prompt.mjs.

import fs from "node:fs";
import path from "node:path";

const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
const dir = path.join(process.cwd(), ".claude", "hook-logs");
fs.mkdirSync(dir, { recursive: true });

const record = {
  time: new Date().toISOString(),
  event: input.hook_event_name,
  cwd: input.cwd,
  prompt: input.prompt || input.user_prompt || ""
};

fs.appendFileSync(
  path.join(dir, "prompts.jsonl"),
  JSON.stringify(record) + "\n",
  "utf8"
);

Garde ce journal local au départ. Les prompts peuvent contenir des noms de clients, des URLs internes, des tokens copiés par erreur ou du contexte métier sensible. Ajoute .claude/hook-logs/ à .gitignore, puis définis durée de conservation, accès et propriétaire.

Use case 3 : lancer format et tests après édition

Le troisième use case est la boucle qualité quotidienne. Après une écriture ou une modification, le Hook lance un formatter et une vérification courte. Tu n’as plus besoin d’ajouter “formate et teste” dans chaque prompt.

Enregistre ce fichier sous .claude/hooks/run-quality-checks.mjs.

import fs from "node:fs";
import { execFileSync } from "node:child_process";

const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");
const filePath = String(input.tool_input?.file_path || "");

const isSourceFile = /\.(js|jsx|ts|tsx|css|md|mdx|json)$/.test(filePath);
if (!isSourceFile) process.exit(0);

const run = (cmd, args) => {
  try {
    return execFileSync(cmd, args, {
      cwd: process.cwd(),
      encoding: "utf8",
      stdio: ["ignore", "pipe", "pipe"]
    });
  } catch (error) {
    return String(error.stdout || "") + String(error.stderr || "");
  }
};

const messages = [];
messages.push(run("npx", ["prettier", "--write", filePath]));

if (/\.(js|jsx|ts|tsx)$/.test(filePath)) {
  messages.push(run("npm", ["test", "--", "--runInBand"]));
}

console.log(JSON.stringify({
  hookSpecificOutput: {
    hookEventName: "PostToolUse",
    additionalContext: messages.join("\n").slice(-4000)
  }
}));

Dans un monorepo, évite la suite complète à chaque écriture. Commence par le formatage, ajoute ensuite des tests liés au fichier, et déplace les checks longs vers un Hook async ou la CI. Réduis aussi les logs renvoyés à Claude pour ne pas saturer le contexte.

Use case 4 : inspecter la session avec Stop

Stop se déclenche quand Claude va terminer. C’est un bon endroit pour enregistrer un résumé ou bloquer seulement un état clairement incomplet, comme un conflit Git non résolu.

import fs from "node:fs";
import { execFileSync } from "node:child_process";

const input = JSON.parse(fs.readFileSync(0, "utf8") || "{}");

if (input.stop_hook_active) {
  process.exit(0);
}

let status = "";
try {
  status = execFileSync("git", ["status", "--short"], {
    cwd: process.cwd(),
    encoding: "utf8"
  });
} catch {
  process.exit(0);
}

if (status.includes("UU ")) {
  console.error("Git conflict remains. Resolve conflicts before finishing.");
  process.exit(2);
}

fs.mkdirSync(".claude/hook-logs", { recursive: true });
fs.appendFileSync(
  ".claude/hook-logs/stop.jsonl",
  JSON.stringify({
    time: new Date().toISOString(),
    lastAssistantMessage: input.last_assistant_message || "",
    gitStatus: status.slice(0, 2000)
  }) + "\n"
);

Sois prudent avec Stop. Si tu bloques trop, l’agent peut sembler coincé. Vérifie stop_hook_active, garde les conditions étroites, et préfère la journalisation au blocage tant que la règle n’est pas éprouvée.

Pitfall : erreurs fréquentes et parades

Premier pitfall : croire que Hooks remplace les permissions. Un command hook s’exécute avec les droits de ton utilisateur système. Mal écrit, il peut lire des secrets ou supprimer des fichiers. Valide les entrées, protège les chemins, évite .env et .git, et cite correctement les chemins.

Deuxième pitfall : exécuter trop de travail en mode synchrone. Formater un fichier est raisonnable. Lancer build, tous les tests, tests navigateur et deploy après chaque édition est généralement excessif. Garde les checks rapides dans PostToolUse, mets le reste en async ou CI.

Troisième pitfall : stocker des logs sans politique. Les journaux sont utiles pour déboguer, mais ils peuvent contenir des informations sensibles. Définis l’emplacement, la rétention, l’accès et l’exclusion Git.

Quatrième pitfall : confondre matcher et logique métier. matcher: "Bash" filtre les événements Bash vers le handler. La décision réelle doit analyser la commande complète dans le script.

Note de vérification façon Masa

Lors des essais, le plus gros gain venait du retour des résultats format/test à Claude via additionalContext. Claude peut corriger l’étape suivante sans que quelqu’un copie les logs dans le chat. Le blocage de commandes dangereuses est aussi précieux, non parce qu’il est parfait, mais parce qu’il arrête les erreurs évidentes au bon moment.

Pour une équipe débutante, je le déploierais en trois étapes : une semaine de logs de prompts, puis format après édition, puis une petite liste de commandes Bash interdites. Ce rythme construit la confiance sans ajouter trop de friction.

Si tu veux l’intégrer dans une équipe, la page de training Claude Code couvre permissions, CLAUDE.md, Hooks et review workflow. Pour un développeur solo, le même contenu peut devenir une checklist Gumroad de démarrage de projet.

Résumé

Claude Code Hooks sont des guardrails pratiques. Utilise UserPromptSubmit pour comprendre les demandes, PreToolUse pour bloquer les actions risquées, PostToolUse pour vérifier les changements et Stop pour ne pas terminer avec un problème évident.

Commence petit. Un Hook simple que l’équipe garde activé vaut mieux qu’une automatisation ambitieuse que tout le monde désactive après deux jours.

#Claude Code #Hooks #automation #security #testing
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.