Qualche settimana fa, ho fatto reverse engineering di Cursor puntandoci un proxy e catturando ogni chiamata API. Ci e’ voluto un po’ di lavoro. Stavolta, Anthropic ha fatto il lavoro sporco per me.
Il 31 marzo 2026, lo sviluppatore Chaofan Shou ha notato qualcosa di strano nel pacchetto npm di Claude Code v2.1.88: un file .map da 57 MB. Una source map. Il tipo di file che mappa il codice minificato al sorgente TypeScript originale. Il tipo di file che non dovrebbe mai finire in produzione.
Anthropic ha rimosso la versione entro tre ore, ma a quel punto il codice era gia’ stato copiato su almeno tre repository GitHub. 512.000 righe di TypeScript. Ogni file interno, ogni commento, ogni feature flag. Ho passato gli ultimi due giorni a leggerlo. Ecco cosa ho trovato.
Non e’ un wrapper sottile
Se pensavate che Claude Code fosse uno script shell che chiama un’API, vi sbagliavate. E’ un’applicazione completa con una UI React nel terminale (tramite React Ink), pacchettizzata con Bun, interamente in TypeScript. La directory src/ ha circa 55 sottodirectory. Il punto di ingresso main.tsx pesa da solo 800 KB.
L’architettura e’ modulare e ben organizzata:
- tools/ contiene circa 40 tool (Bash, Read, Edit, Grep, Glob, Write, Agent, ecc.), ciascuno nella propria directory con schema JSON, validazione e logica dei permessi
- commands/ ha 100+ comandi slash, inclusi quelli nascosti
- components/ contiene 146 componenti React per l’interfaccia terminale
- hooks/ contiene 87 React hooks
- services/ gestisce chiamate API, OAuth, integrazione MCP, analytics e rate limiting
- coordinator/ gestisce l’orchestrazione multi-agente
- buddy/ e’ un… Tamagotchi. Ci arriviamo.
Un dettaglio che colpisce: i feature flag a build-time di Bun. La funzione feature('BUDDY') viene risolta in fase di compilazione, non a runtime. Se il flag e’ disattivato, l’intero ramo di codice viene eliminato tramite dead code elimination. Nessun overhead a runtime, nessun path nascosto nel binario.
Un Tamagotchi nel terminale
La feature che ha fatto il giro di internet. Dietro il flag BUDDY, Claude Code contiene un sistema completo di companion virtuali: 18 specie di animali ASCII, 5 livelli di rarita’, generazione procedurale e personalita’ generate dall’AI.
Le specie includono papera, gatto, drago, fantasma, axolotl, robot, fungo, capybara e altri. Ogni sprite ha 3 frame di animazione a 500ms. Il sistema di rarita’ e’ quello che vi aspettereste da un gacha:
| Rarita’ | Probabilita’ | Stat Minime | Cappello |
|---|---|---|---|
| Common | 60% | 5 | No |
| Uncommon | 25% | 15 | Random |
| Rare | 10% | 25 | Random |
| Epic | 4% | 35 | Random |
| Legendary | 1% | 50 | Random |
Ogni companion ha 5 statistiche: DEBUGGING, PATIENCE, CHAOS, WISDOM, SNARK. I cappelli disponibili: crown, tophat, propeller, halo, wizard, beanie, e tinyduck (una paperina sulla testa del companion). C’e’ l’1% di probabilita’ di ottenere una variante shiny.
La parte intelligente: il companion e’ deterministico. E’ generato dall’hash del tuo user ID con un PRNG Mulberry32. Stesso utente, stesso animale, sempre. Il commento nel codice: “Mulberry32 — tiny seeded PRNG, good enough for picking ducks.”
Le “bones” (specie, occhi, rarita’, stats) vengono rigenerate dall’hash a ogni avvio e non vengono mai salvate su disco. Solo la “soul” (nome e personalita’ generati dall’AI) viene salvata dopo la prima “schiusa.” Non puoi falsificare una rarita’ Legendary editando i file di configurazione.
Un ultimo dettaglio: il nome della specie capybara collide con un nome in codice interno di Anthropic. Per evitare falsi positivi nel build scanner (excluded-strings.txt), tutti i nomi delle specie sono codificati in esadecimale:
const c = String.fromCharCode
export const duck = c(0x64,0x75,0x63,0x6b)
export const capybara = c(0x63,0x61,0x70,0x79,0x62,0x61,0x72,0x61)
Il trucco del prompt caching che lo rende veloce
Questa e’ la parte che conta se costruite prodotti AI. Il motivo per cui Claude Code sembra veloce non e’ il modello. E’ come viene strutturato il system prompt.
In constants/prompts.ts, c’e’ un marker:
export const SYSTEM_PROMPT_DYNAMIC_BOUNDARY =
'__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__'
Questo marker taglia il system prompt in due meta’. Tutto cio’ che viene prima del confine e’ identico per ogni utente: identita’, definizioni dei tool, stile di output, gestione dei permessi. Circa 40-50K token di testo statico. Questa porzione viene cachata con scope globale, un singolo hash Blake2b condiviso da tutti gli utenti first-party. Cache hit rate: superiore al 90%.
Tutto cio’ che viene dopo e’ specifico della sessione: memoria utente, istruzioni MCP, info sull’ambiente, skill. Cache a livello org.
I commenti avvertono: “WARNING: Do not remove or reorder this marker without updating cache logic.” Ogni condizionale piazzato prima del boundary moltiplica le varianti dell’hash per 2N. Diverse PR interne (#24490, #24171) documentano bug causati da condizionali nel posto sbagliato.
Il risultato pratico: il modello non rielabora le istruzioni base a ogni turno. Le trova in cache. Il costo computazionale del system prompt cala del 90%+. Se costruite un wrapper che ricostruisce il prompt da zero a ogni richiesta, partite gia’ svantaggiati strutturalmente.
Come gestisce il contesto senza perdere il filo
Il contesto e’ trattato come una risorsa finita con due strategie di compressione.
Microcompact lavora preventivamente mentre usate Claude Code. I risultati vecchi dei tool (Bash, Read, Grep, Glob, WebSearch, Edit, Write) vengono progressivamente svuotati e sostituiti con [Old tool result content cleared]. La soglia e’ circa 180K token; quando viene superata, comprime fino a circa 40K. I path nei risultati vengono accorciati a path relativi per risparmiare token.
Compattazione completa (/compact) scatta quando il microcompact non basta. Il prompt di compattazione e’ probabilmente il pezzo piu’ curato dell’intera codebase. Impone un riassunto strutturato in 9 sezioni:
- Richiesta primaria e intento
- Concetti tecnici chiave
- File e sezioni di codice (con snippet completi)
- Errori e fix
- Problem solving
- Tutti i messaggi dell’utente (verbatim, mai riassunti)
- Task pendenti
- Lavoro corrente
- Prossimo passo opzionale
Il punto 6 e’ il piu’ significativo: ogni messaggio umano viene preservato parola per parola. Il feedback non va mai perso nella compressione. Il punto 9 include un guard esplicito: “Non iniziare richieste tangenziali o vecchie richieste gia’ completate senza confermare prima con l’utente.”
C’e’ anche il caricamento differito dei tool. I tool MCP e quelli opzionali non vengono inviati con lo schema completo; solo il nome. Quando Claude ne ha bisogno, chiama ToolSearch per il lazy-loading. Con molti server MCP collegati, questo risparmia migliaia di token per turno.
Undercover Mode: l’ironia si scrive da sola
Quando Claude Code lavora in un repository pubblico, un sistema chiamato Undercover Mode si attiva automaticamente. Rileva se il repo e’ pubblico (tramite una allowlist) e sopprime ogni riferimento a informazioni interne di Anthropic: nomi in codice dei modelli, versioni non rilasciate, nomi di repository interni, canali Slack.
I nomi soppressi includono Capybara e Tengu, nomi in codice di modelli non ancora annunciati. Una variabile d’ambiente CLAUDE_CODE_UNDERCOVER=1 forza la modalita’ attiva a prescindere dal tipo di repo.
Un sistema progettato per impedire la fuga di informazioni interne, esposto nella piu’ grande fuga di informazioni interne nella storia di Anthropic. Non lo puoi inventare.
La roadmap non annunciata
Feature flag e nomi in codice sparsi nella codebase rivelano cosa arrivera’ prossimamente:
| Nome in codice | Feature | Evidenze |
|---|---|---|
| Bagel | Browser web integrato nel terminale | bagelActive, bagelUrl, bagelPanelVisible |
| Tungsten | Integrazione tmux (terminale virtuale) | tungstenActiveSession, tungstenPanelVisible |
| Chicago | Computer Use via MCP | computerUseMcpState, screenshot, clipboard |
| Kairos | Agente proattivo + assistant + webhook GitHub | /proactive, /brief, /subscribe-pr |
| Torch | Sconosciuto (comando /torch) |
Solo feature flag, nessun dettaglio |
Kairos e’ il piu’ interessante. Include una modalita’ in cui Claude agisce proattivamente senza aspettare input, un comando /brief per riassunti, una modalita’ /assistant, e webhook per sottoscriversi a eventi GitHub con /subscribe-pr. Se viene rilasciato, Claude Code diventa un partner di sviluppo sempre attivo piuttosto che un tool che invochi quando serve.
Altri flag notevoli: VOICE_MODE (input vocale), BRIDGE_MODE (controllo remoto), DAEMON (server in background), ULTRAPLAN (planning avanzato cloud), FORK_SUBAGENT, UDS_INBOX (comunicazione tra agenti), COORDINATOR_MODE (orchestrazione multi-worker).
Auto-Dream: l’agente che pensa mentre dormite
In services/autoDream/, c’e’ un processo in background che consolida le memorie in 4 fasi: Orient (comprende il contesto), Gather (raccoglie memorie), Consolidate (unifica e deduplica), Prune (rimuove il superfluo).
Lavora sul memdir, la directory di memoria persistente di Claude Code. I log delle conversazioni in formato JSONL vengono analizzati, i pattern ricorrenti estratti, le memorie strutturate create. Appare come una pillola animata nel footer.
Separatamente, in services/extractMemories/, un agente di estrazione automatica delle memorie gira alla fine di ogni conversazione. E’ implementato come un fork perfetto della conversazione principale, ereditando la cache del prompt del parent a costo zero per il prefisso statico. Ha accesso limitato ai tool (solo Read, Grep, Glob, Bash in sola lettura, e scrittura nella directory di memoria).
In pratica: Claude Code sogna. Mentre non lo usate, un processo in background rielabora le conversazioni passate per migliorare quelle future.
Due classi di utenti
Il codice distingue nettamente tra external (tutti) e ant (dipendenti Anthropic). Il check e’ process.env.USER_TYPE === 'ant'.
Ecco cosa ottengono i dipendenti Anthropic e voi no:
| Capacita’ | External | Ant |
|---|---|---|
| curl, wget | Bloccati in auto-mode | Consentiti |
| kubectl, aws, gcloud | Bloccati | Consentiti |
| gh api (API GitHub raw) | Bloccato | Consentito |
| Override del modello | No | Si’ |
| Override feature flag | No | Si’, via env var |
| Prompt anti-allucinazione | Non incluso | Paragrafo completo |
| Agente di verifica | No | Verificatore avversariale |
Il system prompt stesso e’ diverso per i dipendenti. Gli utenti esterni ricevono “Go straight to the point. Be extra concise.” I dipendenti ricevono un intero paragrafo su prosa fluida, piramide invertita, niente tabelle per spiegazioni. Ricevono anche: “Default to writing no comments. Only add one when the WHY is non-obvious” e “If you notice the user’s request is based on a misconception, say so.”
Il paragrafo anti-allucinazione e’ particolarmente rivelatore. Un commento nel codice dice: “@[MODEL LAUNCH]: False-claims mitigation for Capybara v8 (29-30% FC rate vs v4’s 16.7%)”. Traduzione: il modello Capybara v8 fa affermazioni false quasi il doppio delle volte rispetto alla v4. La contromisura e’ un prompt esplicito:
“Non dichiarare mai che ‘tutti i test passano’ quando l’output mostra fallimenti, non sopprimere mai o semplificare check falliti per produrre un risultato verde, e non caratterizzare mai lavoro incompleto o rotto come fatto.”
Questa istruzione gira solo per i dipendenti Anthropic. Il resto di noi usa il modello senza questa protezione.
La telemetria di cui non sapevate
Claude Code ha due pipeline di telemetria completamente separate.
Prima: ogni operazione su file (lettura, scrittura, modifica) produce due hash SHA256. Uno per il path (troncato a 16 caratteri), uno per il contenuto completo (64 caratteri, per file fino a 100 KB). L’evento si chiama tengu_file_operation. Gli hash non sono reversibili, quindi Anthropic non puo’ ricostruire i vostri file. Ma file identici producono hash identici tra utenti diversi. Possono sapere quante persone lavorano sullo stesso file, se un file e’ cambiato tra operazioni, e quali pattern di editing sono piu’ comuni.
Seconda: oltre alla pipeline Datadog, esiste un’infrastruttura di logging first-party con OpenTelemetry che esporta batch di eventi verso /api/event_logging/batch sui server Anthropic. Ha retry persistente su disco in caso di fallimento. Tutti gli eventi tengu_* passano da questa pipeline: assegnamenti di esperimenti GrowthBook, operazioni su file, uso dei tool, contesto della sessione.
Questa seconda pipeline e’ completamente separata da Datadog e non e’ documentata da nessuna parte. Gli utenti non hanno modo di sapere che esiste, ne’ di disattivarla.
In aggiunta, GrowthBook gestisce esperimenti A/B silenziosi. I dipendenti Anthropic possono forzare qualsiasi feature flag tramite CLAUDE_INTERNAL_FC_OVERRIDES. Gli utenti esterni vengono assegnati a gruppi sperimentali senza consenso esplicito.
Easter egg e cultura interna
Sparsi nel codice, piccoli dettagli che raccontano la cultura ingegneristica di Anthropic:
- /good-claude: un comando nascosto e disabilitato (
isHidden: true, isEnabled: false) che non fa nulla. Il nome suggerisce un modo per dare feedback positivo al modello. - /stickers: apre lo store Sticker Mule con il merchandise di Claude Code. Un link hardcodato nel CLI.
- /thinkback: “Your 2025 Claude Code Year in Review.” Come Spotify Wrapped, ma per le sessioni di coding. Nascosto dietro un feature flag.
- /teleport: teletrasporto di sessioni tra web e terminale via OAuth e WebSocket. Inizi una conversazione su claude.ai, la continui nel terminale.
- Spinner verbs: i messaggi di caricamento includono “Hatching” e “Whatchamacalliting” tra le rotazioni standard.
Sicurezza: cosa e’ davvero interessante
Tre meccanismi degni di nota:
Secret scanner: Quando Claude Code scrive nella memoria del team, uno scanner cerca 40+ pattern di segreti (derivati da gitleaks): chiavi AWS, GCP, Azure, GitHub, Slack, Stripe, Anthropic, OpenAI, HuggingFace e chiavi SSH private. La regex per le chiavi API Anthropic e’ assemblata a runtime da quattro stringhe separate ('sk' + 'ant' + 'api' + '03-') per evitare falsi positivi nel build scanner. Stessa tecnica dei nomi delle specie nel buddy system.
Attestazione del client: Ogni richiesta API include un header x-anthropic-billing-header con un fingerprint crittografico che prova la provenienza dal client ufficiale. L’algoritmo: prendi un salt hardcodato, estrai 3 caratteri dalle posizioni 4, 7 e 20 del primo messaggio dell’utente, calcola SHA256 e tronca. Questo permette al server di distinguere i client ufficiali dai wrapper di terze parti.
Anti-scraping nei container: Quando gira in un container remoto (CCR), il proxy upstream legge il token di sessione da /run/ccr/session_token, cancella il file e chiama prctl(PR_SET_DUMPABLE, 0) per bloccare ptrace. Nessun processo con lo stesso UID puo’ leggere il token dalla memoria del processo.
Cosa significa tutto questo
Il sorgente di Claude Code non contiene chiavi API, segreti crittografici o vulnerabilita’ ovvie. E’ un’applicazione client; le chiamate API richiedono comunque un token valido. Ma il leak rivela cose che contano piu’ dei segreti.
Il prompt engineering e’ il prodotto. Il system prompt, la logica di compattazione, la strategia di caching a due livelli, le istruzioni anti-allucinazione, il caricamento differito dei tool. Sono mesi di iterazione su comportamenti specifici del modello. Non e’ qualcosa che reinventereste facilmente.
Il modello mente, e lo sanno. Il tasso di false-claim del Capybara v8 al 29-30% e’ documentato in un commento che doveva restare interno. La mitigazione (un paragrafo di prompt aggressivo) e’ attiva solo per i dipendenti. Tutti gli altri usano il modello senza protezione.
La build pipeline e’ la superficie di attacco. Questo e’ il secondo leak da source map in meno di un anno (il primo era giugno 2025). Il fix e’ una riga in tsconfig.json o un check nel CI. Il fatto che sia successo due volte indica un problema di processo, non tecnico.
L’undercover mode era nella source map. Un sistema progettato per impedire la fuga di informazioni interne, incluso nella fuga di informazioni. L’ironia e’ quasi poetica.
Se costruite prodotti su Claude (o qualsiasi modello frontier), il takeaway e’ strutturale: il divario tra cio’ che le aziende AI vi spediscono e cio’ che usano internamente e’ reale, misurabile, e documentato nel loro stesso codice.
