Blog / · 6 min de lecture
Claude Code Hooks : Gardez votre codebase propre automatiquement
Les hooks PreToolUse et PostToolUse de Claude Code permettent d'automatiser des règles de qualité : pas de console.log, imports triés, tests obligatoires. Configuration concrète avec exemples Symfony et React.
Tu connais les pre-commit hooks de Git. Tu connais peut-être les hooks de CI. Mais Claude Code a sa propre couche d’hooks qui s’exécute en temps réel pendant que tu codes — et ça change tout.
Au lieu de découvrir que tu as laissé un console.log en production pendant la review, l’hook te le signale au moment où tu écris la ligne. Avant même que le fichier ne soit sauvegardé.
Deux types d’hooks, deux moments clés
Claude Code expose deux types d’hooks dans settings.json :
| Hook | Moment | Usage |
|---|---|---|
PreToolUse | Avant l’exécution d’un tool | Bloquer ou modifier une action |
PostToolUse | Après l’exécution d’un tool | Réagir à un résultat |
Les tools concernés : Read, Write, Edit, Bash, et tous les autres outils natifs de Claude Code.
La structure dans settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo 'Bash tool utilisé'"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "/home/user/scripts/check-file.sh"
}
]
}
]
}
}
Les matchers
Le matcher filtre quel tool déclenche l’hook :
"Bash"→ uniquement les commandes bash"Write"→ uniquement l’écriture de fichiers"Edit"→ uniquement les modifications de fichiers"*"→ tous les tools
Tu peux aussi matcher des patterns plus précis :
{
"matcher": "Bash",
"hooks": [...]
}
Cas d’usage 1 : Bloquer les console.log en production
L’hook le plus utile que j’ai configuré : empêcher Claude d’ajouter des console.log dans le code.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "grep -n 'console\\.log' $FILE_PATH && exit 2 || exit 0"
}
]
}
]
}
}
Comment ça marche :
- Claude tente d’écrire un fichier
- L’hook s’exécute avec la variable
$FILE_PATH - Si
console.logest détecté →exit 2bloque l’action - Claude reçoit le feedback et doit corriger
Version Symfony : bloquer les dd() et dump()
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "grep -E '(dd\\(|dump\\()' $FILE_PATH && echo 'DEBUG FUNCTIONS INTERDITES' && exit 2 || exit 0"
}
]
}
]
}
}
Cas d’usage 2 : Forcer les tests avant commit
Tu veux que Claude vérifie que les tests passent avant de considérer une tâche terminée.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$COMMAND\" | grep -q 'git commit'; then bun test; fi"
}
]
}
]
}
}
Note : Cet hook exécute les tests après chaque commit. Si les tests échouent, tu le vois immédiatement.
Version Symfony avec PHPUnit
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$COMMAND\" | grep -q 'git commit'; then php bin/phpunit --testdox; fi"
}
]
}
]
}
}
Cas d’usage 3 : Imports automatiquement triés
Pour les projets TypeScript/React, forcer le tri des imports :
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "if echo \"$FILE_PATH\" | grep -qE '\\.(ts|tsx)$'; then npx sort-imports $FILE_PATH; fi"
}
]
}
]
}
}
Cas d’usage 4 : Vérification des types TypeScript
Bloquer l’écriture si TypeScript n’est pas satisfait :
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "if echo \"$FILE_PATH\" | grep -qE '\\.(ts|tsx)$'; then npx tsc --noEmit; fi"
}
]
}
]
}
}
Variables disponibles dans les hooks
| Variable | Description |
|---|---|
$FILE_PATH | Chemin du fichier (pour Write/Edit/Read) |
$COMMAND | Commande bash exécutée (pour Bash) |
$TOOL_INPUT | Input complet du tool en JSON |
Exit codes et comportement
| Code | Effet |
|---|---|
0 | Succès, l’action continue |
2 | Bloquant, l’action est annulée |
| Autre | Non-bloquant, warning affiché |
Configuration complète pour un projet full-stack
Voici ma configuration settings.json pour un projet Symfony + React :
{
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
},
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/pre-write.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/post-bash.sh"
}
]
}
]
}
}
pre-write.sh
#!/bin/bash
FILE_PATH="$1"
CONTENT=$(cat)
# Bloquer console.log en JS/TS
if echo "$FILE_PATH" | grep -qE '\.(js|jsx|ts|tsx)$'; then
if echo "$CONTENT" | grep -q 'console\.log'; then
echo "BLOCKED: console.log détecté dans $FILE_PATH"
exit 2
fi
fi
# Bloquer dd()/dump() en PHP
if echo "$FILE_PATH" | grep -qE '\.php$'; then
if echo "$CONTENT" | grep -qE '(dd\(|dump\()'; then
echo "BLOCKED: dd() ou dump() détecté dans $FILE_PATH"
exit 2
fi
fi
exit 0
post-bash.sh
#!/bin/bash
COMMAND="$1"
# Après un commit, lancer les tests
if echo "$COMMAND" | grep -q 'git commit'; then
echo "Running tests after commit..."
# Tests PHP
if [ -f "composer.json" ]; then
php bin/phpunit --testdox --colors=always
fi
# Tests JS
if [ -f "package.json" ]; then
bun test
fi
fi
exit 0
Les limites à connaître
- Performance : Les hooks ralentissent chaque opération. Garde-les légers.
- Boucles infinies : Un hook qui modifie un fichier peut déclencher un autre hook. Attention aux effets de bord.
- Debug : Les erreurs d’hooks apparaissent dans les logs Claude Code, pas toujours visibles directement.
Ce que ça change au quotidien
Avec les hooks Claude Code, tu passes d’un workflow “code → commit → CI → discover bug” à “code → immediate feedback → commit clean code”.
C’est la différence entre corriger un problème 30 secondes après l’avoir créé vs le découvrir en review 2 heures plus tard. Multiplié par le nombre de fois où Claude Code travaille sur ta codebase.
Les hooks les plus impactants dans ma pratique :
- Bloquer les debug statements (
console.log,dd(),dump()) - Lancer les tests après commit (feedback immédiat)
- Vérifier les types TypeScript (catcher les erreurs avant qu’elles n’atteignent le runtime)
Configuration minimale pour démarrer : bloque les console.log. Tu remercieras plus tard.
Continuer la lecture