CLI non interattiva, JSON e pipeline
L’automazione affidabile non dipende da frasi da interpretare. Dipende da input stabili, schemi, codici di uscita e un percorso di fallimento che impedisce alle fasi successive di agire su risultati incompleti.
Cosa affronti, passo dopo passo
Interattivo e non interattivo
Quando sei davanti al terminale puoi correggere una richiesta al volo. Una pipeline non può alzare la mano e chiederti che cosa intendevi. Per questo il passaggio alla modalità non interattiva non consiste nel togliere la chat: consiste nel rendere esplicito tutto ciò che prima decidevi durante la conversazione.
In una sessione interattiva, l’utente può chiarire una richiesta a metà. In una pipeline, input e condizioni devono essere completi prima dell’avvio. Lo script deve sapere quando terminare, cosa stampare e quale stato restituire.
Usa input piccoli e versionabili: per esempio `git diff main | claude -p "Rivedi questo diff" --output-format json`. Fissa la cartella di lavoro e aggiungi nel wrapper timeout, strumenti consentiti e gestione dell’exit code. In CI, `--bare` evita di caricare configurazioni locali non previste. Non dipendere da conversazioni invisibili o dalla cartella implicita della shell.
Ogni sera vuoi analizzare le modifiche di Task Notes senza dipendere dalla cronologia della chat o dalla cartella in cui capita di trovarsi la shell.
- Fissa il repository con un percorso esplicito e identifica l’intervallo Git da esaminare, per esempio dal commit base a `HEAD`.
- Passa obiettivo e vincoli in un file di istruzioni versionato invece di ricostruirli da messaggi precedenti.
- Definisci timeout, output atteso e codice di uscita per successo, finding e errore tecnico.
- Esegui due volte sullo stesso commit e confronta gli artefatti essenziali prima di affidare il comando a uno scheduler.
Risultato: La review non dipende più da una sessione invisibile. Chiunque abbia lo stesso commit e lo stesso contratto può riprodurre l’esecuzione e capire dove si è fermata.
JSON come contratto, non decorazione
Mettere parentesi graffe attorno a una risposta non la trasforma in un contratto. JSON diventa utile quando sai quali campi esistono, che tipo hanno e che cosa deve accadere se mancano. Altrimenti hai soltanto prosa più scomoda da leggere.
Un output strutturato è utile quando i campi sono definiti e validati. Con `--json-schema`, il risultato conforme allo schema viene restituito nel campo `structured_output`; testo libero annidato senza un contratto sposta soltanto il problema di interpretazione.
Il formato `stream-json` emette gli eventi di protocollo di Claude Code durante l’esecuzione. Il tuo programma deve riconoscere quei tipi reali e può poi trasformarli in eventi applicativi come avanzamento o finding; non deve presumere che lo stream produca nomi personalizzati inventati dal prompt.
La pipeline deve bloccare la fase successiva quando la review trova un errore alto, ma continuare se esistono soltanto note informative.
- Definisci `status` come enum e `findings` come lista di oggetti con `severity`, `file`, `message` ed eventuale `line`.
- Rendi obbligatori `runId` e `schemaVersion`, così puoi attribuire l’output e gestire cambi di formato.
- Valida il JSON prima di leggere i finding; se la validazione fallisce, classifica l’esecuzione come errore tecnico.
- Calcola il gate dai campi validati, non cercando parole come «critico» dentro messaggi liberi.
Risultato: La pipeline distingue contenuto della review ed errore del formato. Una nuova frase nel messaggio non cambia accidentalmente la decisione automatica.
Gate e propagazione del fallimento
Un gate che diventa rosso ma lascia passare il lavoro non è un gate: è una decorazione. La parte difficile di una pipeline non è avviare lint e test, ma propagare il fallimento in modo che nessuna fase successiva possa comportarsi come se tutto fosse andato bene.
Una pipeline affidabile valida l’output prima di usarlo, ferma il percorso quando lint o test falliscono e propaga un codice di uscita non zero. Generare comunque un rapporto di errore non significa continuare con deploy o pubblicazione.
Conserva gli artefatti utili alla diagnosi: log ridotto, fase responsabile e output validato. `claude -p` usa l’exit code per il successo o l’errore tecnico dell’esecuzione; un JSON valido con un finding alto può comunque arrivare con exit code 0. È il wrapper che deve leggere quel risultato e trasformarlo nel codice di uscita deciso per il tuo gate.
- Fissa input, cartella di lavoro e limite temporale della routine.
- Richiedi un output strutturato e validalo contro lo schema.
- Esegui lint e test come gate con codici di uscita significativi.
- Interrompi le fasi dipendenti al primo gate fallito.
- Conserva rapporto, fase responsabile e artefatti utili alla diagnosi.
La review produce JSON valido, ma il linter trova un errore. La pipeline deve salvare la diagnosi e non eseguire il comando che prepara la release.
- Esegui la validazione dello schema e interrompi subito se l’output non rispetta il contratto.
- Lancia il linter catturando output e exit code senza trasformare automaticamente l’errore in successo.
- Se l’exit code è diverso da zero, salva fase, comando, versione e porzione utile del log in un artefatto locale.
- Restituisci un codice non zero dal processo principale e verifica che il passo di release risulti saltato, non fallito dopo l’avvio.
Risultato: Il fallimento resta diagnosticabile e confinato. La pipeline comunica chiaramente che la release non è mai iniziata, invece di lasciare uno stato intermedio ambiguo.
Auto mode e raggio operativo
Saltare conferme può sembrare una piccola ottimizzazione. In realtà sposta il confine dell’autorità: un’interpretazione errata non si ferma più davanti a te. Prima di ridurre i checkpoint, devi rendere più piccoli ambiente, strumenti e conseguenze.
Le modalità di permesso non sono equivalenti: `default` chiede per le azioni sensibili, `acceptEdits` riduce le conferme sulle modifiche, `plan` resta in lettura, `dontAsk` consente soltanto ciò che hai pre-approvato, mentre `auto` usa controlli di sicurezza in background. Disponibilità e comportamento dipendono dalla versione e dal piano.
`bypassPermissions`, equivalente a `--dangerously-skip-permissions`, salta i controlli ed è appropriato soltanto in ambienti isolati. Non disabilitare globalmente le protezioni perché una pipeline è rumorosa: limita cartelle, strumenti, rete e durata e conserva approvazioni separate prima di effetti esterni.
Vuoi eseguire una review notturna di Task Notes senza approvare ogni lettura, ma il computer possiede anche credenziali per il repository remoto.
- Crea una copia di lavoro dedicata e limita la routine a lettura più scrittura del solo rapporto locale.
- Rimuovi dalla sessione token di push e accessi non necessari; disabilita la rete se le fonti sono già locali.
- Imposta timeout, numero massimo di file e stop immediato davanti a comandi fuori dall’elenco previsto.
- Esegui più volte con log attivo; soltanto dopo valuta quali conferme ripetitive possono essere ridotte senza allargare l’autorità.
Risultato: La routine diventa più comoda senza diventare onnipotente. Anche se interpreta male un file, non può pubblicare, cancellare o uscire dalla cartella assegnata.
Pipeline locale di review
Task Notes deve controllare ogni modifica senza pubblicare nulla.
1. Leggi i file modificati
2. Genera {status, findings, tests}
3. Valida lo schema JSON
4. Esegui lint; se fallisce → exit 1
5. Esegui test; se falliscono → exit 1
6. Salva il rapporto locale; nessun deploy