Passer au contenu principal
Les hooks Claude Code sont des commandes shell définies par l’utilisateur qui s’exécutent à différents points du cycle de vie de Claude Code. Les hooks fournissent un contrôle déterministe du comportement de Claude Code, en garantissant que certaines actions se produisent toujours plutôt que de compter sur le LLM pour choisir de les exécuter.
Pour la documentation de référence sur les hooks, consultez Hooks reference.
Les cas d’usage des hooks incluent :
  • Notifications : Personnalisez la façon dont vous êtes notifié lorsque Claude Code attend votre entrée ou permission pour exécuter quelque chose.
  • Formatage automatique : Exécutez prettier sur les fichiers .ts, gofmt sur les fichiers .go, etc. après chaque modification de fichier.
  • Journalisation : Suivez et comptabilisez toutes les commandes exécutées pour la conformité ou le débogage.
  • Retours d’information : Fournissez des retours automatisés lorsque Claude Code produit du code qui ne suit pas les conventions de votre base de code.
  • Permissions personnalisées : Bloquez les modifications des fichiers de production ou des répertoires sensibles.
En codant ces règles comme des hooks plutôt que comme des instructions d’invite, vous transformez les suggestions en code au niveau de l’application qui s’exécute chaque fois qu’il est censé s’exécuter.
Vous devez considérer les implications de sécurité des hooks lorsque vous les ajoutez, car les hooks s’exécutent automatiquement pendant la boucle de l’agent avec les identifiants de votre environnement actuel. Par exemple, un code de hooks malveillant peut exfiltrer vos données. Examinez toujours votre implémentation de hooks avant de les enregistrer.Pour les meilleures pratiques de sécurité complètes, consultez Security Considerations dans la documentation de référence des hooks.

Aperçu des événements Hook

Claude Code fournit plusieurs événements hook qui s’exécutent à différents points du flux de travail :
  • PreToolUse : S’exécute avant les appels d’outils (peut les bloquer)
  • PostToolUse : S’exécute après la fin des appels d’outils
  • UserPromptSubmit : S’exécute lorsque l’utilisateur soumet une invite, avant que Claude la traite
  • Notification : S’exécute lorsque Claude Code envoie des notifications
  • Stop : S’exécute lorsque Claude Code termine sa réponse
  • SubagentStop : S’exécute lorsque les tâches du sous-agent se terminent
  • PreCompact : S’exécute avant que Claude Code ne soit sur le point d’exécuter une opération compacte
  • SessionStart : S’exécute lorsque Claude Code démarre une nouvelle session ou reprend une session existante
  • SessionEnd : S’exécute lorsque la session Claude Code se termine
Chaque événement reçoit des données différentes et peut contrôler le comportement de Claude de différentes manières.

Démarrage rapide

Dans ce démarrage rapide, vous ajouterez un hook qui enregistre les commandes shell que Claude Code exécute.

Prérequis

Installez jq pour le traitement JSON en ligne de commande.

Étape 1 : Ouvrir la configuration des hooks

Exécutez la commande slash /hooks et sélectionnez l’événement hook PreToolUse. Les hooks PreToolUse s’exécutent avant les appels d’outils et peuvent les bloquer tout en fournissant à Claude des retours sur ce qu’il faut faire différemment.

Étape 2 : Ajouter un matcher

Sélectionnez + Add new matcher… pour exécuter votre hook uniquement sur les appels d’outils Bash. Tapez Bash pour le matcher.
Vous pouvez utiliser * pour correspondre à tous les outils.

Étape 3 : Ajouter le hook

Sélectionnez + Add new hook… et entrez cette commande :
jq -r '"\(.tool_input.command) - \(.tool_input.description // "No description")"' >> ~/.claude/bash-command-log.txt

Étape 4 : Enregistrer votre configuration

Pour l’emplacement de stockage, sélectionnez User settings puisque vous enregistrez dans votre répertoire personnel. Ce hook s’appliquera alors à tous les projets, pas seulement à votre projet actuel. Appuyez ensuite sur Échap jusqu’à ce que vous reveniez au REPL. Votre hook est maintenant enregistré !

Étape 5 : Vérifier votre hook

Exécutez /hooks à nouveau ou vérifiez ~/.claude/settings.json pour voir votre configuration :
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

Étape 6 : Tester votre hook

Demandez à Claude d’exécuter une commande simple comme ls et vérifiez votre fichier journal :
cat ~/.claude/bash-command-log.txt
Vous devriez voir des entrées comme :
ls - Lists files and directories

Plus d’exemples

Pour un exemple d’implémentation complet, consultez l’exemple de validateur de commande bash dans notre base de code publique.

Hook de formatage de code

Formatez automatiquement les fichiers TypeScript après les modifications :
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | { read file_path; if echo \"$file_path\" | grep -q '\\.ts$'; then npx prettier --write \"$file_path\"; fi; }"
          }
        ]
      }
    ]
  }
}

Hook de formatage Markdown

Corrigez automatiquement les balises de langue manquantes et les problèmes de formatage dans les fichiers markdown :
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/markdown_formatter.py"
          }
        ]
      }
    ]
  }
}
Créez .claude/hooks/markdown_formatter.py avec ce contenu :
#!/usr/bin/env python3
"""
Markdown formatter for Claude Code output.
Fixes missing language tags and spacing issues while preserving code content.
"""
import json
import sys
import re
import os

def detect_language(code):
    """Best-effort language detection from code content."""
    s = code.strip()
    
    # JSON detection
    if re.search(r'^\s*[{\[]', s):
        try:
            json.loads(s)
            return 'json'
        except:
            pass
    
    # Python detection
    if re.search(r'^\s*def\s+\w+\s*\(', s, re.M) or \
       re.search(r'^\s*(import|from)\s+\w+', s, re.M):
        return 'python'
    
    # JavaScript detection  
    if re.search(r'\b(function\s+\w+\s*\(|const\s+\w+\s*=)', s) or \
       re.search(r'=>|console\.(log|error)', s):
        return 'javascript'
    
    # Bash detection
    if re.search(r'^#!.*\b(bash|sh)\b', s, re.M) or \
       re.search(r'\b(if|then|fi|for|in|do|done)\b', s):
        return 'bash'
    
    # SQL detection
    if re.search(r'\b(SELECT|INSERT|UPDATE|DELETE|CREATE)\s+', s, re.I):
        return 'sql'
        
    return 'text'

def format_markdown(content):
    """Format markdown content with language detection."""
    # Fix unlabeled code fences
    def add_lang_to_fence(match):
        indent, info, body, closing = match.groups()
        if not info.strip():
            lang = detect_language(body)
            return f"{indent}```{lang}\n{body}{closing}\n"
        return match.group(0)
    
    fence_pattern = r'(?ms)^([ \t]{0,3})```([^\n]*)\n(.*?)(\n\1```)\s*$'
    content = re.sub(fence_pattern, add_lang_to_fence, content)
    
    # Fix excessive blank lines (only outside code fences)
    content = re.sub(r'\n{3,}', '\n\n', content)
    
    return content.rstrip() + '\n'

# Main execution
try:
    input_data = json.load(sys.stdin)
    file_path = input_data.get('tool_input', {}).get('file_path', '')
    
    if not file_path.endswith(('.md', '.mdx')):
        sys.exit(0)  # Not a markdown file
    
    if os.path.exists(file_path):
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        formatted = format_markdown(content)
        
        if formatted != content:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(formatted)
            print(f"✓ Fixed markdown formatting in {file_path}")
    
except Exception as e:
    print(f"Error formatting markdown: {e}", file=sys.stderr)
    sys.exit(1)
Rendez le script exécutable :
chmod +x .claude/hooks/markdown_formatter.py
Ce hook exécute automatiquement :
  • Détecte les langages de programmation dans les blocs de code sans étiquette
  • Ajoute les balises de langue appropriées pour la mise en évidence de la syntaxe
  • Corrige les lignes vides excessives tout en préservant le contenu du code
  • Traite uniquement les fichiers markdown (.md, .mdx)

Hook de notification personnalisée

Recevez des notifications de bureau lorsque Claude a besoin d’une entrée :
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Awaiting your input'"
          }
        ]
      }
    ]
  }
}

Hook de protection de fichier

Bloquez les modifications des fichiers sensibles :
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"import json, sys; data=json.load(sys.stdin); path=data.get('tool_input',{}).get('file_path',''); sys.exit(2 if any(p in path for p in ['.env', 'package-lock.json', '.git/']) else 0)\""
          }
        ]
      }
    ]
  }
}

En savoir plus

  • Pour la documentation de référence sur les hooks, consultez Hooks reference.
  • Pour les meilleures pratiques de sécurité complètes et les directives de sécurité, consultez Security Considerations dans la documentation de référence des hooks.
  • Pour les étapes de dépannage et les techniques de débogage, consultez Debugging dans la documentation de référence des hooks.