Free

Guida completa ai Claude Code Hooks: prendi il controllo di ogni azione di Claude

Analisi completa del meccanismo Claude Code Hooks: cinque tipi di eventi, controllo dei codici di uscita e quattro configurazioni reali per rendere le azioni AI verificabili, intercettabili e automatizzabili.


Ogni volta che Claude Code legge un file, scrive codice o esegue un comando, un sistema di eventi lavora in background. Gli Hooks sono l'interfaccia per connettersi a questo sistema — puoi iniettare la tua logica in qualsiasi momento: eseguire automaticamente i linter, registrare le operazioni, bloccare azioni pericolose o attivare qualsiasi comando shell.

Questo articolo copre in modo completo il meccanismo degli Hooks, la configurazione e l'uso pratico.


Cosa sono gli Hooks

Gli Hooks sono comandi shell configurati in settings.json che Claude Code esegue automaticamente quando si verificano eventi specifici.

L'analogia più diretta: i git hooks. Git può attivare script prima e dopo operazioni come commit e push. I Claude Code Hooks funzionano esattamente allo stesso modo — la differenza è che i punti di attivazione sono le chiamate agli strumenti dell'IA.

Perché è importante?

Più Claude Code diventa capace, più hai bisogno di un livello di controllo deterministico. Gli Hooks forniscono:
- Garanzie di esecuzione indipendenti dal prompt (Claude può ignorare le istruzioni, ma gli hook si eseguono sempre)
- Registri di operazioni verificabili
- Controlli di qualità automatizzati


Cinque tipi di Hook

Tipo Trigger Uso tipico
PreToolUse Prima di una chiamata a strumento Bloccare operazioni pericolose, registrare l'intenzione
PostToolUse Dopo una chiamata a strumento Auto-lint, eseguire test
PreCompact Prima della compattazione del contesto Salvare uno snapshot dello stato attuale
Notification Quando Claude invia una notifica Avvisi desktop, messaggi Slack
Stop Quando Claude termina di rispondere Riassumere i log, attivare flussi successivi

I più usati sono PreToolUse e PostToolUse, per intercettare e post-elaborare le chiamate agli strumenti.


Formato di configurazione

Gli Hooks vanno in ~/.claude/settings.json (globale) o in .claude/settings.json nella root del progetto (livello progetto):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npm run lint --silent"
          }
        ]
      }
    ]
  }
}

Tre campi principali:

  • matcher: Regex che corrisponde ai nomi degli strumenti, determina quali chiamate attivano questo hook. "Write|Edit" si attiva quando si scrive o modifica un file. Lascia vuoto o usa ".*" per corrispondere a tutti gli strumenti.
  • type: Al momento solo "command".
  • command: Qualsiasi comando shell.

Riferimento nomi strumenti

Nomi degli strumenti da conoscere per scrivere i matcher:

Nome strumento Azione
Write Scrivere un nuovo file
Edit Modificare un file
Bash Eseguire un comando shell
Read Leggere un file
Glob Ricerca file
Grep Ricerca contenuto
TodoWrite Aggiornare la lista dei task

Ambiente di esecuzione degli Hook

Durante l'esecuzione, i dati vengono passati come JSON tramite stdin:

{
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.rb",
    "content": "..."
  },
  "tool_response": "..."
}

PreToolUse riceve tool_input (gli argomenti prima della chiamata). PostToolUse riceve anche tool_response (il valore di ritorno dello strumento).

Esempio di hook con logica condizionale:

#!/bin/bash
input=$(cat)
file=$(echo "$input" | jq -r '.tool_input.file_path')

# Eseguire rubocop solo sui file .rb
if [[ "$file" == *.rb ]]; then
  rubocop "$file" --autocorrect-all --no-color
fi

Significato dei codici di uscita

Il codice di uscita dell'hook controlla il comportamento successivo di Claude Code:

Codice di uscita Significato
0 Successo, continua l'esecuzione
2 Blocca: annulla la chiamata allo strumento corrente, invia l'output stderr a Claude
Altri non-zero Registra l'errore ma continua

Il codice di uscita 2 è il più utile — consente di scrivere logica di intercettazione in PreToolUse per impedire a Claude di eseguire un'operazione e spiegargli il motivo.


Pratica: quattro configurazioni di Hook

1. Formattazione automatica dopo la scrittura di file

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'file=$(echo \"$CLAUDE_TOOL_INPUT\" | jq -r .file_path 2>/dev/null); [[ \"$file\" == *.rb ]] && rubocop -A \"$file\" --no-color -q || true'"
          }
        ]
      }
    ]
  }
}

2. Bloccare l'eliminazione di directory specifiche

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'cmd=$(echo \"$CLAUDE_TOOL_INPUT\" | jq -r .command); if echo \"$cmd\" | grep -qE \"rm.*/(migrations|seeds)\"; then echo \"Non è consentito eliminare le directory migrations o seeds\" >&2; exit 2; fi'"
          }
        ]
      }
    ]
  }
}

3. Log di audit delle operazioni

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') $CLAUDE_TOOL_NAME: $(echo $CLAUDE_TOOL_INPUT | jq -c .)\" >> ~/.claude/audit.log"
          }
        ]
      }
    ]
  }
}

4. Notifica desktop al completamento

{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude ha completato\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Globale vs. livello progetto

Gli Hooks possono essere collocati in due posti:

Globale (~/.claude/settings.json): Regole comuni a tutti i progetti — log, notifiche.

Livello progetto (.claude/settings.json): Controlli specifici del progetto. Gli hooks del progetto e quelli globali si fondono e vengono eseguiti entrambi.

Per i progetti di team, fai commit del settings.json del progetto in git così tutti eseguono gli stessi hooks.


Debug degli Hook

Passi per la risoluzione dei problemi quando un hook non si attiva:

  1. Verificare l'ortografia del matcher: I nomi degli strumenti distinguono maiuscole e minuscole — write non è Write
  2. Eseguire il comando da solo: Copia il comando dell'hook ed eseguilo direttamente nel terminale
  3. Controllare l'output di Claude Code: Lo stderr dell'hook appare nella conversazione
  4. Semplificare per testare: Inizia con echo "hook triggered" >> /tmp/hook.log per confermare l'attivazione

Riepilogo

Il valore centrale degli Hooks è connettere il comportamento imprevedibile dell'IA agli standard di ingegneria deterministici. Claude può dimenticare di eseguire i test, ma un PostToolUse hook no. Claude può eliminare file per errore, ma un interceptor PreToolUse non lo permetterà.

Inizia con un hook: auto-lint dopo la scrittura di file. Quando funziona, aggiungine altri.