This is the hands-on part of the series. Part 1 covered the thesis — every box carries file:line evidence or it doesn't render. Here is the workflow: install, scan, read the report, query the graph, wire it to an agent.
One difference from the usual tutorial: you don't have to install anything to evaluate the output. I ran the released svarupa 0.2.1 against two public repos and hosted the full interactive reports on this site — adaptive-rag (268 nodes, 422 edges, 9 modules, 6 routes) and document-extraction-pipeline (277 nodes, 406 edges, 13 modules, 6 routes and a task). Every claim below is something you can click and verify in those reports right now.
Explore it live: adaptive-rag — diagram report · graph · document-extraction-pipeline — diagram report · graph
Install and first scan
Svarupa is a Python CLI on PyPI, MIT-licensed, needs Python 3.10 or newer:
uv tool install svarupa # recommended: isolated CLI
# or
pipx install svarupa
# or
pip install svarupa
svarupa --version # svarupa 0.2.1
Then point it at a repository:
cd your-repo
svarupa . # writes .svarupa/ inside the repo
open .svarupa/index.html # self-contained viewer, no server
svarupa /path/to/repo --out /tmp/report # analyze without writing into the repo
First run takes seconds on a small repo, minutes on a large one — the 592-module production backend I validated on builds in minutes and stays responsive in the viewer.
What's in the artifact
| File | What it is |
|---|
index.html | Self-contained interactive viewer — all views pre-rendered, works offline |
graph.json | The full knowledge graph (nodes, edges, evidence) — the queryable source of truth |
REPORT.md | Human-readable summary: structure, entry points, environments, diagnostics |
diagrams/*.json | Per-diagram layout data backing the viewer |
architecture.lock | With --lock: the commitable, diffable architecture lockfile |
The split matters. The viewer is for humans; graph.json is for everything else. When the viewer withholds a view for readability, the data is still complete in graph.json — nothing exists only as pixels.
The viewer: drill down, link deep, trust the caps
Open one of the demo reports and three things are worth trying immediately:
Recursive drill-down. Boxes open into their internal structure, and each child view is itself evidence-backed. Click into a module on the architecture view and you get its interior, with the same file:line provenance, all the way down.
Deep links. Every box has a copy-link button producing a #tab/<box-id> URL. Paste it to a teammate and it opens that exact box. "Why does this import that?" becomes a link instead of a screenshot.
Honest scale handling. When a view would be unreadable, svarupa draws the 12 most significant boxes and states the remainder — "N more not drawn; all of them are in graph.json." Buttons that would open a withheld view are hidden rather than dead. In the document-extraction-pipeline demo, the module-dependencies root view rendered at 836×1076, larger than the reference viewports, so the report scrolls it at natural size and tells you via SVA-G-016 instead of crushing it into an unreadable thumbnail.
Reading the diagnostics
The diagnostics are the honesty layer, and they are the first thing I check in a new report. From the adaptive-rag demo:
SVA-R-004 — the repo-root module was omitted: no extractable source. No evidence, no box, and the omission is stated.
SVA-R-007 — a few modules (repo root, app/eval, scripts) don't appear in the request-flow view because nothing reachable from a route handler imports them within two import hops. That is a fact about the code's shape, surfaced rather than smoothed over.
One number to read with care: on adaptive-rag, 29.3% of Python call sites pin to a definitive target, while import- and reference-based edges pin at 77–97% (34.0% call-pinning on document-extraction-pipeline). Framework-heavy code dispatches through decorators and dependency injection, and static analysis can't always follow. Svarupa prints these rates in the report rather than inflating them — treat them as a calibration readout, not a defect count.
Querying the graph
The same knowledge graph behind the viewer is queryable from the CLI, no LLM involved:
svarupa query .svarupa graph_stats # overview
svarupa query .svarupa get_node "billing.service" # one node, with its evidence
svarupa query .svarupa get_neighbors "api.routes" --depth 2
svarupa query .svarupa shortest_path "web" "db"
svarupa query .svarupa affected "payments.core" # blast radius, depth 3 by default
svarupa query .svarupa god_nodes --top 10 # highest fan-in/out hotspots
svarupa query .svarupa query_graph "how does auth reach the db" --budget 4000
affected is the one I reach for most: it answers "if I change this, what breaks" with a bounded traversal instead of a grep. Labels match exactly — id, qualified name, or label — and ambiguous matches are listed, never guessed. Add --json for machine consumption; --relation, --undirected, and --max-hops refine the traversal; --budget caps query_graph output in tokens, which is what makes it useful as agent context.
The MCP server
The same seven query functions are served over MCP, so an AI coding agent can answer architecture questions against the verified graph instead of re-deriving structure from raw file reads:
svarupa mcp .svarupa # stdio — what most agent clients use
svarupa mcp .svarupa --transport streamable-http
A stdio client configuration is the usual shape:
{
"mcpServers": {
"svarupa": {
"command": "svarupa",
"args": ["mcp", ".svarupa"]
}
}
}
There's also svarupa setup skill, which installs an agent skill into .claude/skills/svarupa/ teaching the agent to regenerate and consult the report. The practical effect: the agent's "how does this system fit together" answers come with evidence attached, because they come from the same graph the diagrams render from.
If you try it
- Open both live demos — adaptive-rag and document-extraction-pipeline — before installing; judge the output first.
- Install with
uv tool install svarupa and run svarupa . on a repo you know well.
- Read
REPORT.md first, then open the viewer and drill into one module to its evidence.
- Run
svarupa query .svarupa god_nodes --top 10 and check whether the hotspots match your expectations.
- Run
affected on the module you touch most often; compare with what your last PR actually had to change.
- Check the diagnostics and the call-pinning rate before trusting any single view.
- Wire the MCP server to your coding agent and ask it an architecture question you already know the answer to.
The thesis and the evidence contract are in part 1; the lockfile, per-PR diffing, and why I built all this are in part 3. The package is on PyPI, the numbers are in the case study, the short version is on the project page — and if the tool gets your architecture wrong in a way it didn't flag, tell me; that's a bug I want.