Per una guida di avvio rapido con esempi, consulta Iniziare con i hook di Claude Code.

Configurazione

I hook di Claude Code sono configurati nei tuoi file di impostazioni:
  • ~/.claude/settings.json - Impostazioni utente
  • .claude/settings.json - Impostazioni progetto
  • .claude/settings.local.json - Impostazioni progetto locale (non sottoposte a commit)
  • Impostazioni di policy gestite dall’azienda

Struttura

I hook sono organizzati per matcher, dove ogni matcher può avere più hook:
{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here"
          }
        ]
      }
    ]
  }
}
  • matcher: Pattern per abbinare i nomi degli strumenti, sensibile alle maiuscole (applicabile solo per PreToolUse e PostToolUse)
    • Le stringhe semplici corrispondono esattamente: Write corrisponde solo allo strumento Write
    • Supporta regex: Edit|Write o Notebook.*
    • Usa * per abbinare tutti gli strumenti. Puoi anche usare una stringa vuota ("") o lasciare matcher vuoto.
  • hooks: Array di comandi da eseguire quando il pattern corrisponde
    • type: Attualmente è supportato solo "command"
    • command: Il comando bash da eseguire (può usare la variabile di ambiente $CLAUDE_PROJECT_DIR)
    • timeout: (Opzionale) Quanto tempo un comando dovrebbe eseguire, in secondi, prima di annullare quel comando specifico.
Per eventi come UserPromptSubmit, Notification, Stop e SubagentStop che non usano matcher, puoi omettere il campo matcher:
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/prompt-validator.py"
          }
        ]
      }
    ]
  }
}

Script di hook specifici del progetto

Puoi usare la variabile di ambiente CLAUDE_PROJECT_DIR (disponibile solo quando Claude Code genera il comando hook) per fare riferimento a script archiviati nel tuo progetto, assicurando che funzionino indipendentemente dalla directory corrente di Claude:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
          }
        ]
      }
    ]
  }
}

Hook dei plugin

I plugin possono fornire hook che si integrano perfettamente con i tuoi hook utente e progetto. Gli hook dei plugin vengono automaticamente uniti alla tua configurazione quando i plugin sono abilitati. Come funzionano gli hook dei plugin:
  • Gli hook dei plugin sono definiti nel file hooks/hooks.json del plugin o in un file fornito da un percorso personalizzato al campo hooks.
  • Quando un plugin è abilitato, i suoi hook vengono uniti con gli hook utente e progetto
  • Più hook da fonti diverse possono rispondere allo stesso evento
  • Gli hook dei plugin usano la variabile di ambiente ${CLAUDE_PLUGIN_ROOT} per fare riferimento ai file del plugin
Esempio di configurazione hook del plugin:
{
  "description": "Automatic code formatting",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
Gli hook dei plugin usano lo stesso formato degli hook regolari con un campo description opzionale per spiegare lo scopo dell’hook.
Gli hook dei plugin vengono eseguiti insieme ai tuoi hook personalizzati. Se più hook corrispondono a un evento, vengono tutti eseguiti in parallelo.
Variabili di ambiente per i plugin:
  • ${CLAUDE_PLUGIN_ROOT}: Percorso assoluto della directory del plugin
  • ${CLAUDE_PROJECT_DIR}: Directory radice del progetto (uguale a quella per gli hook del progetto)
  • Tutte le variabili di ambiente standard sono disponibili
Consulta il riferimento dei componenti del plugin per i dettagli sulla creazione di hook dei plugin.

Eventi hook

PreToolUse

Viene eseguito dopo che Claude crea i parametri dello strumento e prima dell’elaborazione della chiamata dello strumento. Matcher comuni:
  • Task - Attività subagent (consulta la documentazione dei subagent)
  • Bash - Comandi shell
  • Glob - Corrispondenza del pattern di file
  • Grep - Ricerca di contenuti
  • Read - Lettura di file
  • Edit - Modifica di file
  • Write - Scrittura di file
  • WebFetch, WebSearch - Operazioni web

PostToolUse

Viene eseguito immediatamente dopo il completamento riuscito di uno strumento. Riconosce gli stessi valori di matcher di PreToolUse.

Notification

Viene eseguito quando Claude Code invia notifiche. Le notifiche vengono inviate quando:
  1. Claude ha bisogno della tua autorizzazione per usare uno strumento. Esempio: “Claude ha bisogno della tua autorizzazione per usare Bash”
  2. L’input del prompt è rimasto inattivo per almeno 60 secondi. “Claude sta aspettando il tuo input”

UserPromptSubmit

Viene eseguito quando l’utente invia un prompt, prima che Claude lo elabori. Questo ti consente di aggiungere contesto aggiuntivo in base al prompt/conversazione, convalidare i prompt o bloccare determinati tipi di prompt.

Stop

Viene eseguito quando l’agente Claude Code principale ha finito di rispondere. Non viene eseguito se l’arresto è avvenuto a causa di un’interruzione dell’utente.

SubagentStop

Viene eseguito quando un subagent di Claude Code (chiamata dello strumento Task) ha finito di rispondere.

PreCompact

Viene eseguito prima che Claude Code stia per eseguire un’operazione di compattazione. Matcher:
  • manual - Richiamato da /compact
  • auto - Richiamato da auto-compact (a causa della finestra di contesto piena)

SessionStart

Viene eseguito quando Claude Code avvia una nuova sessione o riprende una sessione esistente (che attualmente avvia una nuova sessione sotto il cofano). Utile per caricare il contesto di sviluppo come problemi esistenti o modifiche recenti al tuo codebase, installare dipendenze o configurare variabili di ambiente. Matcher:
  • startup - Richiamato all’avvio
  • resume - Richiamato da --resume, --continue o /resume
  • clear - Richiamato da /clear
  • compact - Richiamato da compattazione automatica o manuale.

Persistenza delle variabili di ambiente

Gli hook SessionStart hanno accesso alla variabile di ambiente CLAUDE_ENV_FILE, che fornisce un percorso di file dove puoi persistere le variabili di ambiente per i successivi comandi bash. Esempio: Impostazione di singole variabili di ambiente
#!/bin/bash

if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
  echo 'export API_KEY=your-api-key' >> "$CLAUDE_ENV_FILE"
  echo 'export PATH="$PATH:./node_modules/.bin"' >> "$CLAUDE_ENV_FILE"
fi

exit 0
Esempio: Persistenza di tutti i cambiamenti di ambiente dall’hook Quando la tua configurazione modifica l’ambiente (ad es. nvm use), acquisisci e persisti tutti i cambiamenti confrontando l’ambiente:
#!/bin/bash

ENV_BEFORE=$(export -p | sort)

# Run your setup commands that modify the environment
source ~/.nvm/nvm.sh
nvm use 20

if [ -n "$CLAUDE_ENV_FILE" ]; then
  ENV_AFTER=$(export -p | sort)
  comm -13 <(echo "$ENV_BEFORE") <(echo "$ENV_AFTER") >> "$CLAUDE_ENV_FILE"
fi

exit 0
Tutte le variabili scritte in questo file saranno disponibili in tutti i successivi comandi bash che Claude Code esegue durante la sessione.
CLAUDE_ENV_FILE è disponibile solo per gli hook SessionStart. Gli altri tipi di hook non hanno accesso a questa variabile.

SessionEnd

Viene eseguito quando una sessione di Claude Code termina. Utile per attività di pulizia, registrazione delle statistiche della sessione o salvataggio dello stato della sessione. Il campo reason nell’input dell’hook sarà uno di:
  • clear - Sessione cancellata con il comando /clear
  • logout - Utente disconnesso
  • prompt_input_exit - Utente uscito mentre l’input del prompt era visibile
  • other - Altri motivi di uscita

Input dell’hook

Gli hook ricevono dati JSON tramite stdin contenenti informazioni sulla sessione e dati specifici dell’evento:
{
  // Common fields
  session_id: string
  transcript_path: string  // Path to conversation JSON
  cwd: string              // The current working directory when the hook is invoked
  permission_mode: string  // Current permission mode: "default", "plan", "acceptEdits", or "bypassPermissions"

  // Event-specific fields
  hook_event_name: string
  ...
}

Input PreToolUse

Lo schema esatto per tool_input dipende dallo strumento.
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  }
}

Input PostToolUse

Lo schema esatto per tool_input e tool_response dipende dallo strumento.
{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PostToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_response": {
    "filePath": "/path/to/file.txt",
    "success": true
  }
}

Input Notification

{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "Notification",
  "message": "Task completed successfully"
}

Input UserPromptSubmit

{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "UserPromptSubmit",
  "prompt": "Write a function to calculate the factorial of a number"
}

Input Stop e SubagentStop

stop_hook_active è true quando Claude Code sta già continuando a causa di un hook di stop. Controlla questo valore o elabora la trascrizione per evitare che Claude Code continui indefinitamente.
{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "permission_mode": "default",
  "hook_event_name": "Stop",
  "stop_hook_active": true
}

Input PreCompact

Per manual, custom_instructions proviene da quello che l’utente passa in /compact. Per auto, custom_instructions è vuoto.
{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "permission_mode": "default",
  "hook_event_name": "PreCompact",
  "trigger": "manual",
  "custom_instructions": ""
}

Input SessionStart

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "permission_mode": "default",
  "hook_event_name": "SessionStart",
  "source": "startup"
}

Input SessionEnd

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "SessionEnd",
  "reason": "exit"
}

Output dell’hook

Ci sono due modi per gli hook di restituire output a Claude Code. L’output comunica se bloccare e qualsiasi feedback che dovrebbe essere mostrato a Claude e all’utente.

Semplice: Codice di uscita

Gli hook comunicano lo stato attraverso codici di uscita, stdout e stderr:
  • Codice di uscita 0: Successo. stdout viene mostrato all’utente in modalità trascrizione (CTRL-R), tranne per UserPromptSubmit e SessionStart, dove stdout viene aggiunto al contesto.
  • Codice di uscita 2: Errore di blocco. stderr viene restituito a Claude per l’elaborazione automatica. Consulta il comportamento specifico dell’evento hook di seguito.
  • Altri codici di uscita: Errore non bloccante. stderr viene mostrato all’utente e l’esecuzione continua.
Promemoria: Claude Code non vede stdout se il codice di uscita è 0, tranne per l’hook UserPromptSubmit dove stdout viene iniettato come contesto.

Comportamento del codice di uscita 2

Evento hookComportamento
PreToolUseBlocca la chiamata dello strumento, mostra stderr a Claude
PostToolUseMostra stderr a Claude (lo strumento è già stato eseguito)
NotificationN/A, mostra stderr solo all’utente
UserPromptSubmitBlocca l’elaborazione del prompt, cancella il prompt, mostra stderr solo all’utente
StopBlocca l’arresto, mostra stderr a Claude
SubagentStopBlocca l’arresto, mostra stderr al subagent Claude
PreCompactN/A, mostra stderr solo all’utente
SessionStartN/A, mostra stderr solo all’utente
SessionEndN/A, mostra stderr solo all’utente

Avanzato: Output JSON

Gli hook possono restituire JSON strutturato in stdout per un controllo più sofisticato:

Campi JSON comuni

Tutti i tipi di hook possono includere questi campi opzionali:
{
  "continue": true, // Whether Claude should continue after hook execution (default: true)
  "stopReason": "string", // Message shown when continue is false

  "suppressOutput": true, // Hide stdout from transcript mode (default: false)
  "systemMessage": "string" // Optional warning message shown to the user
}
Se continue è false, Claude interrompe l’elaborazione dopo l’esecuzione degli hook.
  • Per PreToolUse, questo è diverso da "permissionDecision": "deny", che blocca solo una chiamata dello strumento specifica e fornisce feedback automatico a Claude.
  • Per PostToolUse, questo è diverso da "decision": "block", che fornisce feedback automatizzato a Claude.
  • Per UserPromptSubmit, questo impedisce l’elaborazione del prompt.
  • Per Stop e SubagentStop, questo ha la precedenza su qualsiasi output "decision": "block".
  • In tutti i casi, "continue" = false ha la precedenza su qualsiasi output "decision": "block".
stopReason accompagna continue con un motivo mostrato all’utente, non mostrato a Claude.

Controllo della decisione PreToolUse

Gli hook PreToolUse possono controllare se una chiamata dello strumento procede.
  • "allow" bypassa il sistema di autorizzazione. permissionDecisionReason viene mostrato all’utente ma non a Claude.
  • "deny" impedisce l’esecuzione della chiamata dello strumento. permissionDecisionReason viene mostrato a Claude.
  • "ask" chiede all’utente di confermare la chiamata dello strumento nell’interfaccia utente. permissionDecisionReason viene mostrato all’utente ma non a Claude.
Inoltre, gli hook possono modificare gli input dello strumento prima dell’esecuzione usando updatedInput:
  • updatedInput ti consente di modificare i parametri di input dello strumento prima dell’esecuzione dello strumento. Questo è un oggetto Record<string, unknown> contenente i campi che desideri modificare o aggiungere.
  • Questo è più utile con "permissionDecision": "allow" per modificare e approvare le chiamate dello strumento.
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow"
    "permissionDecisionReason": "My reason here",
    "updatedInput": {
      "field_to_modify": "new value"
    }
  }
}
I campi decision e reason sono deprecati per gli hook PreToolUse. Usa hookSpecificOutput.permissionDecision e hookSpecificOutput.permissionDecisionReason invece. I campi deprecati "approve" e "block" corrispondono a "allow" e "deny" rispettivamente.

Controllo della decisione PostToolUse

Gli hook PostToolUse possono fornire feedback a Claude dopo l’esecuzione dello strumento.
  • "block" richiede automaticamente a Claude con reason.
  • undefined non fa nulla. reason viene ignorato.
  • "hookSpecificOutput.additionalContext" aggiunge contesto per Claude da considerare.
{
  "decision": "block" | undefined,
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "Additional information for Claude"
  }
}

Controllo della decisione UserPromptSubmit

Gli hook UserPromptSubmit possono controllare se un prompt dell’utente viene elaborato.
  • "block" impedisce l’elaborazione del prompt. Il prompt inviato viene cancellato dal contesto. "reason" viene mostrato all’utente ma non aggiunto al contesto.
  • undefined consente al prompt di procedere normalmente. "reason" viene ignorato.
  • "hookSpecificOutput.additionalContext" aggiunge la stringa al contesto se non bloccato.
{
  "decision": "block" | undefined,
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "My additional context here"
  }
}

Controllo della decisione Stop/SubagentStop

Gli hook Stop e SubagentStop possono controllare se Claude deve continuare.
  • "block" impedisce a Claude di fermarsi. Devi popolare reason affinché Claude sappia come procedere.
  • undefined consente a Claude di fermarsi. reason viene ignorato.
{
  "decision": "block" | undefined,
  "reason": "Must be provided when Claude is blocked from stopping"
}

Controllo della decisione SessionStart

Gli hook SessionStart ti consentono di caricare il contesto all’inizio di una sessione.
  • "hookSpecificOutput.additionalContext" aggiunge la stringa al contesto.
  • I valori additionalContext di più hook vengono concatenati.
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "My additional context here"
  }
}

Controllo della decisione SessionEnd

Gli hook SessionEnd vengono eseguiti quando una sessione termina. Non possono bloccare la terminazione della sessione ma possono eseguire attività di pulizia.

Esempio di codice di uscita: Convalida del comando Bash

#!/usr/bin/env python3
import json
import re
import sys

# Define validation rules as a list of (regex pattern, message) tuples
VALIDATION_RULES = [
    (
        r"\bgrep\b(?!.*\|)",
        "Use 'rg' (ripgrep) instead of 'grep' for better performance and features",
    ),
    (
        r"\bfind\s+\S+\s+-name\b",
        "Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance",
    ),
]


def validate_command(command: str) -> list[str]:
    issues = []
    for pattern, message in VALIDATION_RULES:
        if re.search(pattern, command):
            issues.append(message)
    return issues


try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
    sys.exit(1)

tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
command = tool_input.get("command", "")

if tool_name != "Bash" or not command:
    sys.exit(1)

# Validate the command
issues = validate_command(command)

if issues:
    for message in issues:
        print(f"• {message}", file=sys.stderr)
    # Exit code 2 blocks tool call and shows stderr to Claude
    sys.exit(2)

Esempio di output JSON: UserPromptSubmit per aggiungere contesto e convalida

Per gli hook UserPromptSubmit, puoi iniettare il contesto usando uno dei due metodi:
  • Codice di uscita 0 con stdout: Claude vede il contesto (caso speciale per UserPromptSubmit)
  • Output JSON: Fornisce un controllo più sofisticato sul comportamento
#!/usr/bin/env python3
import json
import sys
import re
import datetime

# Load input from stdin
try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
    sys.exit(1)

prompt = input_data.get("prompt", "")

# Check for sensitive patterns
sensitive_patterns = [
    (r"(?i)\b(password|secret|key|token)\s*[:=]", "Prompt contains potential secrets"),
]

for pattern, message in sensitive_patterns:
    if re.search(pattern, prompt):
        # Use JSON output to block with a specific reason
        output = {
            "decision": "block",
            "reason": f"Security policy violation: {message}. Please rephrase your request without sensitive information."
        }
        print(json.dumps(output))
        sys.exit(0)

# Add current time to context
context = f"Current time: {datetime.datetime.now()}"
print(context)

"""
The following is also equivalent:
print(json.dumps({
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": context,
  },
}))
"""

# Allow the prompt to proceed with the additional context
sys.exit(0)

Esempio di output JSON: PreToolUse con approvazione

#!/usr/bin/env python3
import json
import sys

# Load input from stdin
try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
    sys.exit(1)

tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})

# Example: Auto-approve file reads for documentation files
if tool_name == "Read":
    file_path = tool_input.get("file_path", "")
    if file_path.endswith((".md", ".mdx", ".txt", ".json")):
        # Use JSON output to auto-approve the tool call
        output = {
            "decision": "approve",
            "reason": "Documentation file auto-approved",
            "suppressOutput": True  # Don't show in transcript mode
        }
        print(json.dumps(output))
        sys.exit(0)

# For other cases, let the normal permission flow proceed
sys.exit(0)

Utilizzo degli strumenti MCP

Gli hook di Claude Code funzionano perfettamente con gli strumenti Model Context Protocol (MCP). Quando i server MCP forniscono strumenti, appaiono con un pattern di denominazione speciale che puoi abbinare nei tuoi hook.

Denominazione degli strumenti MCP

Gli strumenti MCP seguono il pattern mcp__<server>__<tool>, ad esempio:
  • mcp__memory__create_entities - Strumento create entities del server Memory
  • mcp__filesystem__read_file - Strumento read file del server Filesystem
  • mcp__github__search_repositories - Strumento search del server GitHub

Configurazione degli hook per gli strumenti MCP

Puoi indirizzare strumenti MCP specifici o interi server MCP:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__memory__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
          }
        ]
      },
      {
        "matcher": "mcp__.*__write.*",
        "hooks": [
          {
            "type": "command",
            "command": "/home/user/scripts/validate-mcp-write.py"
          }
        ]
      }
    ]
  }
}

Esempi

Per esempi pratici inclusi formattazione del codice, notifiche e protezione dei file, consulta Altri esempi nella guida di avvio.

Considerazioni sulla sicurezza

Disclaimer

UTILIZZO A TUO RISCHIO: Gli hook di Claude Code eseguono comandi shell arbitrari sul tuo sistema automaticamente. Utilizzando gli hook, riconosci che:
  • Sei l’unico responsabile dei comandi che configuri
  • Gli hook possono modificare, eliminare o accedere a qualsiasi file a cui il tuo account utente può accedere
  • Gli hook dannosi o scritti male possono causare perdita di dati o danni al sistema
  • Anthropic non fornisce alcuna garanzia e non assume alcuna responsabilità per eventuali danni derivanti dall’utilizzo degli hook
  • Dovresti testare accuratamente gli hook in un ambiente sicuro prima dell’uso in produzione
Rivedi sempre e comprendi qualsiasi comando hook prima di aggiungerlo alla tua configurazione.

Migliori pratiche di sicurezza

Ecco alcune pratiche chiave per scrivere hook più sicuri:
  1. Convalida e sanitizza gli input - Non fidarti mai ciecamente dei dati di input
  2. Racchiudi sempre tra virgolette le variabili shell - Usa "$VAR" non $VAR
  3. Blocca il path traversal - Controlla .. nei percorsi dei file
  4. Usa percorsi assoluti - Specifica percorsi completi per gli script (usa “$CLAUDE_PROJECT_DIR” per il percorso del progetto)
  5. Salta i file sensibili - Evita .env, .git/, chiavi, ecc.

Sicurezza della configurazione

Le modifiche dirette agli hook nei file di impostazioni non hanno effetto immediato. Claude Code:
  1. Acquisisce uno snapshot degli hook all’avvio
  2. Usa questo snapshot durante tutta la sessione
  3. Avverte se gli hook vengono modificati esternamente
  4. Richiede la revisione nel menu /hooks affinché i cambiamenti abbiano effetto
Questo impedisce che le modifiche malintenzionate degli hook influenzino la tua sessione corrente.

Dettagli dell’esecuzione dell’hook

  • Timeout: Limite di esecuzione di 60 secondi per impostazione predefinita, configurabile per comando.
    • Un timeout per un comando individuale non influisce sugli altri comandi.
  • Parallelizzazione: Tutti gli hook corrispondenti vengono eseguiti in parallelo
  • Deduplicazione: I comandi hook identici multipli vengono automaticamente deduplicati
  • Ambiente: Viene eseguito nella directory corrente con l’ambiente di Claude Code
    • La variabile di ambiente CLAUDE_PROJECT_DIR è disponibile e contiene il percorso assoluto della directory radice del progetto (dove Claude Code è stato avviato)
    • La variabile di ambiente CLAUDE_CODE_REMOTE indica se l’hook è in esecuzione in un ambiente remoto (web) ("true") o in un ambiente CLI locale (non impostato o vuoto). Usalo per eseguire logica diversa in base al contesto di esecuzione.
  • Input: JSON via stdin
  • Output:
    • PreToolUse/PostToolUse/Stop/SubagentStop: Progresso mostrato nella trascrizione (Ctrl-R)
    • Notification/SessionEnd: Registrato solo nel debug (--debug)
    • UserPromptSubmit/SessionStart: stdout aggiunto come contesto per Claude

Debug

Risoluzione dei problemi di base

Se i tuoi hook non funzionano:
  1. Controlla la configurazione - Esegui /hooks per vedere se il tuo hook è registrato
  2. Verifica la sintassi - Assicurati che le tue impostazioni JSON siano valide
  3. Testa i comandi - Esegui prima manualmente i comandi hook
  4. Controlla i permessi - Assicurati che gli script siano eseguibili
  5. Rivedi i log - Usa claude --debug per vedere i dettagli dell’esecuzione dell’hook
Problemi comuni:
  • Virgolette non sfuggite - Usa \" all’interno delle stringhe JSON
  • Matcher sbagliato - Controlla che i nomi degli strumenti corrispondano esattamente (sensibile alle maiuscole)
  • Comando non trovato - Usa percorsi completi per gli script

Debug avanzato

Per problemi di hook complessi:
  1. Ispeziona l’esecuzione dell’hook - Usa claude --debug per vedere l’esecuzione dettagliata dell’hook
  2. Convalida gli schemi JSON - Testa l’input/output dell’hook con strumenti esterni
  3. Controlla le variabili di ambiente - Verifica che l’ambiente di Claude Code sia corretto
  4. Testa i casi limite - Prova gli hook con percorsi di file o input insoliti
  5. Monitora le risorse di sistema - Controlla l’esaurimento delle risorse durante l’esecuzione dell’hook
  6. Usa la registrazione strutturata - Implementa la registrazione negli script dell’hook

Esempio di output di debug

Usa claude --debug per vedere i dettagli dell’esecuzione dell’hook:
[DEBUG] Executing hooks for PostToolUse:Write
[DEBUG] Getting matching hook commands for PostToolUse with query: Write
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 hooks for query "Write"
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: <Your command> with timeout 60000ms
[DEBUG] Hook command completed with status 0: <Your stdout>
I messaggi di progresso appaiono in modalità trascrizione (Ctrl-R) mostrando:
  • Quale hook è in esecuzione
  • Comando in esecuzione
  • Stato di successo/fallimento
  • Messaggi di output o errore