About CodeGraph

What inspired me

I'm 15, and I keep running into the same problem when I read code.

I'll open a file, see a weird line like const retryLimit = 3, and ask: why 3? why not 5? why retry at all?

git blame tells me who changed it. GitHub search tells me where it appears. But nobody tells me why it was written that way.

The answer usually exists somewhere — buried in a PR comment from two years ago, an issue nobody reads anymore, or an ADR file that was never written. It's just not connected to the line of code it explains.

So I built CodeGraph: a tool that treats decisions as first-class citizens, not as lost chat history.

What I learned

This project taught me more than any tutorial.

Code is a graph, not text. Once I parsed a file with tree-sitter, I realized every uses, defined_by, and contains relationship is an edge. A codebase is a graph that happens to be written as text.

Time is a dimension. A code graph without history is only half the picture. Every node carries valid_from / valid_to derived from real commits, and codegraph graph --at returns the graph as it existed then.

Precision beats recall. My first extractor turned every commit subject into a "decision." That produced 174 decisions on Express — and 174 empty reasons. I rebuilt the pipeline into three tiers: decision (must have a real reason), change_event (raw commit history), and dependency_event (version bumps). The default view now shows only the ~20 decisions that actually explain why. A small number of trustworthy answers beats a large number of noise.

Not everything survives review. I originally built a Dgraph backend because "graph database" sounded like the right answer. A third-party review showed it added 500 lines with zero multi-hop queries using it. I deleted it and wrote ADR-006: drop Dgraph, keep SQLite. Learning to cut a feature I was proud of was harder than adding one.

How I built it

Stage 1 — CLI + real parsing. Typer CLI, pydantic models, tree-sitter for 7 languages (TypeScript, Python, Java, Go, Rust, C++, JavaScript), SQLite storage.

Stage 2 — Real Git history. Each CodeNode version gets valid_from / valid_to from actual commits. graph --at filters nodes and edges to a point in time. codegraph diff shows how decisions changed between two versions.

Stage 3 — Decision extraction. Rules first: rationale keywords in commit bodies, ADRs, CHANGELOG sections. Every extracted decision carries a traceable commit SHA. No LLM on the default path.

Stage 4 — Line-level binding. git log -p gives the changed line numbers of each commit. Those lines are linked to the CodeNode they fall inside, so codegraph why src/file.py:42 can answer at the exact line — not just the file.

Stage 5 — Interfaces. codegraph serve opens a Cytoscape.js graph with a timeline slider. A VSCode extension adds a right-click "CodeGraph: Show decision" command.

Challenges I faced

"Why" is not in the code. My first assumption was wrong: I thought I could extract decisions from code comments. I couldn't. The real "why" lives in commit bodies, ADRs, and sometimes nowhere at all. The tool must say "no record found" instead of guessing — roughly 40% of line queries return nothing, and that's the honest answer.

Rebuilding the graph destroyed it. My incremental indexer skipped already-indexed commits but still called clear_graph(). Running index twice shrank an Express graph from 7027 nodes to 1871. Every node became a WORKTREE snapshot. I fixed it with a merged-write path and a guard that refuses to write if the node count drops by half.

Review found what tests didn't. I had 136 passing tests, but a reviewer found 22 real problems in an hour: unreproducible uids, dead nodes answering why, category lost in the read path, a pip install command pointing at a package that didn't exist. Tests verify what you thought to test. Review finds what you didn't.

Cutting Dgraph. I wrote 500 lines of Dgraph client code. No command ever ran a multi-hop query. It existed because the original pitch said "graph database" and Dgraph was the most impressive-sounding one. Deleting it and writing ADR-006 was the right call, and it made the project smaller and more honest.

What's next

Publish to PyPI so pip install works without cloning Publish the VSCode extension to the Marketplace More precision work on decision extraction for projects without ADRs

CodeGraph is my attempt to give every line of code a memory. Not just what changed, but why it was allowed to change.

Built With

  • cli
  • code-analysis
  • developer-tools
  • dgraph
  • graph-database
  • python
  • tree-sitter
  • typer
  • typescript
Share this project:

Updates

posted an update —

Status update — post-review

Since v0.1.0 I ran a third-party review that found 22 concrete issues. Most are now fixed:

  • 136 tests (was 52), 82% coverage
  • 8 commands — added diff for decision changes between versions
  • 7 languages — added JavaScript
  • Dgraph removed — ADR-006 documents why. SQLite only.
  • Three-tier decisions — decision / change_event / dependency_event. The default view shows only decisions with real reasons.
  • Line-level binding — why file:line now returns the exact line, not the file
  • Real project verification — Express: 5920 nodes / 2409 edges / 204 records

Every number in the README is measured, not estimated. The 22 issue reports and fixes are in the commit history.

Log in or sign up for Devpost to join the conversation.

posted an update —

CodeGraph v0.1.0 — the decision memory layer for your codebase

Git blame tells you who changed it. CodeGraph tells you why.

CodeGraph turns a codebase into a queryable graph that links three layers:

  • Structure — tree-sitter parses TypeScript, Python, Java, Go, Rust, and C++ into AST nodes and edges
  • Time — every node carries valid_from / valid_to from real Git history
  • Decisions — extracted from commit messages, ADRs, and CHANGELOGs, linked to the lines they justify

What's in this release

  • CLI with 7 commands: index, why, graph, decisions, conflicts, export, serve
  • Real Git history traversal (not a static snapshot)
  • Time-travel queries: codegraph graph --at 2024-06-01
  • Decision cards with traceable commit SHAs
  • Web visualization with an interactive timeline slider
  • VSCode extension (right-click any line → "Show decision")
  • Optional local LLM extraction via Ollama (--use-llm)
  • Dgraph backend as an alternative to SQLite
  • 52 tests passing

Why not just ask an AI?

You can. But AI sees only the current file and infers the rest. The real reason often lives in a PR comment from two years ago, a closed issue, or a rejected alternative that was never written down. CodeGraph extracts those and stores them with a traceable source.

codegraph export --for-ai packages real decisions into a context file you can paste into Cursor or Claude — so agents reason over facts instead of patterns.

Links

Built by a 15-year-old self-taught developer. MIT licensed.

Log in or sign up for Devpost to join the conversation.

Submission history