PostToolUse: formatter e test in Claude Code
Usa PostToolUse per formattare e ricevere feedback sui test. Gestisci percorsi, async e concorrenza senza confondere il controllo con un rollback.
Tempo di lettura: 11 min

PostToolUse permette di reagire dopo una chiamata riuscita a uno strumento di Claude Code. Può avviare un formatter sui file modificati, controllare una condizione e fornire feedback utile alla prossima azione. La distinzione fondamentale è temporale: la modifica è già avvenuta. Un risultato negativo del controllo non ripristina automaticamente il contenuto precedente. PostToolUse nella reference ufficiale.
Per un team che sviluppa un gestionale o un sito, il valore sta nel feedback pertinente: formattare il file corretto, eseguire il controllo opportuno e sapere a quale stato del progetto appartiene il risultato. Far partire tutto dopo ogni edit può produrre concorrenza e risultati ormai superati. La guida ai Claude Code Hooks presenta il meccanismo generale; qui progettiamo il lavoro successivo alla modifica.
Le fonti sono state verificate il 9 ottobre 2026. Gli esempi e gli snippet sono didattici e non sono stati eseguiti per questa guida. Una suite dichiarata positiva richiede comunque un risultato effettivamente raccolto nel progetto del lettore.
In sintesi
- PostToolUse riguarda una tool call riuscita; i fallimenti hanno un evento dedicato.
- Il formatter deve ricevere un percorso valido e supportato.
- Handler distinti non offrono un ordine sequenziale implicito.
- Async permette lavoro in background e non una decisione retroattiva.
- Il risultato dei test deve riferirsi ai file che saranno consegnati.
Che cosa deve fare il controllo dopo un edit?
La prima scelta è definire l’unità di lavoro. Un formatter opera spesso sul file appena modificato. Un typecheck può riguardare il progetto. Un test può interessare un modulo preciso oppure una suite più ampia. Queste unità hanno durate e dipendenze differenti; metterle nello stesso elenco di hook non spiega come devono coordinarsi.
Scrivi un contratto breve: estensioni incluse, cartelle escluse, comando usato e risultato atteso. “Formatta i file TS e TSX del progetto con la configurazione già presente” è verificabile. “Sistema il codice” invita ad azioni implicite, come installare un tool o riscrivere più file. Un hook dovrebbe richiamare una decisione del progetto, non decidere lo stack a ogni evento.
Per chi usa Claude come assistente di sviluppo, Claude per codice aiuta a collocare il formatter fra generazione, revisione e test. La formattazione può rendere un diff leggibile, ma non dimostra la correttezza della logica o il rispetto dei requisiti del software.
Quali chiamate intercetta il matcher Edit e Write?
Un matcher Edit|Write seleziona quei nomi di tool. Non seleziona ogni operazione che modifica file. Se Claude esegue uno script attraverso Bash e quel programma scrive un file, il tool event rimane una chiamata Bash. Se un editor esterno salva una modifica, la registrazione PostToolUse proposta qui non può essere usata come prova di copertura di quell’azione. Regole dei matcher.
Il filtro serve a ridurre lavoro inutile, ma va accompagnato da un’interpretazione dell’input. Un file binario, una cartella, un percorso fuori dal repository e un’estensione non supportata devono essere gestiti esplicitamente. Il nome del tool da solo non autorizza a invocare un programma su qualunque valore ricevuto.
Non aggiungere un matcher generico solo per raggiungere “tutte le modifiche”. Se il progetto usa altri canali, documentali e scegli un evento o un punto di controllo adatto. Per comprendere la differenza fra tentativi di edit e stato del repository può essere utile Replay Theater, con i suoi limiti di visualizzazione.
Un formatter locale con percorso trattato come dato
Il seguente esempio usa Python 3 per leggere l’evento e lanciare pnpm exec prettier con argomenti separati. Presuppone un progetto che ha già Prettier come dipendenza, una sua configurazione valida e pnpm disponibile. Non installa dipendenze e non cerca un formatter alternativo. È uno snippet didattico non eseguito. Esempio ufficiale di formatting.
import json
import os
import subprocess
import sys
from pathlib import Path
try:
event = json.load(sys.stdin)
if event.get("tool_name") not in {"Edit", "Write"}:
sys.exit(0)
root = Path(os.environ["CLAUDE_PROJECT_DIR"]).resolve()
raw = event.get("tool_input", {}).get("file_path")
if not isinstance(raw, str):
sys.exit(0)
target = Path(raw)
if not target.is_absolute():
target = root / target
target = target.resolve()
if root not in target.parents or not target.is_file():
sys.exit(0)
if target.suffix not in {".ts", ".tsx", ".js", ".jsx"}:
sys.exit(0)
result = subprocess.run(
["pnpm", "exec", "prettier", "--write", str(target)],
cwd=root,
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
print("Formatter non riuscito: verifica il file.", file=sys.stderr)
sys.exit(1)
except (ValueError, KeyError, OSError, AttributeError, subprocess.TimeoutExpired):
print("Formatter non disponibile: controllo da ripetere.", file=sys.stderr)
sys.exit(1)
Il timeout dello script è una scelta illustrativa, non un benchmark o una raccomandazione universale. L’esito distingue il controllo non riuscito dalla formattazione completata; il testo di errore evita di riversare automaticamente nei log l’intero contenuto dei file o l’output del programma.
Come collegare lo script a PostToolUse?
La registrazione seguente può vivere nei settings del progetto. Il file dello script, i prerequisiti e la configurazione del formatter devono essere condivisi con il team. Integra il blocco nel JSON già presente e controlla il risultato in /hooks. Configurazione dei settings hook.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/format_file.py\""
}
]
}
]
}
}
Questa configurazione non dichiara async perché l’esempio riguarda un formatter che modifica il file. La scelta non certifica il corretto ordinamento di ogni attività del progetto: va provata nel workflow reale. Se una suite dipende dal contenuto formattato, un unico script può eseguire prima il formatter e poi il controllo, rendendo la dipendenza visibile.
Per un errore di registrazione o di input, debug dei Hooks offre una diagnosi progressiva. Il primo controllo non è cambiare Prettier: è sapere se l’evento corretto ha effettivamente chiamato lo script.
Quando i test devono aspettare il formatter?
I handler corrispondenti a un evento possono essere eseguiti in parallelo. Scrivere un formatter e una suite in due voci consecutive non garantisce che la suite legga i file dopo la formattazione. Se il formatter riscrive il contenuto mentre il test lo carica, il risultato può riguardare uno stato intermedio. Esecuzione e lifecycle dei Hooks.
| Attività | Modifica file? | Ha bisogno di ordinamento? | Prova richiesta |
|---|---|---|---|
| Formatter sul file | Sì | Prima dei controlli che leggono l’output | Diff finale |
| Lint senza fix | No | Dopo l’eventuale formatter | Esito e stato verificato |
| Test del modulo | In genere no | Dopo gli edit pertinenti | Comando e risultato |
| Build del progetto | Può creare artefatti | Dopo modifiche e configurazione | Log sintetico della build |
| Review del diff | No | Sullo stato destinato alla consegna | Diff effettivamente letto |
Se è necessaria una catena, scrivila in uno script del progetto o usa una pipeline che ne definisca l’ordine. Il hook diventa il trigger, mentre il processo di verifica resta esplicito. Così è anche possibile eseguire lo stesso controllo fuori da Claude Code e confrontare gli esiti.
Quando usare async per una verifica lunga?
Solo gli handler command supportano async nella configurazione descritta. Il comando viene eseguito in background; il risultato può essere disponibile più tardi e non può applicare una decisione che blocchi l’azione precedente. Il progetto deve quindi gestire il periodo in cui la verifica è in corso. Run hooks in the background.
Async è utile quando l’attività successiva non dipende immediatamente dal risultato. Può essere sensato per una suite che controlla un modulo già stabilizzato mentre lo sviluppatore legge documentazione. È meno adatto a un formatter che continuerà a riscrivere un file mentre l’agente lo modifica di nuovo.
Il risultato deve indicare almeno quale controllo è stato eseguito e su quale stato. Non è necessario pubblicare ogni riga del log: serve evitare che un risultato di una versione precedente venga scambiato per quello dei file correnti. Alla consegna, un controllo ancora in corso va chiamato “in corso”, non “superato”.
Come evitare verifiche duplicate e risultati superati?
Dopo una serie di edit possono avviarsi diversi processi. Anche se ciascuno funziona, il team può ricevere output disordinato: un primo test termina dopo quello più recente oppure un formatter lavora sul file che nel frattempo è cambiato. Questo è un problema di coordinamento, non di qualità del modello.
Una strategia è ridurre i trigger, eseguire controlli rapidi sul file e riservare le verifiche complete a un punto definito. Un’altra è serializzare il comando con un meccanismo di lock del progetto, gestendo esplicitamente il caso occupato. Qualunque meccanismo deve evitare che “già in esecuzione” venga interpretato come esito positivo.
La fase finale può usare Stop hook senza loop per verificare una condizione di consegna, ma non per inseguire indefinitamente una suite che richiede un servizio indisponibile. La pipeline del progetto rimane il luogo in cui validare il risultato destinato alla pubblicazione.
Quale feedback deve ricevere Claude dopo un fallimento?
Un feedback utile è corto e operativo: controllo non riuscito, categoria del problema, riferimento al risultato locale. Evita di stampare file interi, dump dell’ambiente o output che include credenziali. Se serve una diagnosi dettagliata, conserva il log secondo la policy del progetto e leggi soltanto la parte pertinente.
Un fallimento del formatter non richiede automaticamente una grande riscrittura. Potrebbe dipendere da sintassi non supportata, configurazione assente o percorso errato. Prima di chiedere nuove modifiche, distingui errore del codice ed errore del processo di controllo. Questa distinzione impedisce cicli in cui l’agente “corregge” file che non hanno causato il problema.
Una scheda per un risultato di test leggibile
Indica nome del comando, modulo o revisione controllata, stato concluso oppure in corso ed esito. Se il controllo non è partito, scrivi la causa tecnica. Il log completo può restare nel progetto: la risposta deve riportare l’evidenza necessaria a capire se la modifica corrente è stata verificata.
La valutazione di un risultato è diversa dalla prevenzione. Per impedire una modifica prima che avvenga, serve il percorso dedicato a PreToolUse e file protetti.
Due workflow italiani con una verifica proporzionata
Esempio ipotetico, non testato: un e-commerce di Bologna mantiene un componente React per la selezione delle varianti. Dopo Edit, il team vuole formattare il file e controllare i test del componente. Prima prepara un file di prova con un nome contenente spazi, verifica che il formatter riceva il percorso come un singolo argomento e osserva il diff prodotto. Poi collega il test pertinente, senza attribuire un risultato positivo a una suite mai eseguita.
Esempio ipotetico, non testato: un’impresa di logistica a Parma lavora su un importatore di righe CSV sintetiche. Gli edit avvengono in pochi file, ma i test completi richiedono anche un servizio locale. Il progetto può eseguire subito lint e test unitari, riservando la verifica integrata a un momento in cui il servizio è disponibile. Il report deve distinguere “unitari passati” e “integrazione non eseguita”, invece di condensarli in “tutto funziona”.
In entrambi i casi la scelta del controllo deriva dalla modifica. Un edit a un testo non richiede necessariamente la medesima suite di un cambiamento alla logica di pagamento. Il hook non deve appiattire queste responsabilità in un comando universale.
Quali errori evitare in un hook di formatting e test?
Il primo è usare un comando che scarica strumenti automaticamente quando mancano. Il secondo è invocare il formatter su tutto il repository per ogni singolo edit, generando diff non pertinenti. Il terzo è presumere che l’ordine del JSON coordini i processi. Il quarto è ignorare gli exit code. Il quinto è dichiarare “verificato” prima che il risultato sia arrivato.
Per un team delegato, controlla anche chi può modificare lo stesso file. Hooks per subagent e team spiega come separare fine risposta, fine task e responsabilità delle prove. Le notifiche locali possono segnalare attenzione, ma il loro arrivo non certifica il superamento dei test.
La guida ufficiale Security guidance mostra un approccio a più momenti del workflow. È un riferimento da leggere con prerequisiti e limiti: un controllo aggiuntivo non sostituisce la CI né la revisione del software consegnato.
Quale controllo ripetere dopo una correzione?
Una correzione del codice richiede ripetere le verifiche che possono dipendere da quel cambiamento. Non occorre avviare meccanicamente ogni comando disponibile, ma serve una motivazione: il test del modulo coinvolto, il controllo dei tipi quando cambia un’interfaccia e la build quando configurazione o dipendenze lo richiedono.
Se la correzione riguarda soltanto lo script del hook, prova nuovamente le fixture e il percorso nella sessione. Se riguarda il contenuto elaborato, osserva anche il diff finale. Il report deve chiarire quale livello è stato corretto: automazione di controllo oppure software dell’applicazione. Questa distinzione evita che un formatter finalmente avviato venga presentato come prova della correttezza del prodotto.
Come decidere che il flusso è pronto per il team?
Il flusso è pronto quando il team riesce a ripetere il controllo, osserva gli errori e sa quale stato è stato verificato. Conserva una fixture sintetica per il percorso incluso, una per il percorso escluso e una per un comando fallito. Confronta la prova diretta dello script con l’esecuzione attraverso Claude Code.
Per distribuire personalizzazioni più ampie, Mods di Claude aiuta a scegliere fra un hook nei settings e una funzione dentro un plugin. Non introdurre un mod soltanto per richiamare un comando già chiaramente gestibile dallo script del progetto.
Se il workflow riguarda un’applicazione aziendale, il percorso di software su misura può includere una catena di verifica adatta al suo rischio e alle sue dipendenze. Il risultato da cercare è semplice: edit leggibili, controlli conclusi e prove relative alla versione effettivamente pronta per la consegna.
Metodo e fonti delle guide di Giallo Studio
Come lo applichiamo in azienda
Risorse correlate
Claude Code Hooks: guida pratica in italiano
PreToolUse: proteggere file in Claude Code
Notifiche Claude Code: hook locali e permessi
SessionStart: contesto dopo compaction
Stop hook: verifiche senza loop in Claude Code
Mods di Claude: cosa sono e quando servono in Claude Code
Claude AI per codice e sviluppoFAQ
PostToolUse si attiva dopo un errore del tool?
PostToolUse riguarda una tool call riuscita. Per le chiamate fallite esiste PostToolUseFailure, con un contratto dedicato.
Il formatter può girare dopo Edit e Write?
Sì, un matcher può selezionare questi tool. Lo script deve controllare il percorso ricevuto e usare un formatter già previsto dal progetto.
Quando usare un hook async?
Quando il controllo può proseguire in background senza decidere se autorizzare l’azione. L’esito arriva dopo e non può bloccare retroattivamente la chiamata.
I test async certificano subito la risposta finale?
No. Il risultato deve essere arrivato e riferirsi alla revisione corretta dei file. Un controllo ancora in esecuzione non è un risultato positivo.
PostToolUse annulla codice non valido?
No. La scrittura è già avvenuta. Può fornire feedback da gestire con una correzione successiva e una nuova verifica.
Perché formatter e test possono interferire?
Handler corrispondenti possono essere eseguiti in parallelo. Se uno riscrive file mentre un altro li verifica, il risultato può riferirsi a uno stato diverso.