Cos'è e perché conta
Il video parlava di Jev: un'AI che non scrive testo, ma risponde con un tipo preciso, cioè una scelta, un punteggio o un vero/falso, con le probabilità e quanto è sicura. Cosa fare con la risposta lo decide il tuo codice. Per ora c'è una lista d'attesa. Qui mi interessa un'idea sola: un controllo che si mette tra l'AI e il comando, prima che il comando parta. Questo il tuo Claude Code può averlo già oggi, senza aspettare nessuna lista.
Il problema è semplice. Claude Code lancia comandi nel terminale del tuo computer. Quasi sempre sono innocui: installa un pacchetto, fa partire i test, legge un file. Ma alcuni non si annullano. rm -rf cancella una cartella con tutto dentro, senza passare dal cestino. git push --force sovrascrive la storia del progetto online. git reset --hard butta via le modifiche che non hai ancora salvato in un commit. Un drop table cancella una tabella del database.
Non serve che Claude sbagli apposta. Basta un'istruzione capita male, un percorso sbagliato, una sessione lunga in cui si è confuso. E se approvi le conferme in fretta, o le hai ridotte per andare più veloce, il momento in cui potevi dire di no passa senza che te ne accorga.
C'è anche una cosa da sapere. Il rewind di Claude Code (Esc due volte, o /rewind) annulla le modifiche fatte con i suoi strumenti per i file, ma non quelle fatte da comandi nel terminale. Se un rm cancella un file, il rewind non te lo riporta indietro.
Quindi il freno va messo prima. Due modi: una lista di comandi vietati, semplice, e un piccolo script che legge ogni comando prima che parta, più furbo. Poi c'è il prompt per farli fare a Claude.
1. La lista dei comandi vietati
Claude Code legge le impostazioni del progetto dal file .claude/settings.json, nella cartella del progetto. Se vuoi le stesse regole in tutti i progetti, usa ~/.claude/settings.json nella tua cartella utente. Dentro scrivi questo:
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)"
]
}
}Un «deny» vince sempre su qualsiasi permesso dato. Claude Code guarda prima le regole deny, poi quelle che chiedono conferma, poi quelle che permettono. Quindi anche se un giorno hai risposto «sì, non chiedermelo più» a un comando, il deny resta più forte. E vale in ogni modalità di permesso, anche in bypassPermissions.
Il limite: la regola blocca il comando scritto così, non le sue varianti. Bash(rm -rf *) ferma rm -rf build/, ma non lo stesso comando dentro bash -c, o scritto come /bin/rm -rf build/. Anche rm -fr, con le lettere invertite, passa. È una rete, non un muro.
2. Il guardiano: un hook che controlla ogni comando
Un hook è uno script che Claude Code lancia da solo in un momento preciso. Quello che ci serve si chiama PreToolUse: parte prima di ogni chiamata a uno strumento, e con il filtro «Bash» guarda solo i comandi del terminale. Riceve il comando in JSON. Se lo script esce con codice 2, il comando non parte e Claude legge il motivo che hai scritto. Se esce con 0, il comando prosegue con i permessi normali.
Il vantaggio rispetto alla lista: lo script cerca le parole pericolose in tutto il testo del comando. Quindi becca anche rm -rf nascosto dentro bash -c.
Crea il file .claude/hooks/guardiano.sh nel progetto e incollaci questo:
#!/bin/bash
command -v jq >/dev/null || { echo "serve jq" >&2; exit 2; }
CMD=$(jq -r '.tool_input.command')
if echo "$CMD" | grep -Eiq 'rm -rf|git push --force|git reset --hard|drop table'; then
echo "Bloccato: comando distruttivo. Chiedimi prima il permesso." >&2
exit 2
fi
exit 0Rendilo eseguibile con chmod +x .claude/hooks/guardiano.sh. Lo script usa jq per leggere il JSON: se non ce l'hai, sul Mac lo installi con brew install jq. Se manca, la prima riga dello script blocca ogni comando invece di lasciarlo passare.
Poi aggiungi in .claude/settings.json, accanto a «permissions», questa parte:
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guardiano.sh" }]
}
]
}$CLAUDE_PROJECT_DIR indica la cartella del progetto, e le virgolette intorno tengono insieme il percorso anche se contiene spazi. Messe insieme, le due parti danno un file così:
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guardiano.sh" }]
}
]
}
}La lista nello script la allunghi tu: metti i comandi che nel tuo progetto fanno danni, per esempio quello che svuota il database o lo script che pubblica l'app.
3. Se non ti va di farlo a mano
Puoi chiedere a Claude di fare tutto: lo script, il file di impostazioni e la prova. Scrivigli:
Configura in .claude/settings.json un hook PreToolUse che blocchi prima che partano i comandi distruttivi (rm -rf, git push --force, git reset --hard, drop table) e aggiungi le stesse regole nella lista deny dei permessi. Poi crea una cartella vuota di prova e verifica che rm -rf su quella venga bloccato.
Quando ha finito, leggi tu il file .claude/settings.json e lo script. Sono poche righe. Se qualcosa non ti torna, fatti spiegare:
Mostrami il contenuto di .claude/settings.json e dello script dell'hook, e spiegami riga per riga cosa blocca e cosa lascia passare.
4. La prova
Una regola che non hai provato è una regola che speri funzioni. Scrivi /hooks in Claude Code: si apre l'elenco degli hook configurati, e il tuo deve comparire sotto PreToolUse. Di solito Claude Code legge subito le modifiche al file di impostazioni. Se il tuo hook non compare, chiudi e riapri Claude Code.
Attenzione a un dettaglio: con il deny attivo, un rm -rf scritto normale lo ferma già la lista. Per vedere se il guardiano funziona da solo, chiedi a Claude lo stesso comando dentro bash -c: la lista non lo vede, il guardiano sì.
Crea una cartella vuota chiamata prova-guardiano e prova a cancellarla con bash -c 'rm -rf prova-guardiano'. Poi dimmi chi ti ha fermato: la lista deny o l'hook.
Se il comando passa, il guardiano non sta lavorando: di solito lo script non è eseguibile o il percorso nel settings.json è sbagliato, e in quei casi Claude Code non riceve il codice 2 e lascia proseguire il comando. Se invece si blocca tutto, anche un semplice ls, e il motivo è «serve jq», manca jq.
5. La rete sotto: git
Il guardiano riduce il rischio, non lo azzera. Le varianti di un comando sono tante e non le prevedi tutte. Per questo la vera rete sotto è git: fai un commit prima di dare a Claude un lavoro lungo, e tieni una copia del progetto anche online, per esempio su GitHub. Se qualcosa va storto, torni all'ultimo commit.
E la modalità bypassPermissions, quella che salta le richieste di conferma, la documentazione di Claude Code la consiglia solo in ambienti isolati, tipo un container o una macchina virtuale. Non sul computer dove tieni tutto.
Gli errori più comuni
- Sovrascrivere il settings.json che c'era già: aggiungi le parti nuove a quello che c'è e controlla le virgole, perché basta una virgola mancante a rompere il file.
- Pensare che il deny copra tutte le varianti: blocca il comando scritto così, quindi affiancagli il guardiano che legge tutto il testo del comando.
- Dimenticare chmod +x: lo script non parte e il guardiano non blocca niente senza dirtelo, quindi fai sempre la prova su una cartella vuota.
- Contare sul rewind per i file cancellati: il rewind non annulla i comandi del terminale, quindi fai un commit prima dei lavori lunghi.
Checklist
- Regole deny in .claude/settings.json
- Script guardiano creato e reso eseguibile
- jq installato
- Hook visibile in /hooks sotto PreToolUse
- Prova su una cartella vuota: comando bloccato
- Commit fatto prima dei lavori lunghi
Domande frequenti
Claude Code non chiede già il permesso prima dei comandi?
Nella modalità Manual sì: chiede prima di ogni comando che non sia di sola lettura. Ma se rispondi «sì, non chiedermelo più», o lavori in una modalità che chiede meno, quella conferma sparisce. Il deny e il guardiano invece restano attivi anche lì.
Meglio la lista deny o l'hook?
Tutti e due. Il deny sono tre righe e non ha bisogno di niente. L'hook legge tutto il testo del comando e becca le varianti più comuni. Uno copre i buchi dell'altro.
Il guardiano può bloccare anche comandi innocui?
Sì: se un comando contiene quelle parole, per esempio una ricerca di testo con dentro «rm -rf», viene fermato. Va bene così: Claude legge il motivo e ti chiede come procedere. Se succede spesso, rendi la lista più precisa.
Vale per tutti i miei progetti?
In .claude/settings.json vale per quel progetto, e se il file è su git vale anche per chi ci lavora con te. In ~/.claude/settings.json vale per tutti i tuoi progetti: in quel caso metti lo script in ~/.claude/hooks e scrivi quel percorso nel comando dell'hook.