Vai al contenuto principale
I hook di Claude Code sono comandi shell definiti dall’utente che si eseguono in vari punti del ciclo di vita di Claude Code. I hook forniscono un controllo deterministico sul comportamento di Claude Code, garantendo che determinate azioni avvengano sempre piuttosto che affidarsi all’LLM per scegliere di eseguirle.
Per la documentazione di riferimento sui hook, vedi Riferimento sui hook.
I casi d’uso di esempio per i hook includono:
  • Notifiche: Personalizza il modo in cui ricevi notifiche quando Claude Code è in attesa del tuo input o permesso per eseguire qualcosa.
  • Formattazione automatica: Esegui prettier sui file .ts, gofmt sui file .go, ecc. dopo ogni modifica di file.
  • Registrazione: Traccia e conta tutti i comandi eseguiti per conformità o debug.
  • Feedback: Fornisci feedback automatico quando Claude Code produce codice che non segue le convenzioni della tua codebase.
  • Autorizzazioni personalizzate: Blocca le modifiche ai file di produzione o alle directory sensibili.
Codificando queste regole come hook piuttosto che come istruzioni di prompt, trasformi i suggerimenti in codice a livello di app che si esegue ogni volta che è previsto che venga eseguito.
Devi considerare le implicazioni di sicurezza dei hook mentre li aggiungi, perché i hook si eseguono automaticamente durante il ciclo dell’agente con le credenziali dell’ambiente corrente. Ad esempio, il codice dei hook dannosi può esfiltare i tuoi dati. Rivedi sempre l’implementazione dei tuoi hook prima di registrarli.Per le migliori pratiche di sicurezza complete, vedi Considerazioni sulla sicurezza nella documentazione di riferimento dei hook.

Panoramica degli eventi hook

Claude Code fornisce diversi eventi hook che si eseguono in diversi punti del flusso di lavoro:
  • PreToolUse: Si esegue prima delle chiamate di strumento (può bloccarle)
  • PostToolUse: Si esegue dopo il completamento delle chiamate di strumento
  • UserPromptSubmit: Si esegue quando l’utente invia un prompt, prima che Claude lo elabori
  • Notification: Si esegue quando Claude Code invia notifiche
  • Stop: Si esegue quando Claude Code finisce di rispondere
  • SubagentStop: Si esegue quando i compiti del subagente si completano
  • PreCompact: Si esegue prima che Claude Code stia per eseguire un’operazione compatta
  • SessionStart: Si esegue quando Claude Code avvia una nuova sessione o riprende una sessione esistente
  • SessionEnd: Si esegue quando la sessione di Claude Code termina
Ogni evento riceve dati diversi e può controllare il comportamento di Claude in modi diversi.

Guida rapida

In questa guida rapida, aggiungerai un hook che registra i comandi shell che Claude Code esegue.

Prerequisiti

Installa jq per l’elaborazione JSON nella riga di comando.

Passaggio 1: Apri la configurazione dei hook

Esegui il comando slash /hooks e seleziona l’evento hook PreToolUse. I hook PreToolUse si eseguono prima delle chiamate di strumento e possono bloccarle fornendo a Claude feedback su cosa fare diversamente.

Passaggio 2: Aggiungi un matcher

Seleziona + Add new matcher… per eseguire il tuo hook solo sulle chiamate di strumento Bash. Digita Bash per il matcher.
Puoi usare * per abbinare tutti gli strumenti.

Passaggio 3: Aggiungi l’hook

Seleziona + Add new hook… e inserisci questo comando:
jq -r '"\(.tool_input.command) - \(.tool_input.description // "No description")"' >> ~/.claude/bash-command-log.txt

Passaggio 4: Salva la tua configurazione

Per la posizione di archiviazione, seleziona User settings poiché stai registrando nella tua home directory. Questo hook si applicherà quindi a tutti i progetti, non solo al tuo progetto corrente. Quindi premi Esc finché non torni al REPL. Il tuo hook è ora registrato!

Passaggio 5: Verifica il tuo hook

Esegui /hooks di nuovo o controlla ~/.claude/settings.json per vedere la tua configurazione:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

Passaggio 6: Testa il tuo hook

Chiedi a Claude di eseguire un comando semplice come ls e controlla il tuo file di log:
cat ~/.claude/bash-command-log.txt
Dovresti vedere voci come:
ls - Lists files and directories

Altri esempi

Per un’implementazione di esempio completa, vedi l’esempio di validatore di comandi bash nella nostra codebase pubblica.

Hook di formattazione del codice

Formatta automaticamente i file TypeScript dopo la modifica:
{
  "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 di formattazione Markdown

Correggi automaticamente i tag di lingua mancanti e i problemi di formattazione nei file markdown:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/markdown_formatter.py"
          }
        ]
      }
    ]
  }
}
Crea .claude/hooks/markdown_formatter.py con questo contenuto:
#!/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)
Rendi lo script eseguibile:
chmod +x .claude/hooks/markdown_formatter.py
Questo hook esegue automaticamente:
  • Rileva i linguaggi di programmazione nei blocchi di codice senza etichetta
  • Aggiunge tag di lingua appropriati per l’evidenziazione della sintassi
  • Corregge le righe vuote eccessive preservando il contenuto del codice
  • Elabora solo i file markdown (.md, .mdx)

Hook di notifica personalizzato

Ricevi notifiche desktop quando Claude ha bisogno di input:
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Awaiting your input'"
          }
        ]
      }
    ]
  }
}

Hook di protezione dei file

Blocca le modifiche ai file sensibili:
{
  "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)\""
          }
        ]
      }
    ]
  }
}

Scopri di più

  • Per la documentazione di riferimento sui hook, vedi Riferimento sui hook.
  • Per le migliori pratiche di sicurezza complete e le linee guida sulla sicurezza, vedi Considerazioni sulla sicurezza nella documentazione di riferimento dei hook.
  • Per i passaggi di risoluzione dei problemi e le tecniche di debug, vedi Debug nella documentazione di riferimento dei hook.