How I built a knowledge graph of 0 A.D.'s entire codebase and slashed my AI token costs by 70x

Tran Hieu Dang

Jul 25, 2026

Let me paint a picture you probably know too well.

You open your AI coding assistant, point it at a large codebase, and ask a simple question: "How does the simulation system work?" The agent starts reading files. And reading. And reading. Twenty files later, your context window is half full, you've burned through thousands of tokens, and the agent still hasn't found the architectural backbone of the project. Next session? Same thing all over again. The agent has no memory.

I hit this wall hard with 0 A.D. β€” an open source real time strategy game with a codebase spanning thousands of C++, JavaScript, and C source files across a simulation engine, renderer, networking stack, GUI system, and more. Asking an AI agent to understand this codebase by reading raw files was like trying to understand a city by reading every street sign one by one.

The solution: build a knowledge graph once, query it forever.

Here's exactly how I did it, what it cost, and how you can replicate the setup for any large codebase.

The problem: reading raw files are expensive and forgettable

Every AI coding session follows the same wasteful pattern:

Session Activity Without a Graph With a Graph
Initial orientation Read 50+ files -> ~150K tokens Read GRAPH_REPORT.md -> ~2K tokens
"What calls X?" grep + read 10 files -> ~30K tokens graphify query -> ~1.5K tokens
Trace a dependency path Manual trace through 20 files -> ~50K tokens graphify path -> ~1K tokens
Next session Start over. Read everything again. Graph persists. Zero rediscovery cost.

The graph pays for itself in the first session. Every session after that compounds the savings.

The tool: graphify

Graphify is an open source tool that turns any folder of code, docs, and images into a queryable knowledge graph. It works in two passes:

  1. AST pass (local, free): Parses your source code with tree-sitter - extracting classes, functions, structs, enums, call graphs, imports, and inheritance. No API calls. No tokens burned. This handles C++, C, JavaScript, Python, Rust, Go, and 30+ other languages.
  2. Semantic pass (LLM powered): For documentation, PDFs, and images, it uses an LLM to extract concepts, relationships, and design rationale. Every relationship is tagged EXTRACTED (found in source), INFERRED (reasonable guess), or AMBIGUOUS (flagged for review).

The output is three files you commit to git:

graphify-out/
β”œβ”€β”€ graph.json          # the full knowledge graph (queryable)
β”œβ”€β”€ GRAPH_REPORT.md     # god nodes, communities, surprising connections
β”œβ”€β”€ graph.html          # interactive browser visualization
└── cache/              # (optional) to help other developers generate the knowledge graph incrementally

Step by step

The instructions below assume you have uv installed. Installing uv is straightforward and their documentation is excellent, so that shouldn't be a problem. For the LLM pass, I use Ollama with the deepseek-v4-pro model on the cloud β€” probably overkill for this purpose, but that's another story. If you use a different provider or model, you'll need to adjust accordingly; graphify's documentation covers the various options.

First, graphify needs to be installed:

uv tool install "graphifyy[ollama,mcp,sql]"
# Verify
graphify --version

Note: The PyPI package is graphifyy (double y). The CLI command is graphify.

Then clone 0 A.D. and configure what to index:

git clone https://github.com/0ad/0ad.git
cd 0ad

0 A.D. is massive β€” binaries, 3D models, textures, sound files. We don't want any of that in the graph. Create a .graphifyignore file with the following content:

# Skip binaries, libraries, and build artifacts
binaries/
libraries/
build/

# Skip third-party bundled code
source/third_party/

# Skip test files
source/**/tests/

# Skip large generated/data files
*.dae
*.pmd
*.psa
*.dds
*.png
*.ogg
*.wav

# Skip images - we're using a text-only model for semantic extraction
*.jpg
*.webp
*.gif
*.ico

Graphify also automatically respects .gitignore, so anything already gitignored is skipped.

Then configure the LLM model to be used for the LLM pass:

export OPENAI_BASE_URL="https://ollama.com/v1"
export OPENAI_API_KEY="<your-ollama-api-key>"
export OPENAI_MODEL=deepseek-v4-pro

Finally, the knowledge graph can now be built:

graphify extract . --mode deep --backend openai
graphify cluster-only . --no-viz

You should see similar output to the following:

[graphify extract] deep mode enabled: richer semantic extraction
[graphify extract] scanning /Users/hieu/Documents/0ad
[graphify extract] found 1372 code, 42 docs, 4 papers, 0 images
[graphify extract] 66 file(s) not classified (no supported extension or shebang), skipped: .arcconfig, .arclint, .gitattributes, .gitignore, .graphifyignore, ActorEditor.rc (+60 more)
[graphify extract] AST extraction on 1372 code files...
  AST extraction: 100/1372 uncached files (7%) [16 workers]
  AST extraction: 200/1372 uncached files (14%) [16 workers]
  AST extraction: 300/1372 uncached files (21%) [16 workers]
  AST extraction: 400/1372 uncached files (29%) [16 workers]
  AST extraction: 500/1372 uncached files (36%) [16 workers]
  AST extraction: 600/1372 uncached files (43%) [16 workers]
  AST extraction: 700/1372 uncached files (51%) [16 workers]
  AST extraction: 800/1372 uncached files (58%) [16 workers]
  AST extraction: 900/1372 uncached files (65%) [16 workers]
  AST extraction: 1000/1372 uncached files (72%) [16 workers]
  AST extraction: 1100/1372 uncached files (80%) [16 workers]
  AST extraction: 1200/1372 uncached files (87%) [16 workers]
  AST extraction: 1300/1372 uncached files (94%) [16 workers]
  AST extraction: 1372/1372 uncached files (100%) [16 workers]
  warning: 1 source file(s) produced zero nodes and are absent from the graph: arcadia.json. A re-run will retry them (empties are no longer cached); if it persists, please report the file(s) (#1666).
  warning: 1 .sql file(s) contributed nothing to the graph because a dependency is missing: tree_sitter_sql not installed. Install it with: pip install "graphifyy[sql]" (#1745)
[graphify extract] semantic extraction on 46 files via openai...
[graphify] 1 semantic node(s) had no evidence in the source and were flagged verification=unverified
/Users/hieu/.local/share/uv/tools/graphifyy/lib/python3.12/site-packages/graphify/llm.py:2278: RuntimeWarning: semantic cache skipped out-of-scope source_file 'source/tools/webservices/userreport/templates/reports/base.html'; the file was not dispatched for extraction
  _scs(
/Users/hieu/.local/share/uv/tools/graphifyy/lib/python3.12/site-packages/graphify/llm.py:2278: RuntimeWarning: semantic cache skipped out-of-scope source_file 'source/tools/webservices/userreport/templatetags/report_tags.py'; the file was not dispatched for extraction
  _scs(
/Users/hieu/.local/share/uv/tools/graphifyy/lib/python3.12/site-packages/graphify/llm.py:2278: RuntimeWarning: semantic cache skipped out-of-scope source_file 'source/tools/webservices/userreport/views.py'; the file was not dispatched for extraction
  _scs(
/Users/hieu/.local/share/uv/tools/graphifyy/lib/python3.12/site-packages/graphify/llm.py:2278: RuntimeWarning: semantic cache skipped out-of-scope source_file 'source/tools/webservices/userreport/views_private.py'; the file was not dispatched for extraction
  _scs(
[graphify extract] chunk 2/2 done
[graphify] 3 semantic node(s) had no evidence in the source and were flagged verification=unverified
[graphify extract] chunk 1/2 done
[graphify] WARNING: dropped 13 out-of-scope node(s) attributed to file(s) not dispatched for extraction: report_tags.py, views.py, views_private.py. The model mis-attributed them to another corpus file; they were excluded from the graph (#1895).
[graphify] Deduplicated 11 node(s) (8 exact, 3 fuzzy).
[graphify extract] wrote /Users/hieu/Documents/0ad/graphify-out/graph.json: 21444 nodes, 39907 edges, 807 communities
[graphify extract] wrote /Users/hieu/Documents/0ad/graphify-out/.graphify_analysis.json
[graphify extract] tokens: 52,534 in / 41,512 out, est. cost (~openai): $0.0874
[graphify extract] next: run `graphify cluster-only /Users/hieu/Documents/0ad` to generate GRAPH_REPORT.md and name communities

You can see from the output above that the tokens cost is approximately $0.0874 - of course, this is only a ball park estimate based on the number of tokens used. Your actual cost may be different depending on the actual model used. But as the LLM pass is only used for the 42 documetns and 4 papers, the cost is minimal.

Note: You can see in the output above a warning about missing graphifyy[sql] while in the instructions above, I explicitly mentioned installation of the same package. This output is from a test when I didn't have graphifyy[sql] installed.

Note: I passed --no-viz to the graphify cluster-only . command so that a HTML with the web browsable knowledge graph is not created (graph.html). In some cases, this view can be very useful but in a large project the size of 0 A.D., this creates a visualization view that is too big and too slow to be of much use for me.

By this point, you should have a graphify-out/ folder in which you can find a high level human readable report in GRAPH_REPORT.md as well as the knowledge graph itself in graph.json. Feel free to explore the content of these files. You can also test the generated knowledge graph with graphify CLI:

graphify query "what modules connect simulation to rendering?" --budget 6000
graphify explain "CComponentManager"

VS Code integration

While you can use graphify CLI directly in the console, graphify becomes a lot more powerful when configured to run as a MCP server to aid in agentic coding. Graphify can be wired to VS Code with:

graphify vscode install

Which should return:

hieu@Hieus-MacBook-Pro 0ad % graphify vscode install
  references       ->  /Users/hieu/.copilot/skills/graphify/references
  skill installed  ->  /Users/hieu/.copilot/skills/graphify/SKILL.md
  .github/copilot-instructions.md  ->  already configured (no change)

VS Code Copilot Chat configured. Type /graphify in the chat panel to build the graph.
Note: for GitHub Copilot CLI (terminal), use: graphify copilot install

As can be seen, thhe above command installed several skills and instructions which can be used inside VS Code. Feel free to read through the installed files to see what are available.

Next step is to configure the graphify MCP server by creating/editing .vscode/mcp.json to add the following content:

{
  "servers": {
    "graphify": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "graphify.serve", "graphify-out/graph.json"]
    }
  }
}

Note: you may need to modify the command from python to point to the Python binary uv installed together with graphify. The path to this binary is $(uv tool dir)/graphifyy/bin

Once the MCP server is configured and started (via MCP: List Servers from the Command Palette), you can use the Chat window in Agent mode to ask your model questions about the codebase or even make modifications to the code. For example, I asked my glm-5.2 model: "How does the AI system work in 0 A.D.? What are the key components?" The response - which you can see in this file - used minimal tokens and was much faster than it would have been without the knowledge graph.

Sharing the knowledge graph

You will want to share the generated knowledge graph with other people as well as rebuild the knowledge on changes to the code base so that the graph stays current:

graphify hook install

This command installs several git hooks to rebuild the graph as needed (a post-commit hook to rebuild the graph after every commit and a post-checkout hook to rebuild when switch branches for example). It also installs a custom merge driver to help merging of graph.json.

To share the knowledge graph with other people, the following files need to be committed to git: graphify-out/graph.json and graphify-out/GRAPH_REPORT.md and optionally graphify-out/cache which while it can increase the repository size significantly also helps other developers to take advantage of incremental builds to regenerate the knowledge graph quicker and cheaper. Other files/folder should not be committed.