18 · Boilerplate agentici riusabili
Prima di tutto, la parola del titolo. Un boilerplate è un progetto
modello: una cartella già pronta con struttura, configurazione e convenzioni, che copi ogni volta che
inizi un progetto nuovo — come un modulo prestampato, dove i campi da riempire sono pochi e tutto il
resto è già scritto giusto. (Attenzione: nel modulo 14 hai incontrato
la stessa parola nell’altro suo senso, “codice ripetitivo da scrivere per forza”. Qui è il primo:
template di progetto.) Un boilerplate agentico è un progetto modello in cui la parte già pronta
non è tanto il codice, quanto tutto ciò che questo corso ti ha insegnato a configurare: CLAUDE.md,
hook, comandi, permessi, subagent.
Obiettivi
Sezione intitolata “Obiettivi”- Sapere cosa mettere in un boilerplate agentico, file per file, e perché.
- Scaricare e usare i tre boilerplate di questo corso.
- Scrivere uno script di init che personalizza il template in un comando.
- Distinguere cosa parametrizzare da cosa tenere fisso.
- Mantenere un boilerplate nel tempo e propagare gli aggiornamenti ai progetti derivati.
Concetti chiave
Sezione intitolata “Concetti chiave”Il valore di un boilerplate agentico non è il codice: è la configurazione. Uno scaffold di framework
te lo dà npm create. Quello che non ti dà è il CLAUDE.md che spiega le convenzioni, gli hook che
impediscono gli errori, i comandi che incapsulano i tuoi workflow, i permessi già decisi. È quella parte
che riscrivi ogni volta, ed è quella che vale la pena mettere in un template.
Il tempo che risparmi è quello delle prime tre ore, moltiplicato per ogni progetto. Non è il tempo di
scrivere npm init: è il tempo che passi a ripetere a Claude le stesse convenzioni, a scoprire di nuovo
che ha modificato una migrazione già applicata, a riscrivere il comando che apre le PR nel formato del
tuo team.
Un boilerplate che nessuno mantiene diventa un ostacolo. Un template con dipendenze di un anno fa e convenzioni superate fa perdere più tempo di quanto ne faccia risparmiare. Il capitolo sulla manutenzione non è opzionale.
Parametrizza poco. Ogni segnaposto è una cosa che può restare non sostituita. Il nome del progetto e la descrizione bastano quasi sempre: tutto il resto o è uguale in ogni progetto, o va deciso a mano.
Anatomia di un boilerplate
Sezione intitolata “Anatomia di un boilerplate”Directoryil-tuo-boilerplate/
- CLAUDE.md Convenzioni e regole — il cuore del template
- README.md Per gli umani: cosa contiene, cosa personalizzare, cosa non toccare
- init.sh Personalizza i segnaposto e si auto-rimuove
- PLAN.md Il piano corrente, scritto in Plan Mode
- STATE.md Stato di avanzamento, per riprendere dopo un’interruzione
- .gitignore Include
.claude/settings.local.jsoneCLAUDE.local.md - .env.example Ogni variabile documentata,
.envmai committato - .mcp.json Server MCP condivisi, con variabili al posto dei segreti
Directory.claude/
- settings.json Permessi (allow e deny) e registrazione degli hook
Directorycommands/ I workflow che invochi con
/nome- …
Directoryskills/ Le convenzioni che si caricano su richiesta
- …
Directoryagents/ I subagent: chi esplora, chi implementa, chi rivede
- …
Directoryhooks/ Gli script: la rete di sicurezza
- …
Cosa va in ciascun file
Sezione intitolata “Cosa va in ciascun file”CLAUDE.md — il pezzo che conta di più. Cinque sezioni, in quest’ordine:
- Comandi che Claude non può indovinare, con l’indicazione di quali sono obbligatori.
- Struttura, in una tabella “se stai scrivendo… → va in…”.
- Regole non negoziabili: poche, concrete, verificabili.
- Cosa NON fare senza discuterne — la sezione che evita che un agente introduca una coda di messaggi perché gli hai chiesto di “rendere più robusto” qualcosa.
- Trappole specifiche del progetto: quello che scopriresti solo sbagliando.
Sotto le 200 righe. Le regole settoriali vanno in .claude/rules/ con paths:.
.claude/settings.json — la deny list è più importante della allow. Un boilerplate serio nega la
lettura dei file di ambiente e l’esecuzione dei comandi che toccano la produzione.
.claude/hooks/ — è quello che distingue un boilerplate da una cartella di appunti. Le istruzioni nel
CLAUDE.md sono consigli; gli hook sono codice. Due categorie:
| Tipo | Evento | Esempio |
|---|---|---|
| Difensivi | PreToolUse |
Blocca modifiche a migrazioni applicate, .env, lockfile |
| Correttivi | PostToolUse |
Lint, format e typecheck dopo ogni modifica, con gli errori che tornano a Claude |
PLAN.md e STATE.md — la coppia che rende una sessione interrompibile. PLAN.md contiene il piano
corrente, scritto in Plan Mode e corretto da te; STATE.md la checklist di avanzamento. Quando una
sessione si interrompe, la ripresa parte da STATE.md invece che da zero.
I tre boilerplate
Sezione intitolata “I tre boilerplate”Coerenti con i tre esempi del modulo 17. Sono cartelle vere,
provate: gli script passano shellcheck (il linter degli script di shell:
segnala gli errori tipici di bash prima che ti mordano), i test di agentic-rag girano davvero, e ogni zip è stato
estratto e inizializzato per verificare che funzioni.
A · web-fullstack
Sezione intitolata “A · web-fullstack”| Componente | Cosa contiene |
|---|---|
CLAUDE.md |
Convenzioni Next.js/Supabase, con la regola ogni tabella ha una policy RLS |
.mcp.json |
Server MCP Supabase e Vercel, con il token da variabile d’ambiente |
.claude/hooks/protect.sh |
Blocca modifiche a migrazioni applicate, .env e lockfile |
.claude/hooks/lint-and-typecheck.sh |
Formatta con Prettier, poi ESLint e tsc: gli errori tornano a Claude |
.claude/commands/review.md |
/review — solo correttezza e sicurezza, con scenario di fallimento obbligatorio |
.claude/commands/ship.md |
/ship — verifica, commit, push, PR nel formato del team |
.claude/skills/frontend/ |
Server vs client component, la forma delle Server Action |
.claude/agents/reviewer.md |
Sola lettura, Opus, memory: project |
Il pezzo che vale la pena copiare anche se non usi questo stack è /ship: incapsula la sequenza
verifica → commit → push → PR fermandosi al primo passo che fallisce, e senza correggere di sua
iniziativa. Eccolo per intero (la sintassi — frontmatter, !`comando`, $ARGUMENTS — è quella
del modulo 7):
Il comando /ship completo
---description: Prepara la modifica corrente per il rilascio: verifica, commit, push e apertura della PR.argument-hint: "[descrizione della modifica]"disable-model-invocation: trueallowed-tools: Bash(git *), Bash(npm run typecheck), Bash(npm run lint*), Bash(npm test*), Bash(gh pr *)---
## Stato corrente
!`git status --short`
## Commit sul branch
!`git log --oneline origin/main..HEAD`
## Istruzioni
Porta questa modifica fino alla pull request, **fermandoti al primo passo che fallisce**.
1. **Verifica.** Nell'ordine: `npm run typecheck`, `npm run lint`, `npm test`. Se uno fallisce, **fermati e riporta l'errore**. Non correggere di tua iniziativa: la correzione è una decisione dell'utente.
2. **Branch.** Se sei su `main`, crea un branch prima di committare. Nome: `tipo/descrizione-breve`, per esempio `feat/billing-webhook`.
3. **Commit.** Conventional commit, in inglese, minuscolo dopo il prefisso. Il corpo spiega **perché**, non cosa: il cosa si legge dalla diff.
4. **Push** con `-u` se il branch è nuovo.
5. **Pull request** con `gh pr create`. Corpo in italiano, con esattamente queste sezioni:
### Cosa cambia Due o tre bullet, dal punto di vista di chi usa il prodotto.
### Perché Una frase. Se c'è una issue collegata, linkala.
### Come verificarlo Passi concreti che il revisore può eseguire.
### Rischi Cosa può rompersi. Se niente, scrivi "nessuno noto" e spiega perché.
6. **Riporta l'URL della PR.**
Contesto aggiuntivo dall'utente: $ARGUMENTSI due !`comando` in cima iniettano nel prompt lo stato reale del repository al momento
dell’invocazione; le istruzioni sono numerate perché l’ordine è il contratto — e la riga in
grassetto del punto 1 è il motivo per cui questo comando è affidabile: un /ship che “corregge e
riprova” da solo finirebbe per committare correzioni che non hai mai visto.
B · headless-pipeline
Sezione intitolata “B · headless-pipeline”| Componente | Cosa contiene |
|---|---|
bin/run.sh |
Orchestratore con flock, log per data, stadi che si fermano al primo errore |
bin/01…04 |
Quattro stadi. Solo 02 chiama Claude |
schemas/analisi.json |
Il contratto dell’output, usato con --json-schema |
.claude/skills/analizza/ |
Il prompt, versionato invece che inline negli script |
.claude/hooks/shellcheck.sh |
shellcheck dopo ogni modifica agli script |
.claude/hooks/stato.sh |
SessionStart: inietta ultimo raw, ultimo output, ultima riga di log |
crontab.example · .github-workflow.example.yml |
Le due strade per programmarla |
Due dettagli nati da bug veri, trovati provando la pipeline:
- Scrittura su temporaneo e poi
mv. Una redirezione diretta lascia un file vuoto sejqfallisce, e il run del giorno dopo lo scambia per dati già raccolti. - Exit code distinti:
1= la pipeline ha fallito,2= lo strumento non ha funzionato. Il monitoraggio deve poterli distinguere per svegliare la persona giusta.
C · agentic-rag
Sezione intitolata “C · agentic-rag”| Componente | Cosa contiene |
|---|---|
src/domain/ |
Modelli, tre porte come Protocol, due casi d’uso. Zero import esterni |
tests/domain/test_no_external_imports.py |
La regola architetturale come test eseguibile |
tests/adapters/ |
Test di contratto: ogni adattatore della stessa porta supera gli stessi test |
.claude/hooks/confine-dominio.sh |
Blocca gli import vietati prima che vengano scritti |
.claude/agents/ |
researcher (sola lettura), coder, reviewer (Opus, memoria) |
.mcp.json |
Filesystem e database in sola lettura |
Il pezzo trasferibile è la coppia hook + test sulla stessa regola: l’hook la difende prima, il test la verifica dopo. Una regola architetturale che vive solo nella documentazione non sopravvive a tre mesi di lavoro con un agente.
Riuso pratico
Sezione intitolata “Riuso pratico”Lo script di init
Sezione intitolata “Lo script di init”Tutti e tre i boilerplate hanno lo stesso init.sh. Fa quattro cose e poi si toglie di mezzo:
#!/usr/bin/env bashset -euo pipefail # fermati al primo errore, su variabili non definite, e negli errori dentro le pipe
# $1 e $2 sono il primo e secondo argomento; ${1:-} = "il primo argomento,# o stringa vuota se manca" (senza :-, con set -u lo script morirebbe qui)NOME="${1:-}"DESCR="${2:-}"
if [ -z "$NOME" ]; then # -z = "è vuoto?" echo "Uso: ./init.sh <nome-progetto> [descrizione]" >&2 # >&2 = sul canale degli errori exit 1fi[ -z "$DESCR" ] && DESCR="$NOME" # senza descrizione, usa il nome
# Trova tutti i file che contengono i segnaposto.# grep -rl = cerca ricorsivamente (-r) e stampa solo i nomi dei file (-l)# < <(...) = "process substitution": dà l'output del grep in pasto a mapfile# mapfile -t FILE = carica quelle righe nell'array FILE, una per elementomapfile -t FILE < <(grep -rl '{{PROJECT_NAME}}\|{{PROJECT_DESCRIPTION}}' . \ --exclude-dir=node_modules --exclude-dir=.git 2>/dev/null || true)
for f in "${FILE[@]}"; do # sed sostituisce i segnaposto dentro il file, sul posto. # -i.bak = modifica il file, tenendo una copia .bak (serve perché il sed di # macOS rifiuta -i senza suffisso; la copia si cancella subito dopo) # s|A|B|g = sostituisci A con B, ovunque nella riga (g = global) sed -i.bak \ -e "s|{{PROJECT_NAME}}|$NOME|g" \ -e "s|{{PROJECT_DESCRIPTION}}|$DESCR|g" "$f" rm -f "$f.bak" echo " aggiornato $f"done
# Data di oggi in STATE.md ($(date +%F) = 2026-08-17)sed -i.bak "s|^Ultimo aggiornamento: —|Ultimo aggiornamento: $(date +%F)|" STATE.md && rm -f STATE.md.bak
# Se la cartella non è già un repository git, inizializzalo (-q = senza output)[ -d .git ] || { git init -q; echo " git init"; }
echo "✔ Progetto '$NOME' inizializzato."rm -- "$0" # lo script cancella SÉ STESSO: $0 è il suo percorso, -- protegge dai nomi che iniziano per -Le due righe che fanno la differenza sono l’ultima e il grep -rl: lo script si auto-rimuove, così non
resta nel repository a confondere chi arriva dopo; e cerca i segnaposto invece di avere una lista di file
hardcoded, così aggiungere un file al template non richiede di ricordarsi di aggiornare l’init.
Cosa parametrizzare e cosa no
Sezione intitolata “Cosa parametrizzare e cosa no”| Parametrizza | Tieni fisso |
|---|---|
| Nome e descrizione del progetto | La struttura delle cartelle |
La data in STATE.md |
Gli hook |
| — | Il formato di PLAN.md e STATE.md |
| — | I comandi /review e /ship |
| — | Le regole non negoziabili del CLAUDE.md |
Tutto ciò che è vagamente specifico del progetto — nomi di tabelle, endpoint, provider — non va
parametrizzato: va lasciato come esempio realistico da modificare. Un template pieno di {{TABLE_NAME}}
è illeggibile e produce progetti in cui metà dei segnaposto sono rimasti.
Come si usa
Sezione intitolata “Come si usa”Da zip — oppure scaricalo cliccando la card qui sopra:
# se leggi il corso da un altro indirizzo, usa quello al posto del dominiocurl -O https://claude-tutorial.giuseppebosi.com/downloads/web-fullstack.zipunzip web-fullstack.zip && cd web-fullstack./init.sh "fatture-app" "Gestione fatture per studi professionali"Da template repo GitHub, se hai messo il tuo su GitHub e l’hai marcato come template:
gh repo create fatture-app --template tuo-utente/boilerplate-web --private --clonecd fatture-app && ./init.sh "fatture-app" "Gestione fatture"Da degit, se vuoi la cartella senza la storia git:
npx degit tuo-utente/boilerplate-web fatture-appcd fatture-app && ./init.sh "fatture-app" "Gestione fatture"Da zip — oppure scaricalo cliccando la card qui sopra:
# se leggi il corso da un altro indirizzo, usa quello al posto del dominioInvoke-WebRequest -Uri "https://claude-tutorial.giuseppebosi.com/downloads/web-fullstack.zip" -OutFile web-fullstack.zipExpand-Archive web-fullstack.zip -DestinationPath .cd web-fullstackbash ./init.sh "fatture-app" "Gestione fatture per studi professionali"Da template repo GitHub:
gh repo create fatture-app --template tuo-utente/boilerplate-web --private --clonecd fatture-app; bash ./init.sh "fatture-app" "Gestione fatture"init.sh è uno script bash: serve Git Bash o WSL. Se preferisci PowerShell nativo, riscrivilo — ma
ricordati di mantenere l’auto-rimozione finale.
Manutenzione
Sezione intitolata “Manutenzione”È la parte che decide se il boilerplate sarà ancora utile fra un anno.
Versionamento
Sezione intitolata “Versionamento”Metti il boilerplate in un repository git e tagga — un tag è un’etichetta fissata su un commit
preciso, il modo di git per dire “questa è la versione 1.2.0”. I numeri seguono il semver
(semantic versioning), la convenzione MAGGIORE.MINORE.PATCH: alzi il primo numero quando il
cambiamento rompe la compatibilità con i progetti derivati, il secondo quando aggiungi qualcosa, il
terzo quando correggi. Un progetto derivato deve poter dire da quale versione è partito:
git tag -a v1.2.0 -m "hook di typecheck, comando /ship"git push --tagsE registralo nel progetto derivato, in una riga del README.md:
Generato da [boilerplate-web](https://github.com/tuo-utente/boilerplate-web) v1.2.0Senza questa riga, fra sei mesi non saprai quali aggiornamenti ti riguardano.
Changelog
Sezione intitolata “Changelog”Il changelog è il diario delle versioni: cosa è cambiato, versione per versione. La convenzione più diffusa (Keep a Changelog) raggruppa le voci in Aggiunto / Modificato / Corretto — ed è quella usata qui sotto. Per un boilerplate serve però una cosa in più che i changelog normali non hanno: per ogni voce, serve un’azione sui progetti già derivati?
# Changelog
## v1.2.0 — 2026-08-16
### Aggiunto- Hook `PostToolUse` che lancia `tsc --noEmit` dopo le modifiche TypeScript → **Propagare**: copia `.claude/hooks/lint-and-typecheck.sh` e la voce in `settings.json`
### Modificato- `/ship` ora si ferma al primo passo di verifica che fallisce, invece di correggere → **Propagare** se usi `/ship`: sostituisci `.claude/commands/ship.md`
### Corretto- `protect.sh` non bloccava i file `.env.production` → **Propagare subito**: è una falla
### Solo per i progetti nuovi- Bump di Next.js a 16.3 → Non propagare a un progetto in corso senza una ragionePropagare gli aggiornamenti
Sezione intitolata “Propagare gli aggiornamenti”Tre strategie, in ordine di sforzo:
-
A mano, dal changelog. Per un template usato su pochi progetti è la strada giusta: leggi le voci marcate Propagare, copia i file, verifica. Sembra primitivo ed è il metodo con meno sorprese.
-
Con un comando dedicato. Aggiungi al boilerplate un
/aggiorna-boilerplateche fa il lavoro:.claude/commands/aggiorna-boilerplate.md ---description: Confronta questo progetto con l'ultima versione del boilerplate e propone gli aggiornamenti da applicare.disable-model-invocation: trueallowed-tools: Bash(git *), Bash(curl *), Read, Grep, Glob---## Versione di partenza di questo progetto!`grep -o 'boilerplate-web) v[0-9.]*' README.md || echo "non registrata"`## Changelog del boilerplate!`curl -sf https://raw.githubusercontent.com/tuo-utente/boilerplate-web/main/CHANGELOG.md`## Istruzioni1. Individua la versione da cui parte questo progetto2. Elenca **solo** le voci successive marcate "Propagare"3. Per ciascuna, confronta il file corrispondente in questo progetto con quellodel boilerplate e dimmi cosa cambierebbe4. **Non applicare niente.** Presenta un piano e fermati: le personalizzazionilocali sono legittime e solo io so quali vanno tenuteL’ultima riga è quella importante: un aggiornamento automatico che sovrascrive le personalizzazioni fa più danni di un boilerplate vecchio.
-
Con un remote git. Se il progetto è nato da un clone, puoi tenere il boilerplate come remote aggiuntivo e fare merge selettivi:
Terminal window # registra il repo del boilerplate come secondo "remote" e scaricane lo statogit remote add boilerplate https://github.com/tuo-utente/boilerplate-web.gitgit fetch boilerplate# guarda le differenze nella cartella .claude/ prima di toccare qualcosagit diff HEAD boilerplate/main -- .claude/# prendi UN file dalla versione del boilerplategit checkout boilerplate/main -- .claude/hooks/lint-and-typecheck.shAttenzione all’ultimo comando:
git checkout <ref> -- <file>sovrascrive la tua copia del file senza chiedere niente — le modifiche locali non committate a quel file spariscono. Per questo ilgit diffviene prima: guarda, poi sovrascrivi.Funziona bene per
.claude/, che raramente diverge, e male per il codice, che diverge sempre.
Quando potare
Sezione intitolata “Quando potare”Un boilerplate cresce. Ogni sei mesi, tre domande su ogni componente:
- L’ho usato? Un comando che non invochi da tre progetti va tolto.
- Costa contesto? Skill e server MCP si pagano a ogni sessione.
/contextin un progetto derivato dice quanto. - La regola è ancora vera? Una regola nel
CLAUDE.mdche descrive una convenzione abbandonata è peggio di nessuna regola: manda Claude nella direzione sbagliata con sicurezza.
Esempio guidato
Sezione intitolata “Esempio guidato”-
Scarica e apri il boilerplate più vicino al tuo lavoro — dalla card di inizio pagina, o:
Terminal window # stesso dominio da cui stai leggendo il corsocurl -O https://claude-tutorial.giuseppebosi.com/downloads/agentic-rag.zipunzip agentic-rag.zip && cd agentic-rag -
Leggi il
README.mdprima di tutto. Ha due sezioni che valgono più del codice: Da personalizzare e Da lasciare com’è. -
Inizializza.
Terminal window ./init.sh "kb-interna" "Base di conoscenza interna sui runbook" -
Verifica che parta.
uvè il gestore di pacchetti Python usato dal boilerplate (l’equivalente dinpmper Python, molto veloce — istruzioni di installazione):uv syncinstalla le dipendenze,uv run pytestlancia i test nell’ambiente giusto.Terminal window uv syncuv run pytestOutput atteso:
7 passedSette test che passano prima di aver scritto una riga: sono i test del dominio e quelli di contratto.
-
Prova l’hook difensivo. Apri
claudee chiedi qualcosa che viola la regola architetturale:In src/domain/usecases/answer_question.py, call the Anthropic API directly with httpxL’hook blocca la scrittura e restituisce la ragione. Claude legge “definisci un Protocol in domain/ports.py, implementalo in adapters/” e di norma corregge da solo. È la differenza tra una regola scritta e una regola applicata.
-
Costruisci il tuo. Parti da uno di questi e sostituisci ciò che è specifico:
Terminal window cp -r agentic-rag ~/boilerplate-mio && cd ~/boilerplate-miogit init && git add -A && git commit -m "chore: fork dal boilerplate agentic-rag del corso"git tag -a v1.0.0 -m "prima versione"Poi metti sul repository GitHub e marcalo come template: Settings → Template repository.
Esercizio finale
Sezione intitolata “Esercizio finale”Costruisci il tuo boilerplate e avviaci due progetti, misurando quanto risparmi.
- Parti da uno dei tre e adattalo al tuo stack e alle tue convenzioni.
- Misura il tempo per avviare il primo progetto senza boilerplate.
- Misura il tempo per avviare il secondo con il boilerplate.
- Confronta, e sistema il boilerplate in base a cosa è mancato.
Soluzione
Passo 1 — cosa cambiare davvero.
La tentazione è cambiare tutto. In pratica, su un boilerplate di questo corso, quello che è tuo si conta sulle dita:
| Cosa | Quanto è tuo |
|---|---|
CLAUDE.md → sezioni Regole e Trappole |
Interamente tuo |
.claude/commands/ship.md → formato della PR |
Tuo: è la convenzione del tuo team |
.claude/settings.json → la deny list |
Tuo: dipende da cosa non deve toccare |
.mcp.json |
Tuo: i tuoi servizi |
| Gli hook | Quasi sempre riusabili così come sono |
PLAN.md / STATE.md |
Riusabili |
| La struttura delle cartelle | Riusabile, se lo stack è lo stesso |
Passi 2–3 — misurare in modo onesto.
Cronometra la stessa cosa nei due casi: dal primo comando al primo commit di una feature reale che
funziona. Non “fino a npm run dev” — quello è veloce comunque, e non è dove si perde tempo.
Tieni un log grezzo:
## Progetto 1 — senza boilerplate
| Attività | Minuti || --- | --- || Scaffold e dipendenze | 12 || Configurare lint, format, typecheck | 25 || Scrivere il CLAUDE.md | 40 || Scoprire e correggere: Claude ha modificato una migrazione applicata | 20 || Riscrivere a Claude la convenzione delle PR, tre volte | 15 || Prima feature | 55 || **Totale** | **167** |
## Progetto 2 — con boilerplate
| Attività | Minuti || --- | --- || `init.sh` + `npm install` | 4 || Adattare CLAUDE.md al dominio specifico | 12 || Prima feature | 40 || **Totale** | **56** |Passo 4 — la parte che conta.
Il numero non è il risultato dell’esercizio. Il risultato è la lista di cosa è mancato nel secondo progetto, che diventa la v1.1 del boilerplate.
Da un giro reale, il tipo di cose che emergono:
| Cosa è mancato | Cosa aggiungere |
|---|---|
| «Ho rispiegato tre volte come si chiamano i branch» | Una riga in Etichetta del repository nel CLAUDE.md |
| «Claude ha creato un file di documentazione che non volevo» | “Non creare file di documentazione se non richiesti” nelle regole |
| «Ho dovuto configurare a mano i permessi per il test runner» | La voce in permissions.allow |
«Il comando /ship assumeva main, qui il branch base è develop» |
Parametrizzarlo, o leggerlo da git |
«Nessuno ha aggiornato STATE.md» |
Ricordarlo nel CLAUDE.md, o un hook Stop che lo verifica |
Nota la penultima riga: è un caso in cui la parametrizzazione serve davvero, e si scopre solo usando il template su un secondo progetto. È esattamente il motivo per cui l’esercizio chiede due progetti e non uno.
Chiudi il ciclo:
cd ~/boilerplate-mio# applica le correzionigit commit -am "feat: convenzioni branch, permessi test runner, /ship legge il branch base da git"git tag -a v1.1.0 -m "correzioni dal secondo progetto"git push --tagsE aggiorna il CHANGELOG.md marcando quali voci vanno propagate ai due progetti già avviati.
Errori comuni e troubleshooting
Sezione intitolata “Errori comuni e troubleshooting”| Sintomo | Causa | Soluzione |
|---|---|---|
Restano segnaposto {{...}} nel progetto nuovo |
init.sh non ha coperto quel file |
Cerca i segnaposto invece di elencare i file: grep -rl '{{PROJECT_' |
init.sh è ancora nel repository dopo settimane |
Non si auto-rimuove | Ultima riga: rm -- "$0" |
| Gli hook non partono nel progetto nuovo | Il bit di esecuzione si perde in alcuni trasferimenti | chmod +x .claude/hooks/*.sh, e verificalo estraendo lo zip |
| Un hook funziona per te e non per i colleghi | Percorso assoluto della tua macchina | ${CLAUDE_PROJECT_DIR} |
| Un hook legge stdin vuoto | Due jq in pipeline sullo stesso stdin: il primo lo consuma |
Leggi stdin una volta in una variabile |
| Il boilerplate è enorme e nessuno lo usa | Contiene tutto quello che poteva servire | Pota: se non l’hai usato in tre progetti, non serve |
| I progetti derivati divergono e non si aggiornano più | Nessuna versione registrata | Tagga il boilerplate e registra la versione nel README.md del derivato |
| Un aggiornamento automatico ha sovrascritto le personalizzazioni | Il comando applicava invece di proporre | Un comando di aggiornamento deve fermarsi al piano |
I file dentro .claude/ non finiscono nello zip |
Molti tool di archiviazione saltano i file nascosti | Verifica sempre con unzip -l che i dotfile ci siano |
Il CLAUDE.md del boilerplate è cresciuto oltre le 200 righe |
Ci hai messo anche le regole settoriali | Spostale in .claude/rules/ con paths: |
| Nei test finiscono file di cache nello zip | __pycache__, .pytest_cache, node_modules |
Escludili nello script di packaging |
Cheat-sheet
Sezione intitolata “Cheat-sheet”L’anatomia minima
CLAUDE.md convenzioni · struttura · regole · cosa NON fare · trappoleREADME.md cosa personalizzare / cosa lasciare com'èinit.sh sostituisce i segnaposto e si auto-rimuovePLAN.md STATE.md piano corrente e avanzamento.gitignore include settings.local.json e CLAUDE.local.md.env.example ogni variabile documentata.mcp.json server MCP, segreti da variabili.claude/ settings.json permessi (allow E deny) + registrazione hook commands/ i tuoi workflow, invocabili con /nome skills/ convenzioni caricate su richiesta agents/ researcher · coder · reviewer hooks/ difensivi (PreToolUse) e correttivi (PostToolUse)Parametrizza / tieni fisso
Parametrizza: nome del progetto, descrizione, dataTieni fisso: struttura, hook, formato di PLAN/STATE, comandi, regoleNon toccare: esempi realistici — meglio da modificare che da riempireManutenzione
| Cosa | Come |
|---|---|
| Versionare | git tag -a v1.2.0, e registra la versione nel README.md del derivato |
| Changelog | Con una colonna serve propagare? |
| Propagare | A mano dal changelog · un comando che propone · git remote per .claude/ |
| Potare | Ogni sei mesi: l’ho usato? costa contesto? la regola è ancora vera? |
Le tre righe che rendono un boilerplate utile invece che decorativo
1. Un hook che blocca, con permissionDecisionReason che dice cosa fare invece2. Una regola architetturale scritta come test eseguibile3. Una sezione "Cosa NON fare senza discuterne" nel CLAUDE.mdDocumentazione ufficiale consultata, verificata il 16 agosto 2026:
- Explore the .claude directory — cosa mettere in
.claude/e cosa si committa - Best practices —
CLAUDE.mdefficace, hook, skill, subagent - Hooks reference — eventi,
permissionDecisionReason,${CLAUDE_PROJECT_DIR} - Extend Claude with skills — struttura di
SKILL.mde frontmatter - Subagents — definizione degli agenti e memoria persistente
- Settings — permessi, scope e precedenza
- Connect Claude Code to tools via MCP —
.mcp.jsoned espansione delle variabili - Run Claude Code programmatically —
--bare,--json-schemae--max-turnsusati dalla pipeline
I tre boilerplate sono stati provati end-to-end il 16 agosto 2026: shellcheck pulito su tutti gli script,
7 test verdi in agentic-rag, e ogni zip estratto e inizializzato con init.sh per verificare che non
restino segnaposto.
Corso indipendente, non affiliato ad Anthropic o Google. Claude e Claude Code sono marchi di Anthropic; Antigravity e Gemini sono marchi di Google.