Code graph
Instead of reading files “blind”, Context Code builds a knowledge graph of your project: functions, classes, symbols, imports and the calls between them, across several languages (TypeScript/JavaScript, Python, Rust, C/C++, C# and others), plus the internal links in your Markdown documentation.
What the graph tells you
Section titled “What the graph tells you”- Code communities: modules that relate to each other, detected automatically — the project’s real structure, not the folder layout.
- Central nodes (“god nodes”): pieces with too many dependencies, prime refactor candidates.
- Unexpected connections: relationships that cross different communities or folders and don’t look related at first glance.
What it understands about your code
Section titled “What it understands about your code”The graph does not come out of a text search: files are actually parsed (syntax tree, tree-sitter), so a name inside a string or a comment never invents a relationship.
- TypeScript and JavaScript imports through the AST:
import … from,export … from,require(…)and dynamicimport(…). Resolving the target takes into account the aliases intsconfig.json/jsconfig.json(compilerOptions.pathsandbaseUrl, followingextends), the barrels (index.ts,index.js…) and the re-exports: ifa.tsdoesexport * from './b', the graph also draws the edge tob. Animport { X } from "@/core"stops being an “external” dependency and points at the real file. - Inheritance:
class A extends Bandimplementsin TypeScript,class A(B)in Python,impl Trait for Typein Rust, and the base classes of C++ and C#. They show up as edges of their own — Inheritance and Implements — separate from calls. - C, C++ and C# through the AST too: their functions, classes, structs and methods are extracted with
tree-sitterjust like TS/JS, Rust and Python. Their#includeandusingare still resolved by pattern, andnamespaces are ignored on purpose (they are not navigable pieces).
Front↔back bridges
Section titled “Front↔back bridges”A TypeScript call never “jumps” to a Rust or a Python function: they are different languages and the graph does not make those edges up. But the two seams that matter most in a client/server app are detected and drawn.
Tauri commands. Every invoke("my_command") in the front end is joined to the fn my_command marked #[tauri::command] in Rust, with a Tauri invoke edge. And if the command does not exist — an invoke to a name nobody implements any more, in other words a button that does nothing — the graph creates a broken node and counts it separately in the statistics.
HTTP routes. Routes declared by Express, NestJS, FastAPI, Flask, ASP.NET or axum become route nodes (GET /api/x) with a Route → handler edge to the function that serves them.
All of it is summed up in the .context/grafo/GRAPH_REPORT.md report, in a Front↔back bridges section with two very concrete lists:
- Invokes with no Rust command — each line is a button that does nothing, with the file it is called from.
- Routes with no identified handler — declared routes no function could be attached to.
If the project has neither invokes nor routes, the section does not appear.
The 3D view
Section titled “The 3D view”The graph is explored in a native 3D view: handy for grasping a large project’s architecture at a glance, seeing what connects to what and examining each node’s relationships.
Besides the usual types, the legend now has HTTP route among the nodes and four new relationships among the edges: Inheritance, Implements, Tauri invoke and Route → handler. Each entry toggles on and off with a click, and the second button isolates it (leaves only that type).
Keyboard shortcuts inside the view:
| Key | What it does |
|---|---|
1 … 6 | Toggle Markdown, Folder, Tag, Broken, Code and MD+Code |
7 | Toggles the HTTP route nodes |
0 | Show all the types again |
Ctrl+K / ⌘K | Jumps to the search box (filter by name or path) |
The agent asks the graph
Section titled “The agent asks the graph”The agent does not read the graph’s JSON: it uses the GraphQuery tool, which returns text already summarised and trimmed to a token cap. On top of the long-standing queries (summary, neighbors, subgraph, path, tag, orphans), 3.6.9 brings four that answer exactly the questions you ask when touching someone else’s code:
| Query | What it is for |
|---|---|
explore | The most useful one: in a single call it returns the symbol’s literal source code, who calls it, what it calls and its impact radius. |
symbol | Searches symbols by name or substring and lists file, line, kind and how many calls come in and out of each one. |
callers / callees | Who calls a symbol, or what it calls, grouped by file. Takes a depth from 1 to 3. |
impact | What breaks if you touch it: how many nodes depend on it, across how many files, broken down by depth and with the list of affected files. depth from 1 to 4, 2 by default. |
When a result does not fit, the agent knows: impact says so if the walk hit the node cap, and explore says so if it had to trim the source.
In the chat
Section titled “In the chat”You need to know none of this to benefit from it. Just ask in plain language:
explain
handle_livekit_jointo me and what breaks if I change it
The agent settles both things with a single explore query — it brings back the whole function, who calls it, what it calls and the files that depend on it — instead of chaining half a dozen searches and whole-file reads.
Limits and priority
Section titled “Limits and priority”A graph cannot grow forever, so there are caps: 20,000 symbols, 20,000 calls and 12,000 imports. What matters is how they are handed out: your project’s own code first, and only then the vendored folders — those ending in -master, the runtime* ones, third_party, external, include and the like — and within each group by depth and path.
The order is deterministic: two consecutive regenerations give the same graph. Before, on a repo with large vendored dependencies, they ate the cap and your own code never made it in.
Updating the graph
Section titled “Updating the graph”The graph is updated when you open the Graph view, with the /grafo command in the chat or with the view’s Regenerate button. Opening the view paints the graph that was already there first and only reprocesses if some file changed since last time; the Regenerate button always rebuilds the whole thing.
Why your wallet cares
Section titled “Why your wallet cares”The agent navigates the graph to pinpoint exactly the snippet of code it needs, instead of loading whole files into the model. Less context sent means fewer tokens — cheaper and faster answers, especially on large projects.