ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Hooks Claude Code

Comment les hooks donnent à Claude Code des garde-fous déterministes — des commandes shell qui s'exécutent à des points spécifiques du cycle de vie pour appliquer des règles, formater automatiquement le code et bloquer les opérations dangereuses

Planté
claude codeautomationdata engineering

Les hooks sont des commandes shell qui s’exécutent à des points spécifiques du cycle de vie de Claude Code. Là où CLAUDE.md fournit des directives que Claude devrait suivre, les hooks fournissent un contrôle déterministe que Claude doit respecter. Un hook qui bloque les modifications des schémas de production les bloquera à chaque fois, indépendamment de la persuasion de votre invite.

CLAUDE.md est probabiliste — Claude le suit de manière fiable, mais des invites complexes ou des conversations longues peuvent amener à déprioritiser des instructions. Les hooks sont déterministes — des commandes shell qui réussissent ou échouent, sans place pour l’interprétation du LLM.

Points du cycle de vie des hooks

Claude Code expose plusieurs hooks de cycle de vie, mais deux sont les plus utiles pour les workflows d’analytics engineering :

PreToolUse s’exécute avant que Claude n’utilise un outil (comme modifier un fichier, exécuter une commande ou écrire du code). C’est votre point de contrôle — vous pouvez inspecter ce que Claude s’apprête à faire et le bloquer s’il viole une règle.

PostToolUse s’exécute après que Claude a fini d’utiliser un outil. C’est votre étape de nettoyage — formater automatiquement le code, compiler des modèles, exécuter des linters ou déclencher des vérifications en aval.

D’autres hooks de cycle de vie existent (comme PreToolCall pour la demande initiale), mais PreToolUse et PostToolUse couvrent 90% des cas d’usage pratiques.

Fonctionnement des hooks

Les hooks sont configurés dans le fichier .claude/settings.json de votre projet. Chaque hook possède :

  • Un matcher qui détermine quelles activations d’outils le déclenchent (ex. : Edit|Write pour les modifications de fichiers, Bash pour l’exécution de commandes)
  • Un type (command pour l’exécution shell)
  • Une commande qui reçoit l’entrée de l’outil via stdin en JSON

Le code de sortie du hook détermine le résultat :

Code de sortieComportement
0Le hook passe, l’opération se poursuit
2Le hook bloque l’opération, le message d’erreur remonte à Claude
Autre non-zéroL’erreur est journalisée mais l’opération continue

Le code de sortie 2 est le crucial. Lorsqu’un hook retourne 2, Claude voit l’erreur et peut ajuster son approche. Il ne réessaie pas silencieusement — il comprend que l’opération a été bloquée et pourquoi.

Formatage automatique du SQL après les modifications

L’un des hooks les plus pratiques pour les projets dbt : exécuter automatiquement sqlfluff après que Claude a modifié un fichier SQL.

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read f; if echo \"$f\" | grep -q '\\.sql$'; then sqlfluff fix \"$f\" --dialect bigquery; fi; }"
}
]
}
]
}
}

Ce hook intercepte toute modification de fichier, vérifie si le fichier est du SQL et exécute sqlfluff avec le dialecte BigQuery le cas échéant. Résultat : chaque fichier SQL que Claude touche est automatiquement formaté selon les règles de style de votre projet. Pas besoin d’inviter au formatage, pas de dérive par rapport à votre configuration sqlfluff.

Le même pattern fonctionne pour d’autres formateurs. Vous pourriez exécuter sqlfmt, prettier pour les fichiers YAML ou tout autre outil qui accepte un chemin de fichier.

Blocage des modifications sur les fichiers protégés

Pour les projets dbt avec des modèles mart de production qui ne devraient changer que via un processus de revue formel :

{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "python3 -c \"import json, sys; d=json.load(sys.stdin); p=d.get('tool_input',{}).get('file_path',''); sys.exit(2 if 'models/marts/prod/' in p else 0)\""
}
]
}
]
}
}

Lorsque Claude tente de modifier un fichier dans models/marts/prod/, le hook retourne le code de sortie 2, bloquant l’opération. Claude voit le blocage et demande soit une confirmation, soit contourne le problème. C’est un garde-fou absolu — aucune invite ne pourra le contourner.

Vous pouvez étendre ce pattern pour protéger tout chemin critique : seeds/ si les données de seeds ne doivent pas être modifiées par l’IA, macros/generate_schema_name.sql si votre logique de schéma personnalisée est soigneusement réglée, ou des répertoires entiers appartenant à d’autres équipes.

Compilation automatique après les modifications de modèles

Après que Claude a modifié un modèle dbt, vous pouvez vouloir le compiler automatiquement pour détecter immédiatement les erreurs de syntaxe :

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read f; if echo \"$f\" | grep -q 'models/.*\\.sql$'; then dbt compile --select $(basename \"$f\" .sql) 2>&1 | tail -5; fi; }"
}
]
}
]
}
}

Cela détecte les problèmes comme les appels ref() invalides, les erreurs de syntaxe et le Jinja cassé avant que Claude ne passe à la tâche suivante. Le SQL compilé donne également à Claude un retour immédiat sur ce que ses modifications produisent.

Application de la discipline TDD

Les hooks peuvent appliquer le développement piloté par les tests en interceptant la création de fichiers de modèles et en vérifiant si des tests existent d’abord :

{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read f; if echo \"$f\" | grep -q 'models/.*\\.sql$'; then model=$(basename \"$f\" .sql); grep -rq \"$model\" models/ --include='*.yml' || exit 2; fi; }"
}
]
}
]
}
}

Si Claude tente de créer un nouveau fichier SQL de modèle et qu’aucune entrée YAML correspondante n’existe avec des tests définis, le hook le bloque. Claude comprend alors qu’il doit d’abord écrire les tests dans schema.yml.

Considérations pratiques

Gardez les hooks rapides. Chaque hook PostToolUse s’exécute après chaque invocation d’outil qui correspond. Un hook qui prend 10 secondes à s’exécuter ralentira l’ensemble du workflow de Claude. sqlfluff sur un seul fichier est rapide ; exécuter dbt build sur un grand graphe ne l’est pas.

Utilisez les matchers judicieusement. Le matcher Edit|Write se déclenche à chaque modification de fichier, donc votre commande hook doit filtrer de manière appropriée (vérifier l’extension du fichier, le chemin, etc.). Sans ce filtre, vous tenteriez d’exécuter sqlfluff sur un fichier Python ou YAML.

Combinez avec CLAUDE.md. Les hooks appliquent des limites dures. CLAUDE.md fournit des directives souples. Utilisez les hooks pour les règles qui ne doivent jamais être enfreintes, et CLAUDE.md pour les conventions que Claude devrait suivre mais où une déviation occasionnelle est acceptable.

Testez les hooks localement d’abord. Un hook avec un bug (comme une boucle infinie ou une commande qui retourne toujours le code 2) bloquera toutes les opérations Claude Code. Testez manuellement vos commandes hook avec un exemple d’entrée JSON avant de les ajouter aux paramètres.

Quand les hooks sont excessifs

Tout n’a pas besoin d’un hook. Si vous souhaitez simplement que Claude préfère un certain style SQL, mettez-le dans CLAUDE.md. Si vous souhaitez que Claude exécute des tests après l’implémentation, demandez-le simplement. Les hooks sont destinés à la poignée de règles où l’application déterministe vaut le coût de configuration : protéger les fichiers de production, appliquer les normes de formatage, bloquer les opérations qui pourraient causer de réels dommages.