Kevin Aubrée

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.

Claude Code Hooks : Gardez votre codebase propre automatiquement

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 :

HookMomentUsage
PreToolUseAvant l’exécution d’un toolBloquer ou modifier une action
PostToolUseAprès l’exécution d’un toolRé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 :

  1. Claude tente d’écrire un fichier
  2. L’hook s’exécute avec la variable $FILE_PATH
  3. Si console.log est détecté → exit 2 bloque l’action
  4. 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

VariableDescription
$FILE_PATHChemin du fichier (pour Write/Edit/Read)
$COMMANDCommande bash exécutée (pour Bash)
$TOOL_INPUTInput complet du tool en JSON

Exit codes et comportement

CodeEffet
0Succès, l’action continue
2Bloquant, l’action est annulée
AutreNon-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 :

  1. Bloquer les debug statements (console.log, dd(), dump())
  2. Lancer les tests après commit (feedback immédiat)
  3. 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.

Kevin Aubrée

Continuer la lecture

Retour au blog