Complex codebase,
Deterministic answers
Niro turns every repo into one semantic graph - languages, config and events - then answers by walking edges instead of searching text. Same question, same path, every time, at any size.
A node per symbol
an edge per relationship
Every symbol parsed at AST depth and woven into a directed graph: call chains, dependency trees, inheritance, data flow.
The graph updates incrementally as files change. No full re-index, no stale context, and it knows which branch you are on.
Calls that cross a service boundary are edges like any other. Monorepo and polyrepo resolve the same way.
Not only source. Niro parses .env files, config YAML and properties, so the graph knows how services are wired, not just how they are written.
HTTP endpoints, data resources, message queues and event handlers are mapped, so asynchronous boundaries are visible.
Every commit adds edges. More repos connected means connections no single engineer holds. File-by-file reading hits a ceiling; the graph does not.
Structural retrieval is a graph traversal, not a similarity search: the same question against the same index returns the same hops and the same facts every run. Embeddings do have a job here - natural-language search and find_reusable_code use them to pick candidates - but the relationships those candidates sit in are resolved on the graph, not ranked by distance. The sentence your agent writes around the facts is still the model's.
Reading files,
against resolving them
One incident, asked of the same assistant two ways. One column is a capable agent with a shell; the other is the same agent with the graph.
| File by file | On the graph | |
|---|---|---|
| Files opened | 47 | 2 |
| Tool calls | 87 | 10 |
| Cost of the answer | $0.35 | $0.21 |
| Time to answer | 53s | 11ms |
| Crossed a repo it never imports | no | yes |
| Asked a second time | a different path | the same four hops |
| Answer was verified | guessed | traced |
Pick a question
watch it resolve
Each question is a real MCP tool, and the traversal lights in the graph as the hops resolve - not a file read among them.
One graph per branch,
worktree and environment
Your repositories are not in one state, so Niro does not keep one graph. It keeps a project per repository and branch, reads parallel worktrees as the separate trees they are, and routes every question to the graph that covers where you actually are - re-indexing as the work moves rather than serving everyone a nightly snapshot.
Changed files re-index on their own. A full rebuild is available and rarely needed.
Every question routes to the project covering your repo and current branch. On a branch no project covers, Niro refuses to answer rather than serving stale code - and offers to build a temporary project instead.
Parallel worktrees of the same repo are read as what they are: separate trees, keyed apart, sharing what can safely be shared.
Files move over multipart and are never written to logs. Indexing needs the code; observability does not.
Questions your agent
could not answer with confidence before
35 tools reach the graph over MCP. No plugins, no per-tool wiring, and the same set for every compatible assistant.
Questions about
the index
Are the answers deterministic?
The retrieval is. A question is resolved by walking edges in the graph, so the same question against the same index returns the same hops and the same set of facts on every run. What is not deterministic is the sentence your agent writes around those facts - that is the model, and it will phrase the same finding differently twice. We claim exactness for the traversal, not for the prose.
What happens if the graph is out of date?
Changed files re-index on their own, so the graph tracks the work rather than a nightly snapshot. On a branch no project covers, Niro refuses to answer rather than serving last week's code as if it were current, and offers to build a temporary project instead. A confident wrong answer is the one failure mode worth refusing outright.
Does Niro need to build or compile my repo?
No. Tree-sitter grammars parse your source to an AST and a semantic language mapper turns that into graph nodes, so indexing does not depend on your build system, your dependency resolution or a successful compile.
What happens with a language you do not support?
Nine languages have mappers: Java, TypeScript, JavaScript, Python, Go, C#, Kotlin, PHP and Ruby. C, Scala and Rust have grammars but no mapper yet, so they are not supported - and we would rather say that than half-index them and let an agent draw conclusions from the half.
Is there a limit on how much code it will index?
Local mode (coming soon) has no line-of-code cap on any paid tier. The cloud graph is capped per tier: 25k lines on Free, 100k on Solo with add-on packs available, a 1M shared pool on Team, and unlimited on Enterprise.
Who else can see my graph?
Every project, index and session is keyed to an account, so one tenant cannot traverse into another tenant's graph. On Team an org main graph lives in Niro's cloud alongside local copies; on Enterprise it can be a shared cloud, a dedicated single-tenant instance, or a deployment inside your own VPC.
Index a repo
and ask it something
One install and one command. The graph is built from your code, and your agent picks the tools up over MCP without further wiring.