
Claude Code Hooks: La Guida Completa per Sviluppatori con Esempi Pronti per la Produzione
Claude Code è ottimo per scrivere codice, ma rimane un sistema probabilistico. Puoi chiedergli di eseguire Prettier dopo ogni modifica a un file. Puoi mettere quell'istruzione nel tuo CLAUDE.md. E a volte, semplicemente... se ne dimentica. Gli hooks di Claude Code risolvono questo problema dandoti un controllo deterministico e garantito su ciò che accade prima, durante e dopo ogni azione di Claude.
Ho configurato hooks su decine di progetti negli ultimi mesi, e sono diventati silenziosamente la parte più importante della mia configurazione di Claude Code. Questa guida copre tutto, dalle basi a un kit di avvio pronto per la produzione che puoi inserire in qualsiasi progetto oggi stesso. Se hai già usato Claude Code insieme a strumenti come Cursor o Copilot, conosci già il valore della personalizzazione -- gli hooks vanno ancora più in là.
Cosa Sono gli Hooks di Claude Code (e Perché Dovresti Tenerci)?
Gli hooks di Claude Code sono comandi shell, endpoint HTTP o prompt LLM definiti dall'utente che si eseguono automaticamente in punti specifici del ciclo di vita di Claude Code. Secondo la documentazione ufficiale di Anthropic, a differenza delle istruzioni nei prompt che Claude potrebbe ignorare, gli hooks si attivano deterministicamente ogni volta -- dandoti un controllo garantito su formattazione, sicurezza, notifiche e automazione del workflow.
Il Problema Probabilistico
Ecco la cosa con le istruzioni in CLAUDE.md: sono suggerimenti, non contratti. Puoi scrivere "esegui sempre npx prettier --write dopo aver modificato file TypeScript" nel contesto del progetto, e Claude lo farà la maggior parte delle volte. Ma "la maggior parte delle volte" non basta quando stai applicando la formattazione del codice in un team, o bloccando push in produzione, o registrando ogni comando shell per un audit di sicurezza.
Questa è la tensione centrale di qualsiasi strumento di coding AI. Claude è un language model -- opera su probabilità. L'ingegneria del contesto può orientare il comportamento, ma non può garantirlo.
Come gli Hooks Risolvono il Problema
Gli hooks bypassano completamente l'LLM. Sono script shell, chiamate HTTP o valutazioni AI che si attivano su eventi specifici del ciclo di vita -- prima che uno strumento venga eseguito (PreToolUse), dopo che ha completato (PostToolUse), quando appare una notifica, quando una sessione inizia, o quando Claude si ferma. Pensali come i Git hooks, ma per il tuo assistente di coding AI.
Esistono quattro tipi di hook: command (script shell), HTTP (richieste POST a webhook), prompt (valutazioni sì/no su Claude in un singolo turno) e agent (lancia un subagent con accesso agli strumenti). Approfondiremo ciascuno più avanti -- gli hooks di tipo command coprono circa il 90% di quello di cui avrai bisogno.
Come Funzionano gli Hooks di Claude Code: Il Flusso del Ciclo di Vita
Gli hooks di Claude Code si eseguono in un ciclo di vita definito: un evento si attiva (es. PreToolUse), il matcher verifica se l'hook si applica, lo script hook viene eseguito e riceve JSON su stdin, e il codice di uscita determina cosa succede dopo. Il codice di uscita 0 significa procedere, il codice di uscita 2 significa bloccare l'azione. Questo flusso è identico indipendentemente dal tipo di hook che stai usando.
Evento -> Matcher -> Hook -> Codice di Uscita (Il Flusso in 4 Passi)
Ecco come funziona ogni esecuzione di hook:
1. L'EVENTO SI ATTIVA es. PreToolUse(Write)
|
2. IL MATCHER VERIFICA "Write" corrisponde al pattern matcher dell'hook?
|
3. L'HOOK SI ESEGUE Lo script shell viene eseguito, riceve JSON via stdin
|
4. IL CODICE DECIDE 0 = procedi | 2 = blocca | altro = erroreIl JSON che arriva su stdin contiene tutto sull'evento: tool_name, tool_input (percorso del file, contenuto, comando) e metadati della sessione. Il tuo script legge questo JSON, applica la logica necessaria ed esce con il codice appropriato.
Per gli hooks PreToolUse, il codice di uscita 2 è quello potente -- blocca l'azione completamente e invia il tuo messaggio stdout a Claude come feedback. Claude vede il messaggio e può adattare il suo approccio.
Ambiti di Configurazione: User, Project e Local
Gli hooks risiedono in settings.json a tre livelli:
| Ambito | File | Committed in Git? | Caso d'Uso |
|---|---|---|---|
| User | ~/.claude/settings.json | No | Impostazioni personali (notifiche, preferenze di formattazione) |
| Project | .claude/settings.json | Sì | Hooks condivisi del team (protezione file, test runner, linting) |
| Local | .claude/settings.local.json | No (gitignored) | Override personali per questo progetto |
Le impostazioni di progetto sono le più utili per i team. Inserisci i tuoi hooks in .claude/settings.json, esegui il commit, e ogni sviluppatore del team ottiene automaticamente le stesse protezioni.
Il Campo if: Filtraggio Granulare
Da Claude Code v2.1.85, gli hooks supportano un campo if che consente di filtrare per argomenti dello strumento -- non solo per nome dello strumento. Come documentato nel riferimento hooks di Anthropic, questo significa che puoi scrivere un hook che si attiva solo sui comandi Bash corrispondenti a git push, invece di attivarsi su ogni singola invocazione di Bash.
{
"matcher": "Bash",
"if": "tool_input.command matches 'git push'",
"hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}Questo è stato un cambio di paradigma. Prima del campo if, dovevi scegliere tra matchare troppo ampiamente (ogni comando Bash) o fare il filtraggio dentro lo script (ingombrante).
Tutti gli Eventi Hook di Claude Code: Tabella di Riferimento Rapido
Claude Code fornisce oltre 20 eventi hook lungo il suo ciclo di vita, come documentato nel riferimento ufficiale degli hooks e nel changelog di Claude Code. I più usati sono PreToolUse, PostToolUse, Notification e Stop -- ma eventi più recenti come ConfigChange e FileChanged aprono pattern di automazione avanzati.
Ecco il riferimento completo:
| Evento | Quando Si Attiva | Può Bloccare? | Caso d'Uso Comune |
|---|---|---|---|
| PreToolUse | Prima che uno strumento venga eseguito | Sì (exit 2) | Bloccare comandi pericolosi, proteggere file |
| PostToolUse | Dopo che uno strumento completa | No | Auto-formattazione, eseguire test, log azioni |
| Notification | Quando Claude invia una notifica | No | Alert desktop, messaggi Slack |
| Stop | Quando Claude termina una risposta | No | Pulizia, generazione di riepiloghi |
| SessionStart | All'inizializzazione della sessione | No | Iniettare contesto, impostare ambiente |
| UserPromptSubmit | Quando l'utente invia un prompt | Sì (exit 2) | Validazione input, filtraggio contenuti |
| PreCompact | Prima della compattazione del contesto | No | Salvare stato prima che la memoria venga ridotta |
| PostCompact | Dopo la compattazione del contesto | No | Reiniettare contesto critico |
| ConfigChange | Quando le impostazioni cambiano | No | Ricaricare variabili d'ambiente a caldo |
| FileChanged | Quando un file monitorato cambia | No | Attivare rebuild, invalidare cache |
| TaskCreated | Quando viene creato un nuovo task | No | Tracciamento task, allocazione risorse |
| PermissionDenied | Quando un controllo di permesso fallisce | No | Audit logging, alert su azioni bloccate |
| WorktreeCreate | Quando viene creato un nuovo Git worktree | No | Inizializzare impostazioni specifiche del worktree |
| SubagentStart | Quando un subagent viene lanciato | No | Monitorare l'attività del subagent |
| SubagentStop | Quando un subagent completa | No | Validare l'output del subagent |
Consiglio pro: Userai PreToolUse e PostToolUse per l'80% dei tuoi hooks. SessionStart è il successivo più utile -- è perfetto per iniettare il contesto del progetto di cui Claude ha bisogno all'inizio di ogni sessione.
I 4 Tipi di Hook di Claude Code Spiegati
Claude Code supporta quattro tipi di handler per hook: gli hooks command eseguono script shell, gli hooks HTTP fanno POST a URL, gli hooks prompt fanno una domanda sì/no a Claude, e gli hooks agent lanciano un subagent con accesso agli strumenti. Nella nostra esperienza, gli hooks command coprono il 90% dei casi d'uso. Usa HTTP per integrazioni esterne, gli hooks prompt e agent per decisioni sfumate che richiedono il giudizio dell'AI.
| Tipo | Velocità | Complessità | Ideale Per | Esempio |
|---|---|---|---|---|
| Command | Veloce | Bassa | Formattazione, blocco, logging | Eseguire Prettier dopo la modifica di un file |
| HTTP | Media | Media | Servizi esterni, webhook | POST a Slack al completamento |
| Prompt | Lento | Media | Decisioni soggettive | "È sicuro eseguire questo codice?" |
| Agent | Più lento | Alta | Verifica complessa con accesso ai file | Verificare se il nuovo codice segue i pattern del progetto |
Hooks Command (Il Cavallo di Battaglia)
Gli hooks command eseguono un comando shell e usano il codice di uscita per determinare il risultato. Ricevono i dati JSON dell'evento su stdin.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
}]
}]
}
}Questo è quello che userai per formattazione, protezione file, notifiche e la maggior parte delle automazioni. Veloce, semplice e prevedibile.
Hooks HTTP (Integrazioni Esterne)
Gli hooks HTTP inviano una richiesta POST a un URL con il JSON dell'evento come corpo. Il codice di stato della risposta determina il risultato (200 = procedi, 403 = blocca).
{
"hooks": {
"Stop": [{
"matcher": "",
"hooks": [{
"type": "http",
"url": "https://your-api.com/claude-webhook"
}]
}]
}
}Ottimi per inviare eventi a Slack, Discord, PagerDuty o una dashboard personalizzata. Potresti anche usarli per interrogare un motore di policy esterno prima di consentire l'esecuzione di uno strumento.
Hooks Prompt (Decisioni Guidate dall'AI)
Gli hooks prompt passano i dati dell'evento a Claude stesso per una valutazione sì/no in un singolo turno. Claude restituisce una risposta JSON con "decision": "allow" o "decision": "block" più motivazione.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "prompt",
"prompt": "Is this bash command safe to run in a production environment? Consider: does it modify system files, delete data, or access sensitive credentials?"
}]
}]
}
}Usali con parsimonia. Aggiungono latenza (una chiamata LLM completa per ogni esecuzione di hook) e costi. Ma per controlli di sicurezza genuinamente soggettivi -- come "questa migrazione del database sembra distruttiva?" -- sono difficili da battere. Se sei curioso di cambiare modello in Claude Code, il modello usato per gli hooks prompt segue il modello della tua sessione corrente.
Hooks Agent (Verifica con Accesso agli Strumenti)
Gli hooks agent lanciano un subagent con accesso agli strumenti Read, Grep e Glob. Il subagent può ispezionare i file prima di prendere la sua decisione.
{
"hooks": {
"PreToolUse": [{
"matcher": "Write",
"hooks": [{
"type": "agent",
"prompt": "Check if the file being written follows the project's naming conventions and import patterns. Read .claude/CONVENTIONS.md for the rules."
}]
}]
}
}Questo è il tipo di hook più potente, ma anche il più lento. Riservalo ai controlli ad alto rischio dove hai bisogno del contesto dei file per prendere una buona decisione.
7 Esempi di Hooks di Claude Code Pronti per la Produzione (Copia e Incolla)
Gli hooks di Claude Code più utili includono: auto-formattazione con Prettier o Black dopo le modifiche ai file, blocco scritture su file protetti, notifiche desktop al completamento dei task, iniezione del contesto del progetto all'avvio della sessione, esecuzione dei test dopo le modifiche al codice, applicazione della protezione dei branch e audit di tutti gli utilizzi degli strumenti. Ho varianti di questi in ogni progetto negli ultimi tre mesi.
Ogni esempio qui sotto è uno snippet completo di settings.json che puoi inserire nel tuo .claude/settings.json. Collezioni della community come awesome-claude-code contengono ancora più pattern.
1. Auto-Formattazione al Salvataggio
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; esac; exit 0"
}]
}]
}
}Si attiva dopo ogni Write o Edit, estrae il percorso del file dal JSON su stdin ed esegue il formatter appropriato. L'exit 0 finale assicura che l'hook non blocchi mai -- gli errori di formattazione non devono fermare Claude.
Consiglio pro: Aggiungi *.go con gofmt e *.rs con rustfmt se lavori su più linguaggi.
2. Blocco Scritture su File Protetti
{
"hooks": {
"PreToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '(\\.env|\\.env\\.local|package-lock\\.json|yarn\\.lock|pnpm-lock\\.yaml)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"BLOCKED: This file is protected. Edit it manually.\"}' && exit 2"
}]
}]
}
}Il codice di uscita 2 blocca l'azione e invia il messaggio JSON a Claude. Claude vede il feedback e si adatta -- di solito ti dirà che voleva modificare il file e ti chiederà di farlo manualmente. Il campo if evita che si attivi su ogni singola scrittura.
3. Notifica Desktop al Completamento
{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "MSG=$(jq -r '.message // \"Claude Code task finished\"' /dev/stdin); if [ \"$(uname)\" = 'Darwin' ]; then osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\"; else notify-send 'Claude Code' \"$MSG\"; fi; exit 0"
}]
}]
}
}Funziona su macOS (osascript) e Linux (notify-send). Il matcher vuoto significa che si attiva su tutte le notifiche. Genuinamente utile quando avvii un task lungo e passi a un'altra finestra.
4. Iniezione del Contesto all'Avvio della Sessione
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null || echo none)\"' | Last commit: '\"$(git log --oneline -1 2>/dev/null || echo none)\"'\"}'; exit 0"
}]
}]
}
}Inietta il nome del progetto corrente, il branch Git e l'ultimo commit in ogni sessione. Claude riceve questo contesto automaticamente -- non serve dirgli su quale branch sei.
5. Esecuzione Automatica dei Test dopo le Modifiche al Codice
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '\\.(ts|tsx|js|jsx|py)$'",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path' /dev/stdin); TEST_FILE=$(echo \"$FILE\" | sed 's/\\.[^.]*$/.test&/'); if [ -f \"$TEST_FILE\" ]; then npx jest \"$TEST_FILE\" --no-coverage 2>&1 | tail -5; fi; exit 0",
"timeout": 30000
}]
}]
}
}Se esiste un file di test corrispondente, viene eseguito automaticamente dopo che Claude modifica il sorgente. tail -5 mantiene l'output conciso, e il timeout previene suite di test fuori controllo. Funziona bene con un workflow di code review guidato dall'AI.
6. Protezione dei Branch (Avanzato)
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"if": "tool_input.command matches 'git push.*(main|master|production)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"BLOCKED: Direct push to protected branch. Use a feature branch and open a PR.\"}' && exit 2"
}]
}]
}
}Blocca qualsiasi git push che punta ai branch main, master o production. Claude riceve il feedback e suggerirà di creare un feature branch.
7. Audit Log di Sicurezza (Avanzato)
{
"hooks": {
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "INPUT=$(cat /dev/stdin); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] BASH: $CMD\" >> .claude/audit.log; exit 0"
}]
}]
}
}Registra ogni comando Bash eseguito da Claude in un file di audit con timestamp UTC. Preziosissimo per revisioni di sicurezza e per capire cosa ha effettivamente fatto Claude durante una sessione. Aggiungi .claude/audit.log al tuo .gitignore.
Hooks vs MCP vs Skills vs CLAUDE.md: Quando Usare Cosa
Usa gli hooks per l'automazione deterministica che deve sempre girare (formattazione, blocchi, notifiche). Usa MCP per dare a Claude accesso a strumenti e dati esterni. Usa le Skills per pacchetti di prompt riutilizzabili. Usa CLAUDE.md per indicazioni comportamentali e contesto del progetto. Gli hooks sono garantiti; tutto il resto è probabilistico. Questa è la distinzione più importante, e ci torno sempre quando consiglio i team.
La Matrice Decisionale
| Meccanismo | Deterministico? | Quando Viene Eseguito | Ideale Per | Esempio |
|---|---|---|---|---|
| Hooks | Sì | Automaticamente su eventi del ciclo di vita | Applicazione regole, automazione, notifiche | Auto-formato, blocco scritture su file |
| MCP | No (Claude decide) | Quando Claude chiama lo strumento MCP | Nuove capacità, accesso a dati esterni | Interrogare un database, cercare su Notion |
| Skills | No (l'utente attiva) | Quando l'utente invoca uno slash command | Set di istruzioni riutilizzabili | /review per il workflow di code review |
| CLAUDE.md | No (guida) | Letto all'avvio della sessione | Contesto del progetto, standard di codice | "Usa Tailwind, scrivi test per tutto il nuovo codice" |
Per un approfondimento su MCP, consulta la nostra guida MCP. Se vieni da Cursor, il sistema di regole di Cursor è approssimativamente analogo a CLAUDE.md -- ma Cursor non ha niente di simile agli hooks.
Quando Si Sovrappongono (e Come Scegliere)
Ecco il diagramma di flusso che uso:
- "Deve succedere ogni singola volta, senza eccezioni?" -- Hook. Formatta il codice, blocca i file protetti, invia notifiche. Zero ambiguità.
- "Claude ha bisogno di una nuova CAPACITÀ che non ha?" -- Server MCP. Accede a un database, chiama un'API, cerca in documenti esterni.
- "Voglio ISTRUZIONI riutilizzabili per un workflow specifico?" -- Skill (slash command). Template di code review, checklist di deploy.
- "Voglio modellare il COMPORTAMENTO di Claude in questo progetto?" -- CLAUDE.md. Standard di codice, decisioni architetturali, librerie preferite.
Esempi reali che chiariscono il confine:
- "Formatta sempre con Prettier" = Hook (deve succedere ogni volta)
- "Usa Prettier per la formattazione" in CLAUDE.md = Indicazione (Claude potrebbe dimenticarsi)
- "Cerca nella nostra documentazione aziendale" = MCP (nuova capacità)
- "Segui la nostra style guide durante la code review" = Skill o CLAUDE.md
Come descritto nell'annuncio dei plugin di Anthropic, gli hooks sono un elemento di un ecosistema di plugin più ampio che include anche MCP e Skills. Sono progettati per completarsi a vicenda, non per competere.
Il Kit di Avvio: Configurazione Hook di Claude Code Pronta all'Uso per Qualsiasi Progetto
Una configurazione hook di base per Claude Code dovrebbe includere: auto-formattazione alla modifica dei file, notifica al completamento del task, protezione dei file sensibili, iniezione del contesto della sessione e un hook Stop per la pulizia. Questa è esattamente la configurazione che inserisco in ogni nuovo progetto -- adattata per lo stack, ma la struttura rimane invariata.
La Configurazione
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null)\"' | Node: '\"$(node -v 2>/dev/null)\"'\"}'; exit 0"
}]
}],
"PreToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '(\\.env|\\.env\\..+|.*lock\\.json|.*lock\\.yaml)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Protected file. Edit manually.\"}' && exit 2"
}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; *.go) gofmt -w \"$FILE\" 2>/dev/null;; esac; exit 0"
}]
}],
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "MSG=$(jq -r '.message // \"Done\"' /dev/stdin); osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\" 2>/dev/null || notify-send 'Claude Code' \"$MSG\" 2>/dev/null; exit 0"
}]
}],
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '[STOP] '\"$(date +%H:%M:%S)\"'' >> .claude/session.log; exit 0"
}]
}]
}
}Come Personalizzarlo per il Tuo Stack
| Stack | Comando di Formattazione | Comando Test | Estensioni da Monitorare |
|---|---|---|---|
| Node/TypeScript | npx prettier --write | npx jest --no-coverage | .ts, .tsx, .js, .jsx |
| Python | black | pytest -x | .py |
| Go | gofmt -w | go test ./... | .go |
| Rust | rustfmt | cargo test | .rs |
Sostituisci i comandi di formattazione e test nella configurazione sopra per adattarli al tuo stack. La struttura rimane identica.
Verificare che gli Hooks Funzionino
Tre modi per confermare che gli hooks siano attivi:
- Comando
/hooks-- Digita/hooksin Claude Code per vedere tutti gli hooks registrati, i loro matcher e il loro stato. - Ispezione del transcript -- Dopo che un hook si attiva, controlla il transcript della sessione. Le esecuzioni degli hook appaiono con il loro output e codice di uscita.
- Toggle rapido -- Aggiungi
"disableAllHooks": trueal tuo settings.json per disabilitare temporaneamente tutti gli hooks senza eliminare la configurazione. Rimuovilo (o impostalo sufalse) per riabilitarli.
Integrazione CI/CD: Gli Hooks di Claude Code in Modalità Headless
Gli hooks di Claude Code funzionano in modalità headless (claude -p) con alcune differenze: gli hooks Notification si attivano comunque, ma dovresti reindirizzare al logging invece che agli alert desktop. Gli hooks PreToolUse con codice di uscita 2 possono mettere in pausa le sessioni headless per la revisione umana. GitHub Actions usa anthropics/claude-code-action@v1 insieme agli hooks per i workflow automatizzati.
Comportamento in Modalità Headless
| Evento Hook | Modalità Interattiva | Modalità Headless (-p) | Raccomandazione CI |
|---|---|---|---|
| PreToolUse (exit 2) | Blocca, mostra messaggio | Mette in pausa per --resume | Usa per approvazioni umane obbligatorie |
| PostToolUse | Gira normalmente | Gira normalmente | Mantieni formatter e logger |
| Notification | Alert desktop | Si attiva comunque (niente UI) | Reindirizza a file log o webhook Slack |
| Stop | Esegue pulizia | Esegue pulizia | Utile per la raccolta di artifact CI |
| SessionStart | Inietta contesto | Inietta contesto | Inietta variabili d'ambiente CI |
La grande sorpresa in modalità headless: gli hooks PreToolUse che escono con codice 2 non falliscono silenziosamente. Mettono in pausa la sessione e ti permettono di riprendere con --resume, il che ti dà un pattern human-in-the-loop per le pipeline CI/CD.
Integrazione con GitHub Actions
Ecco un workflow GitHub Actions minimale che usa Claude Code con hooks. Come documentato nella guida ufficiale di GitHub Actions:
- name: Run Claude Code
uses: anthropics/claude-code-action@v1
with:
prompt: "Review this PR and suggest improvements"
allowed_tools: "Read,Grep,Glob"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}Gli hooks nel tuo .claude/settings.json viaggiano con il repository, quindi si attiveranno in CI esattamente come in locale. Assicurati solo che gli hooks che dipendono da strumenti specifici del desktop (come osascript) abbiano fallback o condizionali.
Gestione degli Hooks nel Team
Un pattern che funziona bene per i team:
.claude/settings.json(committed) -- Hooks condivisi del team: protezione file, formatter, protezione branch. Li ricevono tutti..claude/settings.local.json(gitignored) -- Hooks personali: preferenze di notifica, logging personalizzato, hooks sperimentali.~/.claude/settings.json(globale utente) -- Le tue impostazioni predefinite per tutti i progetti: stile di notifica, preferenze di formattazione personali.
Questo rispecchia il funzionamento di .editorconfig (committed) e delle impostazioni locali dell'IDE (personali). Come notato dalla guida CI/CD di Angelo Lima, i team che standardizzano sugli hooks condivisi vedono meno problemi di "funziona sulla mia macchina" con Claude Code.
Risoluzione dei Problemi e Errori Comuni con gli Hooks di Claude Code
I problemi comuni con gli hooks di Claude Code includono: hook che non si attivano (controlla l'ortografia del matcher e la posizione di settings.json), hook che girano ma non bloccano (codice di uscita sbagliato -- usa 2 non 1), loop infiniti (hook Stop che si attiva da solo) e avvio lento (troppi hook sincroni). L'errore più comune che vedo è la confusione sui codici di uscita -- gli sviluppatori usano exit 1 quando intendono exit 2.
L'Hook Non Si Attiva
Sintomi: Hai aggiunto un hook ma non succede niente quando si verifica l'evento.
Soluzioni:
- Typo nel matcher -- I matcher sono case-sensitive.
"write"non corrisponde allo strumentoWrite. Controlla i nomi esatti degli strumenti con/hooks. - File settings sbagliato -- Gli hooks in
~/.claude/settings.jsonnon appariranno nell'output di/hooksper l'ambito del progetto. Prova.claude/settings.jsonnella root del progetto. - Errore di sintassi JSON -- Una virgola di troppo o una parentesi mancante disabilita silenziosamente l'intera configurazione degli hooks. Fai passare il tuo settings.json attraverso
jq .per validarlo. disableAllHooks: true-- Controlla se qualcuno (o una sessione di debug precedente) ha lasciato questo flag attivo.
L'Hook Gira ma Non Blocca
Sintomi: Il tuo hook PreToolUse viene eseguito, ma l'azione procede comunque.
Soluzioni:
- Codice di uscita sbagliato -- Il codice di uscita 1 significa "errore" (hook fallito), non "blocca". Usa
exit 2per bloccare un'azione. Questo frega quasi tutti, come notato nella documentazione ufficiale. - JSON stdout mancante -- Per gli hooks bloccanti, invia un messaggio JSON in modo che Claude sappia perché l'azione è stata bloccata:
echo '{"message": "Bloccato: motivo"}'
Loop Infiniti
Sintomi: Claude continua a riprovare la stessa azione, o la tua macchina si scalda in modo sospetto.
Soluzioni:
- Hook Stop che attiva azioni -- Se il tuo hook Stop scrive un file o esegue un comando che fa rispondere Claude, hai creato un loop. Gli hook Stop dovrebbero fare solo cose passive: loggare, notificare, pulire.
- Hook PostToolUse che causa modifiche -- Un hook PostToolUse che modifica un file attiva un altro evento PostToolUse. Proteggi da questo usando matcher specifici o il campo
if.
Problemi di Performance
Sintomi: Claude impiega notevolmente più tempo per avviarsi o eseguire gli strumenti.
Soluzioni:
- Troppi hook SessionStart -- Ciascuno gira sincronamente all'avvio. Mantienili leggeri (meno di 1 secondo ciascuno).
- Script pesanti nei percorsi caldi -- Gli hook su PreToolUse e PostToolUse si attivano frequentemente. Se il tuo script fa richieste di rete o calcoli pesanti, aggiungi un campo
timeout(in millisecondi) e valuta se dovrebbe essere un hook HTTP. - Nessuna cache -- Se stai controllando la stessa cosa ripetutamente (come "è questo un branch protetto?"), memorizza il risultato in un file temporaneo invece di eseguire comandi Git a ogni invocazione dell'hook.
Domande Frequenti
Cosa sono gli hooks di Claude Code e come funzionano?
Gli hooks di Claude Code sono script di automazione definiti dall'utente che vengono eseguiti a eventi specifici del ciclo di vita durante una sessione di Claude Code. Li configuri in settings.json con un pattern matcher e un handler (comando shell, endpoint HTTP, prompt o agent). Quando l'evento corrispondente si attiva, l'hook viene eseguito automaticamente e usa i codici di uscita per controllare il risultato.
Come configuro gli hooks in settings.json di Claude Code?
Aggiungi un oggetto "hooks" a una delle tre posizioni di configurazione: ~/.claude/settings.json (globale utente), .claude/settings.json (condiviso nel progetto) o .claude/settings.local.json (personale nel progetto). Ogni tipo di evento mappa a un array di definizioni di hook con matcher, campo if opzionale e un array hooks contenente oggetti handler con type e command o url.
Qual è la differenza tra hook PreToolUse e PostToolUse?
PreToolUse si attiva prima che uno strumento venga eseguito, dandoti il potere di bloccarlo con il codice di uscita 2. PostToolUse si attiva dopo il completamento dell'esecuzione, utile per formattazione, test o logging. PreToolUse serve per la prevenzione e il gating. PostToolUse serve per la validazione e la pulizia. Entrambi ricevono il nome dello strumento e l'input come JSON su stdin.
Gli hooks di Claude Code possono bloccare comandi pericolosi?
Sì. Gli hook PreToolUse con codice di uscita 2 bloccano qualsiasi esecuzione di strumento. Puoi proteggere i file sensibili dalla scrittura, bloccare comandi shell corrispondenti a pattern pericolosi come rm -rf o git push main, e impedire l'accesso ai database di produzione. Il messaggio di blocco viene inviato a Claude come feedback, in modo che possa adattare il suo approccio.
Quali eventi hook sono disponibili in Claude Code?
Claude Code fornisce 15+ eventi: PreToolUse e PostToolUse per l'esecuzione degli strumenti, Notification per gli alert, Stop per la fine della sessione, SessionStart per l'inizializzazione, UserPromptSubmit per il filtraggio degli input, PreCompact e PostCompact per la gestione del contesto, e nuovi eventi come ConfigChange, FileChanged, TaskCreated e PermissionDenied. Vedi la tabella di riferimento completa nella sezione degli eventi hook sopra.
Come differiscono gli hooks dagli strumenti MCP e dalle Skills?
Gli hooks sono deterministici -- si attivano sempre sugli eventi corrispondenti indipendentemente da ciò che decide Claude. Gli strumenti MCP estendono le capacità di Claude (accesso a database, chiamate API) ma Claude sceglie quando usarli. Le Skills sono pacchetti di istruzioni riutilizzabili invocati da slash command. CLAUDE.md fornisce indicazioni comportamentali. Usa gli hooks quando qualcosa deve succedere ogni volta, MCP quando Claude ha bisogno di nuove capacità.
Gli hooks di Claude Code funzionano in modalità headless?
Sì, con alcune avvertenze. Gli hook si attivano normalmente in modalità headless (claude -p), ma gli hook specifici del desktop come le notifiche macOS hanno bisogno di fallback. In particolare, gli hook PreToolUse che escono con codice 2 possono mettere in pausa le sessioni headless per l'approvazione umana tramite --resume. Questo abilita pipeline CI/CD human-in-the-loop dove certe azioni richiedono il via libera manuale.
Quanti hooks sono troppi? Gli hooks rallentano Claude Code?
Non c'è un limite rigido, ma ogni hook sincrono aggiunge latenza. Gli hook SessionStart vengono eseguiti all'avvio, quindi tienili veloci (meno di 1 secondo ciascuno). Gli hook PreToolUse e PostToolUse si attivano a ogni chiamata di strumento corrispondente -- gli script pesanti si accumulano rapidamente. Ti consiglio di tenere il totale degli hooks sotto 10-15, usare il campo if per restringere l'ambito e aggiungere valori timeout per prevenire script fuori controllo.
Posso usare gli hooks per auto-formattare il codice con Prettier o Black?
Sì -- è il caso d'uso più popolare degli hook. Crea un hook PostToolUse che corrisponde a Write|Edit, estrai il percorso del file dal JSON su stdin ed esegui il formatter appropriato in base all'estensione del file. Vedi l'esempio numero uno nella sezione degli esempi di produzione per una configurazione completa e pronta all'uso che gestisce file TypeScript, JavaScript e Python.
Gli hooks di Claude Code sono sicuri? Quali sono i rischi per la sicurezza?
Gli hook girano con i tuoi permessi utente completi -- non c'è sandbox. Un hook malevolo potrebbe leggere le tue chiavi SSH, eliminare file o esfiltrare dati. Usa solo hook da fonti fidate, rivedi qualsiasi .claude/settings.json condiviso prima di accettarlo nel tuo progetto, e usa .claude/settings.local.json per hook personali che non dovrebbero essere condivisi. Per pattern più ampi di sicurezza AI, consulta la nostra guida ai guardrail LLM.