Code Knowledge Graphs

How a codebase becomes a graph of functions, files, modules and the calls between them, and how AI coding agents query that graph before they change code. Start with the pillar guide, Knowledge Graph for Code Explained, then go deeper on code graph MCP servers, tree-sitter parsing and dependency graphs.

Start with Knowledge Graph for Code Explained: A Practical Guide

Monorepo dependency graph for safer AI-assisted code changes
Code Knowledge Graphs

Monorepo Dependency Graph for Safer AI-Assisted Code Changes

Suppose you're changing a return type in shared-auth, the assistant has opened the implementation, the package's tests are passing, and you still haven't checked the apps that consume it. That's the question I want a monorepo dependency graph to answer before the edit grows.

Start with the graph your workspace already has. Find the consumers of the shared package, inspect the work that depends on it, then open the relevant callers, including the ones outside the package you're editing.

I care about that last step. A build dependency tells me where to investigate. It doesn't tell me whether a particular caller handles the new return type correctly.

Pick the graph that answers your question

A monorepo dependency graph connects things inside one repository, but those things might be projects, source modules, build targets, or individual tasks. Read the node labels before drawing conclusions about the edges.

Visualizer What it maps What to check
Nx graph Projects, with a separate task view Inspect which files create a project dependency.
Turborepo --graph Tasks and their dependencies Compare the graph with turbo.json and actual package scripts.
Bazel query BUILD targets and dependency edges Check the target label and query universe.
dependency-cruiser Source-module
Dan Greer · · 7 min read
Code dependency graph for software architecture for confident AI-assisted developers
Code Knowledge Graphs

Code Dependency Graph for Confident AI-Assisted Developers

A helper changes from returning Tier | null to returning Tier, its consumers still compile, and you have a tidy diff, but callers used null to decide whether a user needed provisioning.

That's the question I want a code dependency graph to help me investigate, before I accept an AI refactor, while the old behavior is still available to compare, with the affected callers in front of me.

What the graph needs to represent

A code dependency graph connects code entities through named relationships. Files can import files. Functions can call functions. The useful level depends on the change.

For an import rule, start with a file graph, follow the edges across module boundaries, inspect the reverse dependencies, and check how the tool resolves your project paths. For a function's return value, you'll also need its callers and their source.

I care about the distinction because an edge from billing.ts to tiers.ts doesn't say which export billing uses. A caller edge gets you closer to the decision inside that file.

Consider this illustrative chain:

checkout.ts imports billing.ts
billing.ts imports tiers.ts
createInvoice() calls getUserTier()

Here, checkout depends transitively on the tiers module, through billing, but that

Dan Greer · · 6 min read
Code graph MCP server for architecture context and safer AI code changes
Code Knowledge Graphs

Code Graph MCP Server for Safer AI Code Changes

Before I trust a code graph MCP server with a refactor, I want to know which checkout it indexed, whether it can follow calls outside the edited file, and how it catches up after a save.

A caller graph from the default branch can be useful. So can a language server reading your working tree. They answer questions about different versions of your code.

The comparison includes graph servers, repository research tools, generated documentation, and context packing.

I build Pharaoh, which is marked as ours in the table.

What the MCP connection tells you

MCP gives a client access to tools a server exposes. The MCP tools specification defines that interface.

It doesn't establish the quality of a caller graph. When evaluating a server, ask what it parsed, which references it resolved, how the index updates, and whether the returned paths belong to the revision you're editing.

For the underlying model, read what a code knowledge graph represents.

I care about the evidence attached to an answer. A useful result should let me open the affected file, inspect the caller, follow an indirect path, and decide what to test before changing shared code.

Compare the graph servers first

These projects

Dan Greer · · 7 min read
Tree-sitter code parsing use cases for AI agents cover photo
Code Knowledge Graphs

Tree-Sitter Code Parsing Use Cases for AI Agents

I can extract normalize(value) from a syntax tree and still have the wrong dependency graph. The call's spelling tells me where to look, but if a local binding shadows it, which this query doesn't check, there's more work before I can tell an agent what will break.

I build Pharaoh. Its parser, pharaoh-parser, is open source under MIT and built on Tree-sitter.

The useful place to start is a small file and a query you can inspect. Extract declarations for function search, imports for dependency analysis, and call expressions for candidate caller relationships, then check what each capture actually proves before handing it to an agent.

A concrete syntax tree keeps the punctuation

Tree-sitter produces a concrete syntax tree, or CST, with punctuation tokens inside its larger constructs, and each node has a type and a source range, so a tool can tell a declaration from a comment that happens to mention the same name and say where each one sits.

An abstract syntax tree, or AST, leaves out less useful syntactic detail, and Tree-sitter's named-node APIs let you skip anonymous tokens, including punctuation, so you can traverse something that behaves much like an AST without maintaining a separate

Dan Greer · · 6 min read
Visual knowledge graph for code explained with connected nodes and programming symbols
Code Knowledge Graphs

Knowledge Graph for Code Explained: A Practical Guide

Knowledge graph for code explained sounds abstract until your agent renames one helper, misses two downstream callers, and quietly breaks a cron job. That's the real problem: AI tools can write code fast, but they still miss structure when the repo only looks like files and folders.

What matters is whether you can answer the questions that usually burn an afternoon (or a Friday deploy): what calls this, where does it enter production, and does the same logic already exist somewhere else.

A few things worth getting straight first:

  • A code graph is about relationships, not "smart search"
  • Blast radius beats file reading when you're changing shared code
  • Reachability is the check people skip, then regret later

Read this and you'll stop guessing.

The Problem AI Coding Tools Still Have

You’ve probably seen this one already. You ask Claude Code, Cursor, or Devin Desktop to refactor a shared utility. It changes the obvious files, the diff looks clean, tests pass locally, and then some unrelated endpoint breaks because the agent never saw the callers two hops away.

That pattern keeps repeating because the weak point usually isn’t syntax. It’s structure.

The failure modes are familiar:

  • the agent
Dan Greer · · 14 min read