Graft: mappa del codebase per agenti di coding
Graft analizza il repository con tree-sitter, crea una mappa dei simboli e la rende interrogabile via MCP: l’agente evita di riscoprire la struttura a ogni sessione.
Che cos’è una mappa del codebase per gli agenti di programmazione
Una mappa del codebase per gli agenti di programmazione è un indice persistente del repository che l’agente consulta, invece di esplorarlo da zero con grep a ogni nuova sessione. Graft è un’implementazione di questo approccio. Analizza il codice con tree-sitter, scrive una cartella di nodi Markdown collegati e un grafo dei collegamenti tra i simboli, quindi fornisce strumenti di recupero tramite MCP (model context protocol, l’interfaccia standard usata dagli agenti di programmazione per chiamare strumenti esterni).
Graft non è un proxy e non è un gateway. Tra l’agente e l’API del modello non viene inserito alcun componente. La mappa è una cartella su disco che l’agente legge. Questa distinzione determina quale problema stai risolvendo: un gateway self-hosted per i token misura e instrada le richieste che già invii, mentre una mappa modifica il numero complessivo di richieste necessarie.
La tecnica è precedente a questo strumento e continuerà a essere utile anche dopo. Impara prima la tecnica, poi i dettagli operativi.
Perché gli agenti di coding consumano contesto per riscoprire la struttura
Osservate un agente che inizia a lavorare su un repository già analizzato cinquanta volte. Elenca le directory. Cerca un simbolo con grep. Apre tre file per trovare quello che definisce la funzione, poi un quarto per scoprire chi la chiama. Nulla di tutto questo fa parte dell'attività richiesta. È orientamento e viene pagato in token di input a ogni sessione.
La causa è semplice. Un modello non conserva memoria tra le sessioni. Tutto ciò che l'agente ha appreso sulla struttura del repository viveva in una finestra di contesto che è stata eliminata al termine della sessione. La stessa fase di analisi riparte quindi da zero, al costo completo. In un repository di grandi dimensioni, l'orientamento costa più della modifica: dieci chiamate agli strumenti per individuare il codice e una per modificarlo. L'orientamento rappresenta solo una metà di quel costo e la modifica l'altra; per questo una skill che impone all'agente la modifica minima funzionante è utile insieme a una mappa, invece di scegliere tra le due.
Una mappa interrompe questo ciclo spostando l'analisi dal modello al disco. Un parser esamina il repository una volta, registra dove è definito ogni simbolo e quale simbolo chiama quale altro, quindi mantiene aggiornato il registro al variare del codice. L'agente pone una domanda e riceve una risposta con file e riga associati. L'esplorazione ripetuta diventa una ricerca economica.
Probabilmente usate già una versione più semplice di questo approccio. Un file AGENTS.md che definisce le vostre convenzioni impedisce all'agente di ricostruirle ogni volta. Una mappa generata gli impedisce di ricostruire la struttura. La differenza riguarda chi la scrive. Il file di istruzioni viene scritto manualmente, quindi rimane breve. La mappa viene generata da un parser, quindi può coprire diecimila file. Per capire come viene effettivamente distribuito il budget durante una sessione, come Claude Code utilizza la finestra di contesto illustra la ripartizione.
Che cosa costruisce effettivamente Graft
Due artefatti, entrambi all’interno di un’unica cartella graft/ nella radice del repository.
Il primo è un grafo di nodi scritto come markdown collegato, con un file per ogni nodo. Ogni nodo contiene un riepilogo in inglese semplice, un «punto centrale» con le righe di logica più importanti estratte dal codice sorgente, i file sorgente esatti con un hash del contenuto, wikilink tipizzati verso altri nodi (depends_on, part_of, uses, implements) e una sezione di note che sopravvive alla rigenerazione, così puoi annotare il contesto che un parser non è in grado di dedurre.
Il secondo è graft/.graph/wiring.json, il grafo strutturale per simbolo estratto da tree-sitter: definizioni, riferimenti e archi di chiamata tra questi elementi.
La separazione è importante perché solo una delle due parti richiede un modello. graft build usa esclusivamente tree-sitter e non chiama mai un LLM (large language model), quindi è deterministico e non ha costi. graft build --deep aggiunge i riepiloghi scritti e i punti centrali per ogni simbolo; queste operazioni richiedono chiamate al modello e sono a pagamento.
Il supporto ai linguaggi è organizzato per livelli, e il livello indica quanto puoi fidarti di un grafo delle chiamate. TypeScript, JavaScript, Python, Go e Java ricevono la risoluzione tra file consapevole dell’ambito. Rust, C, C++, C#, Ruby, PHP, Kotlin, Scala, Swift, Elixir, Solidity, OCaml, Zig e Dart ricevono i simboli e archi di chiamata generici. In questo caso un arco può basarsi sulla corrispondenza di un nome anziché su un riferimento risolto. Gli archi con precisione da compilatore sono opzionali tramite --lsp e un language server come rust-analyzer o gopls.
Installare Graft e bloccare la versione
Graft richiede Node.js 20 o versione successiva ed è distribuito con licenza MIT. Ad agosto 2026 la release corrente è 0.10.1 e la prima versione pubblicata, 0.1.0, risale a luglio 2026. Consideratelo un software ancora giovane.
npm install -g @nanonets/graft@0.10.1
npm ls -g @nanonets/graftnpm ls -g deve stampare @nanonets/graft@0.10.1. Bloccate intenzionalmente questa versione. Un semplice npm install -g @nanonets/graft risolve il tag latest nel momento in cui lo eseguite. Se il progetto pubblica diverse release minori ogni mese, il martedì potreste usare uno strumento diverso da quello installato dal collega il lunedì. Una versione bloccata mantiene uguali per tutti i flag della CLI e il formato del grafo. In questo modo l'aggiornamento avviene quando lo decidete voi.
Collegate quindi Graft a un repository di vostra proprietà:
cd /path/to/your/repo
graft init --dry-run
graft initgraft init chiede con quali coding agent eseguire l'integrazione, quindi crea il grafo. Eseguite prima --dry-run e leggete l'elenco dei file che intende modificare, perché alcuni possono trovarsi fuori dal repository. graft init è idempotente e non sovrascrive le configurazioni esistenti, quindi eseguirlo una seconda volta è sicuro.
Ad agosto 2026 l'integrazione supporta Claude Code, Cursor, Codex, GitHub Copilot, Google Gemini, Kiro, Windsurf e AdaL. Claude Code offre l'integrazione più completa: una voce per un server MCP, una statusline che mostra le dimensioni e l'aggiornamento del grafo, hook post-edit che ricostruiscono il grafo e un file skill in .claude/. Gli altri ricevono un file di istruzioni o di regole che informa l'agent della disponibilità degli strumenti. Di conseguenza, "supportato" significa che Graft scrive l'integrazione; se un agent ignora il proprio file di regole, ignorerà anche la mappa. Questo è il motivo ordinario per cui gli agent ignorano le istruzioni che scrivete per loro, e vale anche in questo caso.
Cosa entra nel repository e cosa resta fuori da git
Dopo graft init, sono previsti questi file:
graft/: il grafo dei nodi markdown egraft/.graph/wiring.json. Viene aggiunto automaticamente a.gitignore..mcp.json: registra il server MCP graft, in modo che Claude Code lo avvii..claude/settings.json: viene integrato nella posizione esistente e aggiunge la statusline e gli hook post-edit.AGENTS.md,GEMINI.md,.github/copilot-instructions.md,.cursor/rules/graft.mdc,.kiro/steering/graft.md,.windsurf/rules/graft.mde.adal/skills/graft/SKILL.md: sezioni delimitate da marker, aggiunte ai file corrispondenti agli agent selezionati.~/.codex/config.toml,~/.codex/hooks.jsone~/.codex/hooks/graft/graft-hooks.cjs: file a livello di sistema, scritti solo quando selezioni Codex.graft init --no-globalli salta, mentregraft init --no-hookssalta autonomamente l'hook shim.
Il grafo è una cache, come node_modules. Non eseguirne il commit. Viene rigenerato dal codice in pochi secondi, cambia dopo quasi ogni modifica e, se incluso nel commit, trasforma una correzione di una riga in un diff di diverse centinaia di file che nessun revisore leggerà. Esegui invece il commit dei file di integrazione, inclusi AGENTS.md e .mcp.json. Un collega clona il repository, esegue graft build e ottiene il proprio grafo locale.
Verifica che la regola di esclusione sia stata applicata prima del primo commit:
grep -n graft .gitignore
git status --shortgrep dovrebbe stampare una riga contenente graft/, mentre git status --short non dovrebbe elencare nulla sotto graft/. Se nell'output compaiono file sotto graft/, significa che la voce di esclusione manca oppure è stata sovrascritta altrove. Correggi il problema prima del commit, perché git continua a tenere traccia di un file dopo che è stato aggiunto e una successiva modifica con .gitignore non ne rimuoverà il tracciamento.
Se preferisci registrare manualmente il server MCP o fissarlo alla stessa versione installata, la voce è breve:
{
"mcpServers": {
"graft": {
"command": "npx",
"args": ["-y", "@nanonets/graft@0.10.1", "mcp"]
}
}
}Gli strumenti di esplorazione che l’agente usa al posto di grep
Graft espone sei strumenti tramite MCP. graft_find_code restituisce i nodi ordinati per rilevanza rispetto alla descrizione di un’attività, con file e riga. graft_file_api restituisce tutte le signature presenti in un file, senza i corpi delle funzioni. graft_trace_calls segue i chiamanti o i chiamati per diversi livelli. graft_find_all restituisce le corrispondenze regex raggruppate per simbolo. graft_repo_map offre una prima panoramica di un repository sconosciuto. graft_check_freshness segnala se il grafo corrisponde ancora al codice.
Ogni strumento ha anche un equivalente CLI. È così che puoi verificare quali informazioni riceve effettivamente l’agente:
graft map .
graft ask "where do we validate the refresh token"
graft skeleton src/auth/session.ts
graft callers validateRefreshToken
graft callers validateRefreshToken --direction out
graft grep "refresh_token" --jsongraft ask dovrebbe stampare i nodi ordinati per rilevanza con riferimenti file:line, invece del contenuto dei file. Questo è l’intero meccanismo: l’agente riceve un riferimento e apre un solo file, invece di leggerne dieci per trovare quello corretto. graft viz apre un visualizzatore interattivo su localhost, se vuoi esaminare direttamente il grafo. Se graft ask non restituisce informazioni utili per una domanda a cui sapresti rispondere in trenta secondi, il grafo è obsoleto oppure il tuo linguaggio rientra nel livello ampio, e la mappa non sarà utile neppure all’agente.
Un costo è facile da trascurare. Le definizioni dei sei strumenti vengono inserite nel prompt di sistema di ogni richiesta per l’intera sessione. Il costo si applica anche se l’agente non usa la mappa. In un repository abbastanza piccolo da poter essere contenuto interamente nel contesto, il costo fisso può superare il lavoro di esplorazione risparmiato.
Cosa succede al grafo quando cambia il codice
L'aggiornamento della struttura è rapido e automatico. Graft legge il working tree, non git, quindi rileva allo stesso modo una modifica non sottoposta a commit e una modifica messa in staging. Una query analizza nuovamente solo i file il cui valore stat è cambiato. La documentazione del progetto indica un overhead di circa 3 ms. La ricostruzione al termine di un turno riguarda solo i file in cui il codice è stato spostato. Imposta GRAFT_NO_REFRESH=1 o passa --no-refresh per ottenere la risposta dal grafo su disco senza analizzare nuovamente i file. Passa --no-reuse per forzare una nuova analisi completa a freddo. È l'opzione da usare dopo l'aggiornamento di Graft.
La parte scritta dal modello si comporta diversamente ed è quella in cui gli errori si verificano senza essere rilevati. I riepiloghi e i punti chiave vengono memorizzati nella cache. Ogni nodo registra l'hash del contenuto delle proprie fonti. Quando un file sorgente cambia, il nodo viene contrassegnato come obsoleto anziché essere considerato aggiornato. Questo flag è utile solo se un'operazione lo utilizza. Aggiorna con graft build --deep, che consuma nuovamente token del modello.
Rendi visibili gli elementi obsoleti:
graft check .
echo $?Il codice di uscita 0 indica che il grafo corrisponde al codice. Il codice di uscita 1 indica una discrepanza. Esegui il controllo da un hook pre-push oppure sul branch in CI, così una mappa vecchia di sei mesi non potrà fornire risposte affidabili su codice riscritto a marzo.
Leggete con attenzione i numeri dei benchmark pubblicati
La principale dichiarazione di Graft è: «fino a 4 volte meno costoso e 3 volte più veloce, con correttezza migliore o invariata». Questi dati provengono dai benchmark del progetto, pubblicati nel relativo README. Di seguito sono riportate integralmente le due esecuzioni descritte.
The data behind this chart
[
{
"label": "Controlled sweep",
"run_count": 162,
"token_saving_pct": 42,
"tool_call_saving_pct": 46,
"correctness_pct": 93,
"baseline_correctness_pct": 93
},
{
"label": "SWE-bench Verified",
"run_count": 50,
"token_saving_pct": 23,
"tool_call_saving_pct": 25,
"correctness_pct": 66,
"baseline_correctness_pct": 54
}
]La scansione controllata comprende 162 esecuzioni su due repository, uno dei quali è Graft stesso, con tre prove per attività. Riporta il 42% di token in meno e il 46% di chiamate agli strumenti in meno. L'esecuzione su SWE-bench Verified comprende 50 istanze, con lo stesso modello in entrambi i gruppi, e riporta un risparmio inferiore: 23% di token e 25% di chiamate agli strumenti. Una terza esecuzione ha riprodotto cinque pull request di PocketBase già unite, con un costo di 11.02 dollari statunitensi rispetto ai 13.91 del riferimento.
Considerate tutti questi dati come benchmark del fornitore. Due aspetti ne limitano l'utilità. La scansione controllata include il repository di Graft, cioè la codebase rispetto alla quale gli autori hanno ottimizzato lo strumento. SWE-bench Verified è un dataset pubblico di issue provenienti da noti progetti Python open source, e gli strumenti vengono ottimizzati proprio per i dataset pubblici, indipendentemente dalle intenzioni. Nessuno dei due benchmark descrive il vostro monorepo privato, che ha convenzioni di denominazione proprie e il proprio codice non utilizzato.
La correttezza richiede una seconda lettura. Nella scansione controllata non è cambiata: 93% con la mappa rispetto a 93% senza. L'aumento a 66% rispetto a 54% compare soltanto su SWE-bench Verified. Uno strumento che riduce la spesa per i token senza modificare la qualità offre comunque un buon compromesso. Non trasferite però il risultato di correttezza di SWE-bench al risultato sui token della scansione e non presentate entrambi come un'unica dichiarazione.
Misura la differenza effettiva di token nel tuo repository prima di trarre conclusioni
L'unico numero rilevante è quello del tuo repository. Questo metodo richiede un pomeriggio.
Scegli un'attività che puoi ripetere esattamente. Una domanda è preferibile a una modifica, perché una modifica cambia il repository e la seconda esecuzione non costituisce più lo stesso esperimento. «Quale modulo applica il rate limiting alla route di login?» ha la forma corretta.
Attiva la telemetria e inviala al tuo terminale:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
claudeL'exporter della console stampa i record delle metriche mentre vengono raccolti. Quello che ti interessa è claude_code.token.usage, che contiene un attributo type con valore input, output, cacheRead o cacheCreation. L'orientamento compare in input e cacheRead, perché è lì che finiscono i contenuti dei file. Somma questi due valori.
Esegui l'attività 3 volte, ogni volta in una sessione nuova, con la mappa collegata. Rimuovi quindi la voce graft da .mcp.json ed esegui l'attività altre 3 volte. Confronta le mediane invece delle singole esecuzioni, perché le esecuzioni dell'agent possono variare molto e un'esecuzione sfavorevole può indicare il risultato opposto a quello reale. Registra anche il numero di chiamate agli strumenti: le chiamate agli strumenti sono il meccanismo, mentre i token sono l'effetto; quindi, se i token diminuiscono senza una riduzione delle chiamate agli strumenti, è cambiato qualcos'altro.
Sottrai quindi i costi che il benchmark non mostra. graft build --deep consuma token del modello a ogni refresh completo. I 6 schemi degli strumenti vengono inclusi in ogni richiesta. Se gli agent vengono eseguiti su un server che noleggi, impostare un limite massimo rigido per la spesa degli agent trasforma un costo imprevisto in un budget, mentre che cosa rileva realmente la telemetria di un coding agent descrive quali dati escono dalla macchina dopo l'attivazione dell'exporter.
Quando una mappa del codebase smette di essere utile?
- Il repository rientra già nel contesto. Un singolo servizio di piccole dimensioni non ha bisogno di una mappa, e a ogni richiesta continui comunque a pagare il costo di sei schemi di strumenti. Se oggi l'agent trova qualsiasi file con una o due chiamate agli strumenti, salta la mappa.
- Il linguaggio rientra nel livello ampio. I collegamenti generici tra chiamate fanno sì che
graft callerspossa non trovare un chiamante oppure produrne uno a causa di una collisione tra nomi. Verifica congraft grepprima di considerare attendibile l'ampiezza dell'impatto. - Il grafo è diventato obsoleto e nessuno se n'è accorto.
graft checkrestituisce 1 quando rileva una deriva, ma questo è utile solo se qualcosa lo esegue. Serve un hook o un passaggio CI, non un'abitudine. - Il monorepo richiede un'ambito più ristretto. Un monorepo basato su un singolo repository Git viene suddiviso automaticamente in base al file workspace,
go.mod,pyproject.tomloCargo.toml, mentregraft ask "..." --in services/billing/restringe una query a un solo sottoprogetto. Lo stesso criterio che porta a usare file AGENTS.md annidati per ogni package si applica anche alla mappa. - L'agent ignora il collegamento. Osserva le chiamate agli strumenti in una sessione reale prima di concludere che la mappa venga utilizzata. Se l'agent continua a eseguire
grep, significa che non ha mai letto il file delle regole.
FAQ
Devo aggiungere la directory graft/ a git?
No. graft build aggiunge automaticamente graft/ al tuo .gitignore, perché il grafo è una cache rigenerabile come node_modules. Cambia dopo quasi ogni modifica, quindi aggiungerla al repository nasconde le differenze effettive sotto centinaia di file generati. Esegui il commit della configurazione che indica agli agenti l'esistenza della mappa, inclusi AGENTS.md e .mcp.json, e lascia che ogni membro del team esegua graft build localmente. Verifica con grep -n graft .gitignore e git status --short prima del primo commit, perché git continua a tracciare un file dopo che è stato aggiunto e modificare .gitignore in seguito non interrompe il tracciamento.
Graft ha un costo di esecuzione?
La parte strutturale no. graft build, graft ask, graft check e i sei strumenti MCP di recupero eseguono operazioni tree-sitter senza mai chiamare un modello. graft build --deep è la parte a pagamento: scrive i riepiloghi in inglese semplice e i crux per ogni simbolo tramite un LLM, configurato con GRAFT_PROVIDER, GRAFT_API_KEY e GRAFT_MODEL, oltre a GRAFT_BASE_URL per qualsiasi endpoint compatibile con OpenAI. Puoi eseguire Graft solo con la struttura e non consumare mai token per il grafo.
Quanto può far risparmiare una mappa del codice nel mio repository?
Non è possibile dirlo senza effettuare una misurazione. Il progetto riporta il 42% di token in meno nella propria analisi di 162 esecuzioni e il 23% in meno su SWE-bench Verified, in entrambi i casi rispetto a una baseline senza mappa. Sono entrambi benchmark del fornitore: uno è stato eseguito in parte sul repository di Graft e nessuno dei due descrive il tuo codice privato. Esegui tre volte la stessa domanda ripetibile con la mappa e tre volte senza, impostando CLAUDE_CODE_ENABLE_TELEMETRY=1 e OTEL_METRICS_EXPORTER=console, quindi confronta la mediana di claude_code.token.usage per i tipi input e cacheRead.
Cosa succede al grafo quando eseguo un refactoring?
La struttura viene rianalizzata automaticamente. Graft verifica l'albero di lavoro e rianalizza soltanto i file modificati, quindi un rinominazione viene rilevata alla query successiva con un overhead di circa 3 ms. Inoltre rileva il lavoro non sottoposto a commit perché legge i file anziché la cronologia di git. I riepiloghi scritti dal modello sono invece quelli che diventano obsoleti: ogni nodo memorizza un hash del contenuto delle proprie sorgenti e una sorgente modificata contrassegna il nodo come obsoleto invece di riscriverlo. Esegui graft check . per visualizzare la divergenza, quindi graft build --deep per aggiornare la parte scritta.
Quali agenti di codifica possono usare Graft oggi?
Ad agosto 2026 graft init configura Claude Code, Cursor, Codex, GitHub Copilot, Google Gemini, Kiro, Windsurf e AdaL. Claude Code riceve il supporto più completo: una voce del server MCP in .mcp.json, una statusline, hook post-edit e un file skill in .claude/. Codex riceve una sezione AGENTS.md e voci a livello di macchina in ~/.codex/, che graft init --no-global non modifica. Gli altri ricevono un file di regole o di steering. Qualsiasi altro client MCP può usare direttamente il server registrando il comando npx -y @nanonets/graft@0.10.1 mcp.