Ogni sessione riparte da una finestra di contesto vuota, e il CLAUDE.md è il canale con cui le fai arrivare quello che altrimenti riscriveresti a ogni avvio. Un dettaglio cambia il modo di progettarlo: quel contenuto «is delivered as a user message after the system prompt, not as part of the system prompt itself». Resta contesto interpretabile, non configurazione applicata — e infatti la stessa pagina, per bloccare un’azione qualunque cosa decida il modello, rimanda a un hook PreToolUse. Il CLAUDE.md indirizza, non impone, e lo paghi in token a ogni richiesta della sessione.
Quattro sedi e un ordine di caricamento
Le posizioni sono quattro, elencate dalla più larga alla più specifica.
Managed policy macOS /Library/Application Support/ClaudeCode/CLAUDE.md
Linux /etc/claude-code/CLAUDE.md
Windows C:\Program Files\ClaudeCode\CLAUDE.md
User ~/.claude/CLAUDE.md
Progetto ./CLAUDE.md oppure ./.claude/CLAUDE.md
Locale ./CLAUDE.local.md (da aggiungere a .gitignore)
Non è una catena di override: «All discovered files are concatenated into context rather than overriding each other». Claude Code carica il file della working directory e di ogni directory superiore, ordinandoli dalla radice del filesystem verso il basso, così le istruzioni più vicine al punto di avvio sono le ultime lette; dentro ogni directory il CLAUDE.local.md viene accodato dopo il CLAUDE.md. Se due file si contraddicono, «Claude may pick one arbitrarily»: la coerenza fra i livelli è un requisito di progetto, non una raffinatezza.
I file nelle sottodirectory si comportano diversamente. Non entrano all’avvio: entrano quando Claude legge un file lì dentro. Il livello managed policy è l’unico che nessuna impostazione individuale può escludere, ed è per questo che ci si mettono le regole di compliance e non lo stile del codice.
Lo scoping segue l’albero delle directory
In un monorepo un unico file di radice fa una di due cose: gonfia fino a coprire ogni sottosistema, pagando contesto su istruzioni estranee al task, oppure resta così generico da essere inutile. La divisione consigliata è a due livelli.
monorepo/
CLAUDE.md # regole valide in ogni pacchetto
packages/api/CLAUDE.md # convenzioni dello stack API
packages/web/CLAUDE.md # convenzioni del frontend
La leva più efficace, però, non è un’impostazione: è da dove lanci la sessione. Partendo dalla radice carichi solo il file di radice, e quelli sottostanti arrivano su richiesta; partendo da packages/api/ carichi quella directory più tutti i suoi antenati, e le convenzioni del frontend non entrano mai. Attenzione a un’asimmetria che si paga cara: i .claude/settings.json non si ereditano dalle directory superiori come i CLAUDE.md, quindi le impostazioni di ogni area devono essere autosufficienti.
Per i pacchetti in cui non lavori mai c’è claudeMdExcludes, che salta i file per path o glob confrontati con i percorsi assoluti, e i cui array si sommano fra i livelli di impostazioni. È una lista statica, non un interruttore per singolo task: per concentrarti su un pacchetto oggi e su un altro domani conviene cambiare directory di avvio, non riscrivere le esclusioni.
Modularità che non sconta il costo
La sintassi @path/to/import espande un altro file dentro il CLAUDE.md. I percorsi relativi si risolvono rispetto al file che contiene l’import, non alla working directory; la ricorsione ha «a maximum depth of four hops»; il parser salta i code span e i blocchi recintati, quindi un percorso scritto fra backtick resta testo letterale. Un import di progetto che punta fuori dalla working directory è considerato esterno e la prima volta apre un dialogo di approvazione: serve a proteggerti dai file che qualcun altro committa in un repo condiviso.
Qui sta l’errore di progettazione più comune. Spezzare un file lungo in import non riduce il contesto: «imported files still load and enter the context window at launch». Migliora l’ordine e la manutenibilità, non il costo. La soglia dichiarata è «under 200 lines per CLAUDE.md file», e un file oltre 4 MiB viene saltato per intero. Se il problema è il costo e non il disordine, il contenuto va spostato in meccanismi che caricano su richiesta, non spalmato su più file che caricano comunque.
Un caso concreto: il CLAUDE.local.md è gitignorato, quindi esiste solo nel worktree in cui l’hai creato. Per portare le preferenze personali su tutti i worktree si importa un file dalla home invece di duplicarlo.
Verificare, non sperare
/memory elenca e apre i file di memoria; /context mostra sotto Memory files quelli davvero caricati nella sessione in corso. È la differenza fra «il file esiste» e «il file è in contesto», ed è il primo controllo quando un’istruzione viene ignorata. /init genera un CLAUDE.md di partenza e, se ne trova già uno, propone miglioramenti invece di sovrascriverlo. Per capire quali file di istruzioni vengono caricati, quando e perché, esiste l’hook InstructionsLoaded.
Un ultimo fatto che va considerato prima di dimensionare i file: dopo una compaction il CLAUDE.md di radice viene ri-iniettato da disco, mentre quelli annidati nelle sottodirectory tornano solo quando Claude rilegge un file di quella directory. Se un’istruzione deve sopravvivere a una sessione lunga, la radice non è una comodità: è il requisito.