Come ho ridotto dell'80% il consumo di token con Claude Code
Strumenti e abitudini per usare Claude Code in modo sostenibile: RTK per filtrare l'output dei comandi, Caveman per comprimere le risposte, CLAUDE.md come contratto di contesto, e /compact per non lasciare che la sessione esploda.
Dopo qualche mese di utilizzo quotidiano di Claude Code su progetti multi-repo, mi sono ritrovato a guardare il breakdown dell’usage API con una certa preoccupazione. I token non crescevano linearmente con la complessità dei task — crescevano con la verbosità delle risposte e con il contesto accumulato nel tempo. Sessioni lunghe, output di comandi bash copiati integralmente nel contesto, risposte elaborate per cose semplici.
Ho iniziato a misurare prima di intervenire. Il breakdown era chiaro: i token di input erano dominati da output di comandi (git diff, test runner, build logs) — grandi blocchi di testo che il modello leggeva per capire lo stato del sistema. I token di output erano dominati da risposte prolisse: spiegazioni, riepilogatori, commenti sul codice che nessuno aveva chiesto.
Queste sono le soluzioni che ho adottato, in ordine di impatto.
RTK: filtrare l’output dei comandi prima che entri nel contesto
Il consumatore di token più silenzioso è l’output dei comandi bash. Un git diff su un refactor può generare 10.000 token. Un test runner che stampa ogni assertion fallita può arrivare a 25.000. Questo testo entra tutto nel contesto — e il modello lo legge, anche se il 90% è ridondante.
RTK (Rust Token Killer) è un proxy CLI che si interpone tra il terminale e il modello. Intercetta l’output dei comandi e lo filtra prima che raggiunga il contesto: rimuove righe duplicate, tronca sezioni ripetitive, aggrega risultati simili.
brew install rtk
rtk init -g # configura il hook globale per Claude Code
Dopo il restart, RTK lavora in trasparenza — non cambia nulla nel workflow, ma riscrive l’output prima che venga consumato. Su una sessione da 30 minuti:
| Comando | Token prima | Token dopo | Riduzione |
|---|---|---|---|
git diff | 10.000 | 2.500 | -75% |
| Test runner | 25.000 | 2.500 | -90% |
| Sessione complessiva | 118.000 | 23.900 | -80% |
È un singolo binario Rust senza dipendenze, con ~10ms di overhead per comando. Supporta oltre 100 comandi: git, npm, cargo, docker, AWS CLI, e i principali test framework.
Caveman: comprimere le risposte del modello
Il secondo grande consumatore è l’output del modello stesso. Per default, Claude risponde con frasi complete, ripete il contesto, aggiunge spiegazioni anche quando non servono. Su task tecnici ripetitivi — refactor, rename, aggiunta di test — il 60-70% delle parole è filler.
Caveman è una skill per Claude Code che comprime le risposte rimuovendo il filler e mantenendo solo la sostanza tecnica. Usa frammenti invece di frasi complete, elimina le ridondanze, risponde con la densità di un commento in codice piuttosto che di una spiegazione a voce.
# Installazione come skill Claude Code
mkdir -p ~/.claude/skills
# clona caveman nella directory skills
Quattro livelli di compressione disponibili tramite /caveman:
- lite — taglia le frasi di raccordo, mantiene la struttura
- full — frammenti, niente frasi complete
- ultra — output denso, quasi mnemonico
- wenyan — stile classico cinese, massima compressione
Un esempio concreto. Risposta senza Caveman:
“Ho analizzato il file e ho notato che la funzione
createUsernon gestisce il caso in cui l’email è già presente nel database. Ho aggiunto un controllo all’inizio della funzione che verifica l’esistenza dell’email e lancia un errore appropriato se trovata. Ho anche aggiornato i test per coprire questo scenario.”
Con Caveman full:
createUser: added email existence check, throws if duplicate. Tests updated.
Da 69 token a 19. La riduzione media sull’output è intorno al 65%.
Caveman ha anche un comando /caveman-compress per comprimere i file di memoria e il CLAUDE.md — riduzione media del 46% su questi file, che vengono caricati come contesto di sistema ad ogni sessione.
CLAUDE.md come contratto di contesto
Ogni sessione con Claude Code inizia da zero. Senza contesto persistente, il modello chiede o inferisce: qual è lo stack? Quali convenzioni? Come si builda? Dove si trovano i file chiave?
Il file CLAUDE.md nella root del progetto viene caricato automaticamente ad ogni sessione. È l’unico posto dove vale la pena investire tempo a scrivere bene — non come documentazione per un umano, ma come contesto denso e strutturato per il modello.
Un CLAUDE.md efficace:
## Commands
| Task | Command |
|------|---------|
| Dev | pnpm dev |
| Build | pnpm build |
| Test | pnpm test |
## Stack
- Astro 6 + React 19 + TypeScript strict
- Tailwind CSS 4, Redux 5
- baseUrl: "src" → import da 'utils/foo' non '../../utils/foo'
## Key files
| File | Purpose |
|------|---------|
| src/App.tsx | OS desktop layout |
| src/reducers/index.ts | RootState |
## Conventions
- No comments unless WHY is non-obvious
- No any, strict mode
- Tailwind first, no inline styles
Questo blocco evita decine di domande per sessione e riduce gli errori da convenzione mancante. Il contesto è scritto una volta, compresso con /caveman-compress, e caricato automaticamente.
Memory system: persistenza inter-sessione
Claude Code supporta un sistema di memoria persistente tramite file .md in .claude/projects/<path>/memory/. Questi file vengono caricati come parte del system prompt nelle sessioni successive.
Tipi utili:
- feedback: cosa funziona, cosa il modello non dovrebbe fare
- project: decisioni prese, motivazioni, deadline
- user: profilo di chi usa il tool (senior dev, stack principale, area di expertise)
Il file MEMORY.md è un indice: una riga per file, caricato sempre. I file singoli vengono caricati quando rilevanti.
Mantenere questi file brevi e compressi con /caveman-compress è importante: ogni byte conta perché viene caricato come prefisso di sistema ad ogni chiamata.
/compact e /clear: gestire il ciclo di vita della sessione
Una sessione lunga accumula contesto: messaggi, output, iterazioni. Dopo un’ora di lavoro su un problema complesso, il contesto può contenere tentativi falliti, output intermedi, e ragionamenti che non servono più.
/compact riassume la conversazione corrente in un sommario denso e ricomincia da lì. Va usato proattivamente — non aspettare che il contesto si avvicini al limite, perché a quel punto il modello inizia a perdere dettagli importanti. Una buona euristica: usarlo dopo ogni sotto-task completato, o ogni 20-30 messaggi.
/clear azzera tutto. Utile quando si cambia task in modo netto — ad esempio dopo aver finito un refactor e voler iniziare a lavorare su una feature completamente diversa. Portare il contesto del refactor nella sessione della feature è rumore puro.
La sequenza tipica:
[inizio sessione] → task A → /compact → task B → /compact → task C → /clear
[nuova sessione] → task D
Questo evita la degradazione progressiva della qualità delle risposte che avviene quando il contesto è saturo di informazioni obsolete.
Il risultato complessivo
Mettendo insieme tutti i layer:
| Intervento | Token risparmiati |
|---|---|
| RTK (output comandi) | -75–90% sui comandi |
| Caveman (output modello) | ~-65% sull’output |
| CLAUDE.md + memory compressi | -40–50% sul system prompt |
/compact proattivo | evita re-lettura di contesto stale |
Non è una riduzione additiva — i layer si combinano. La stima conservativa su una sessione di lavoro tipica è una riduzione complessiva tra il 70% e l’80% rispetto a una sessione non ottimizzata.
Il punto non è solo il costo. Meno token in contesto significa anche risposte più precise: il modello non deve filtrare il rumore per trovare il segnale rilevante.