CLI tool
Cranot/roam-code avatar
Cranot/roam-code

roam-code: a local code graph for AI coding agents

Local codebase intelligence CLI + MCP server for AI coding agents: SQLite code graph, 28 languages, 287 commands, 246 MCP tools, change-safety gates, audit evidence, zero API keys.

519 stars50 forksPythonApache-2.0

At a glance

What is it?
roam-code builds a SQLite index of your repository so an agent can ask what a change touches before it makes it. Here is how the install works, where the static analysis stops being trustworthy, and who should skip it.
Who is it for?
Adopt roam-code if your agent already works in a Git repository and you want structural answers (callers, blast radius, affected tests) without sending source anywhere. Skip it if you need runtime truth, coverage numbers, or a guarantee that a green gate means the change is safe; the README says a good health score is not permission to merge.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem roam-code targets: agents that write faster than humans can read

A coding agent can produce more code in an afternoon than a reviewer can read line by line. The README states the project's premise plainly: it is built for agents that outpace manual reading. The gap it addresses is not generation but orientation. Before an agent edits a function, it needs to know where that function is defined, who calls it, which files sit downstream, and which tests are connected to it. Text search answers the first question and nothing else.

roam-code is aimed at developers running an AI coding agent against an existing repository, particularly one large enough that "just read the files" stops working. It is a Python package (3.10 or newer) that installs as a CLI and, optionally, as a Model Context Protocol server. The README is explicit that it complements the editor, text search, tests and code review rather than replacing them: "a search finds a name; Roam helps you follow where that name is defined and used." That framing is honest about scope. It is an orientation tool, not a test runner and not a type checker.

How the SQLite code graph is built and queried

The mechanism is static analysis over a persisted index. `roam init` parses the repository into a map of functions, classes, imports and the connections between them, and stores it locally. Parsing is done with tree-sitter; the Docker image notes that tree-sitter and tree-sitter-language-pack ship glibc-only manylinux wheels for several language packs, which is why the image is Debian-based rather than Alpine. The project claims 28 languages.

Queries run against that map rather than against the source tree. The CLI exposes the results in the terminal, and the MCP server exposes them to an agent as tools: the README's headline counts are 287 commands and 246 MCP tools, with 17 in a default `core` preset. The preset matters. Handing an agent 246 tools is not the same as handing it 17, and the default is the smaller number.

One output worth understanding is the preflight report, which classifies a symbol by blast radius, affected tests, complexity, coupling, conventions and fitness rules. The README includes a recorded example from Roam's own codebase for `open_db`, returning CRITICAL with 17922 symbols in 1732 files. The README also flags the reading carefully: blast radius means code that could be affected through the indexed connections, not code that will break. That distinction is the difference between a useful signal and a panic.

Installing roam-code and running a first preflight

The README gives a four-command sequence to run inside a Git repository. The `[mcp]` extra installs the agent-tool server; dropping it gives a CLI-only install. Python 3.10 or newer is required.

bash
pip install "roam-code[mcp]"
cd /path/to/your/repo
roam init
roam health

`roam init` builds the local index and project configuration. `roam health` prints a summary of code structure and findings. The README warns that the first index takes longer than later refreshes and that timing depends on repository size and your machine; it does not publish a number, so treat any figure you see elsewhere as unverified.

To check a specific symbol, find it first and then preflight it. The README's example uses `open_db`, a function in Roam's own source tree.

bash
roam search open_db
roam preflight open_db

The report prints a verdict line, then blast radius, affected tests, complexity, coupling, conventions and fitness. In the recorded example the verdict is CRITICAL and the stated risk driver is blast radius. If you only want the index without project configuration, the README says to use `roam index` instead of `init`. Isolated installs are also documented: `pipx install roam-code` and `uv tool install roam-code`. On Windows, if `roam` is not found after a uv install, the README says to run `uv tool update-shell` and restart the terminal.

Where the static analysis stops being trustworthy

The README concedes the central limitation: the connections come from static analysis, so they can be incomplete. Dynamic dispatch, reflection, generated code and configuration-driven wiring are the usual places where a static graph misses an edge. A blast radius that looks small may simply be a blast radius the parser could not see.

There are two more boundaries stated in the README. First, "a suggested test list is not test coverage." The affected-tests figure tells you which tests are connected to the code through the index; it does not tell you whether those tests exercise the behaviour you are changing. Second, "a good health score is not permission to merge." A passing gate is evidence that the checks ran, not proof that the change is correct.

The evidence feature deserves the same caution. Roam can save what changed, which checks ran, and why a gate passed or stopped, and signed records can reveal later changes to the evidence. The README is direct that they "cannot prove that every relevant check was captured." If your compliance story requires completeness rather than tamper-evidence, this does not supply it.

Finally, the README points to `docs/network-boundary.md` for anyone working in a restricted environment. Local analysis needs no account or API key and does not automatically upload code, index, findings or telemetry, but installation and the first parser download need network access, and optional online features have explicit triggers. Read that document before assuming the tool is fully offline.

roam-code compared with language servers and grep

The closest functional neighbour is a language server: both build a symbol graph and answer definition and reference queries. The difference is in what gets persisted and who consumes it. A language server holds an in-memory view for an editor session, usually for one language at a time. roam-code writes a SQLite index to disk and exposes it over MCP, which means an agent can query it without an editor attached and across a polyglot repository.

The trade-off runs the other way too. A language server is typically built by the compiler team for that language and resolves types precisely, including generics and overloads. roam-code parses 28 languages with tree-sitter, which buys breadth at the cost of type-level precision. If your question is "which overload of this method is called here," a proper language server is the better instrument. If your question is "what in this repo touches this symbol," across Python, Go and TypeScript at once, the SQLite graph answers it in one place.

Against plain `grep` or ripgrep, the difference is the graph rather than the text. Grep finds the string; it cannot tell you that a match is a comment, a string literal or a same-named symbol in another module. That is the specific gap roam-code is selling, and it is a real one for an agent that has no memory of the repository between sessions.

Licence, upkeep and what the release cadence implies

roam-code is Apache-2.0, declared both in the README badge and in `pyproject.toml` as `license = "Apache-2.0"`. The README notes that the free CLI stays Apache-2.0 and refers to paid layers, so the permissive licence covers the local analysis surface but you should confirm which commands sit behind the paid tiers before planning a rollout. This is a description of the licence text, not legal advice.

The repository is not archived and the last push was on 2026-09-08, with v14.1.0 released on 2026-09-09. That is recent activity, and the version numbering has moved through 14.0.3, 14.0.4 and 14.1.0 within days, which suggests a fast patch cadence. Fast cadences cut both ways: fixes land quickly, and so do surface changes. The headline counts of 287 commands and 246 MCP tools are generated by an automated counter in the README, so they will drift between releases.

Upgrade cost is mostly index rebuild. The README does not document rollback, and it does not promise index compatibility across versions, so a major bump may mean re-running `roam init`. The build itself is pinned tightly: `pyproject.toml` requires exact versions of setuptools and wheel, and the Dockerfile installs a pinned uv and syncs from a lock file rather than a fresh solve. That pinning is deliberate, and it means a from-source build is reproducible but also that you inherit the maintainer's toolchain choices.

Editorial conclusion

Adopt roam-code if your agent already works in a Git repository and you want structural answers (callers, blast radius, affected tests) without sending source anywhere. Skip it if you need runtime truth, coverage numbers, or a guarantee that a green gate means the change is safe; the README says a good health score is not permission to merge. Before trusting it, run roam init and roam preflight on one symbol you know well and check whether the blast radius matches your own reading of the code.

Frequently asked questions

What is roam-code used for?

It builds a local SQLite index of a repository's functions, classes, imports and their connections, then lets a CLI or an AI coding agent query that map. Typical questions are where a feature starts, who calls a function, which tests are connected to a change, and what a change could affect.

How do I install roam-code?

The README gives `pip install "roam-code[mcp]"` for the CLI plus the agent-tool server, or `pipx install roam-code` and `uv tool install roam-code` for isolated environments. Python 3.10 or newer is required, and dropping the `[mcp]` extra gives a CLI-only install.

Does roam-code send my source code anywhere?

The README states that local analysis needs no account or API key and that it does not automatically upload your code, index, findings or telemetry. Installation and the first parser download need network access, and optional online features have explicit triggers; the README points to docs/network-boundary.md for restricted environments.

What does a CRITICAL preflight verdict mean in roam-code?

It means the indexed connections place a large number of symbols in the change's blast radius, as in the README's recorded example where `open_db` shows 17922 symbols in 1732 files. The README clarifies that blast radius means code that could be affected through the indexed connections, not code that will break.

Is a passing roam-code gate enough to merge a change?

No. The README says a suggested test list is not test coverage and a good health score is not permission to merge. The connections come from static analysis, so they can be incomplete, and the evidence records cannot prove that every relevant check was captured.

Official sources

  1. Cranot/roam-code on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cranot-roam-code.svg)](https://hysenlabs.com/projects/cranot-roam-code)