Zero-dependency parsing
The Python extractor walks the stdlib ast module only. There is no tree-sitter and no jedi, so nothing third-party sits between your source and the graph.
Asking what calls a function, or what breaks if you change it, used to mean reading files and grepping. Lattice parses the code once into a graph and answers in one short call, with the exact file and line for every symbol. It also draws the same graph as rings you can read at a glance.


Internal to Renkara. Lattice is a tool Renkara Media Group builds and runs for itself. It is not offered for sale, and there is nothing to buy or join. This site shows what it does and how it is built.


Distance from the center is call depth: entry points sit on the outer rim, and the helpers everything leans on sit near the middle. Symbols cluster by package around each ring, and bigger dots are structural hubs.
A call that jumps across many rings is a layering violation you can literally see. Filter by repository, symbol kind, or package when the whole picture is too much.
An agent that asks context about a symbol gets its signature, its callers, its callees, and its metrics in one short reply, each with a file:line citation. It reads the file only if it needs the body.
The replies on the agent tools page are real output from the sample codebase, not a mockup.


Lattice reads Python with the standard library's parser, resolves what each call really points at, measures every symbol, and serves the result two ways: as MCP tools for coding agents and as a visualizer for people. Everything below runs today.
The Python extractor walks the stdlib ast module only. There is no tree-sitter and no jedi, so nothing third-party sits between your source and the graph.
Extraction looks at one file at a time: its imports, base classes, annotations, and call sites. Cross-file work happens later, in a separate pass, which keeps parsing simple and leaves a clean seam for other languages.
Lattice never writes to a repository it analyzes: no marker files, no .gitignore edits, no config injection. A test asserts it, and the test is never skipped.
Route decorators, command-line command decorators, MCP tool decorators, and Lambda-style handler(event, context) functions are detected as the places execution starts, and they seed the depth rings.
Each file's content hash is stored. When every file in a repository still matches, indexing leaves it alone and says nothing changed; when any file differs, the repository is re-indexed. A forced rebuild is one flag.
Calls like x.foo() are the hard case. Lattice reads the declared type of x from your annotations instead of running a type-inference engine, so fully annotated code resolves best.
A call resolves through its own scope, then its imports, then self and base classes, then declared annotations, then a small inferred-local pass. Standard library and third-party calls are marked external.
When nothing else resolves a method name, Lattice checks whether the name is unique in the repository. If it is, the edge is kept at confidence 0.5 so you can filter it out. If it is not unique, the call stays unresolved.
Each call edge carries a resolution tag and a confidence. A call that cannot be resolved is stored as unresolved with its raw text. A confidently wrong graph is worse than an incomplete one, because an agent acts on it.
A breadth-first walk from every entry point gives each symbol its distance from where execution starts. Entry points are depth 0, and shared foundations sit deepest. Code no entry point reaches has no depth, which is itself a signal.
PageRank over the call graph, computed in plain Python, ranks the structural hubs. It sizes the nodes in the visualizer and orders search results, so the central match comes first.
A recursive query walks the call graph backward from a symbol and groups everything that depends on it by hop distance, so you see whether a change is contained or systemic before you touch it.
In-degree and out-degree are stored with each symbol at index time, so "how coupled is this?" is a lookup, not a traversal.
context, impact, search, and overview answer structural questions. code_instrument and verify_blueprint hand graph evidence to Chirp and check a PubMark Code Blueprint against the graph.
Responses carry signatures and file:line locations, never file bodies. A context call is designed to cost under 500 tokens. If a response starts carrying source, that is a defect.
The visualizer puts entry points on the outer rim and foundations at the center, groups symbols by package around each ring, and sizes nodes by PageRank. A call that crosses many rings is a layering violation you can see.
Select a symbol and every dependent is colored by hop distance, from red at the symbol through orange, yellow, green, and blue to purple at five hops or more. Everything else fades back.
Real captures of the running tool, with fictional StrataForge Robotics data. They follow your theme.






The stdlib parser reads each file on its own and emits symbols plus call stubs. A repository whose files are all unchanged is skipped on the next index.
A symbol table across the repository turns stubs into edges, cheapest rule first, and tags each edge with how it was resolved and how confident that is.
Depth, PageRank, and in and out degree are computed once and stored on every symbol.
MCP tools, a REST API, a command line, and the visualizer read the stored graph. No source is re-parsed when you ask a question.
Lattice's visualizer uses native controls with accessible names, a page heading, and focusable scrolling regions, and axe-core finds no violations in it in light and dark. The graph itself is a canvas you drive with a mouse, so picking a symbol has no keyboard path yet. We do not claim a WCAG conformance level for the product.
The repository, kind, and package menus, the blast-radius checkbox, the theme toggle, the symbol panel, and its scrolling regions are native controls or focusable regions that Tab reaches. The graph canvas is mouse-only, so selecting a symbol has no keyboard path yet.
Every menu has a name, the page has one h1, and axe-core finds no violations in the populated visualizer in either theme. The graph is a canvas with a text label only; the symbol panel and the MCP tools return the same facts as text. It has not been tested with a screen reader.
The axe-core color-contrast rule passes on the interface in both themes. The colors drawn inside the canvas (node kinds and the blast-radius ramp) were not measured for contrast.
Nothing in the visualizer animates. Its stylesheet has no transitions or animations, and the canvas redraws only in response to input.
Resizing text to 200 percent has not been tested in the visualizer.
The visualizer page does not scroll sideways at 375 by 667. It is a desktop tool. The canvas pans with a mouse drag and zooms with the wheel, with no touch gestures, and touch target sizes were not measured.
| Backend |
|
|---|---|
| Frontend |
|
| MCP server |
|
| Languages and scope |
|
| Privacy and operations |
|
code_instrument builds a Chirp message candidate with exact graph evidence. Lattice never sends it; a separately authorized producer does.
Relays Lattice's MCP tools to coding agents in every session.
The first Code Blueprint verified against the graph was Dossier's backend: every file and every declared component edge matched, with zero drift.
Receives Lattice's own service logs and traces, like the rest of the fleet.
Agents ask structural questions of the code and get compact, cited answers. Lattice only reads its database: it never edits a repository and never sends a message.
contextimpactsearchoverviewcode_instrumentverify_blueprintNo. Lattice is internal to Renkara and is not offered for sale. It runs locally because the graph encodes the structure of proprietary source. This site shows what it does. Write to contact@renkara.com with questions.
No. Every screenshot is the real visualizer drawing a small made-up Python codebase for StrataForge Robotics, a fictional company. Lattice normally graphs Renkara's own repositories, and those never appear here.
Not fully, and Lattice says so. Resolution depends on annotations, and some calls cannot be resolved statically. On two of Renkara's largest Python codebases, measured on 07/27/2026, about half to seven in ten internal calls resolved, and about 44 to 48 percent resolved exactly with no heuristic. The rest are stored as unresolved or as low-confidence edges you can filter. A small, fully annotated codebase like the sample resolves almost completely.
Never. It opens source files for reading only, and a test asserts that indexing writes nothing to the analyzed repository.
Annotations already state the types, so Lattice reads them. It keeps the parser to the standard library and makes every edge explain how it was derived.
Write to Renkara Media Group and a person will answer.