Query The Code Graph
Ask an ingested repository who calls a symbol, what it calls, what breaks if it changes, how two nodes connect, what sits next to it, what a commit range changed, and why a symbol exists — from the CLI or from an agent over MCP.
Once a repository is ingested, eight read verbs answer questions about it: who calls this, what does it call, what breaks if I change it, how do these two things connect, what is next to it, what did a range of commits change, why does this exist, and what repository snapshot the graph currently holds. All eight are available from the CLI and to any agent connected over MCP.
Before You Start
- A repository already ingested — Ingest a Repository covers that. Confirm the graph is
current first by re-running
dots repo ingestafter the checkout moves, because a stale graph returns answers that no longer match the code. - Authority to read the graph (
graph.read). Every built-in role from Viewer up carries it.
Naming A Symbol
Every verb takes a node reference. The most reliable form is a Code Symbol's human id, which you get by searching the Dotabase:
dots search "resolveActor" --dotabase code-symbols
Search is a survey read: it answers at the summary disclosure level, so each hit is
identity plus classification rather than a whole symbol record. That is all this step
needs, because the verb below takes the id and nothing more. Pass --level full when
you want to read the symbol rather than traverse from it.
The friendly <path>#<qualifiedName> form — src/auth/resolve.ts#resolveActor — is also
accepted, and it is what the MCP tools advertise. A reference that matches nothing is a
clear "symbol not found" error rather than an empty result, so an empty list always
means "found it, nothing connects", never "typo".
Who Calls This
dots graph callers SYM-412
Returns the queried symbol plus every symbol that calls it, each with its edge
confidence. Cap the result with --limit:
dots graph callers SYM-412 --limit 50
--limit takes a positive integer up to 500; a larger or non-integer value is rejected
before any request goes out rather than being silently clamped.
What Does This Call
dots graph callees SYM-412 --limit 50
The same shape in the forward direction, and the same --limit bound.
What Breaks If I Change This
dots graph impact SYM-412
Impact is the transitive blast radius: every incoming dependent reachable from the symbol within a hop bound, each carrying its hop distance and confidence. Run it before changing a symbol other code depends on.
dots graph impact SYM-412 --hops 4
--hops defaults to 2 and is capped at 5.
Two bounds apply to the result.
Impact traverses calls and inherits edges only — it is a call-graph question, not
a general reachability one, so an import relationship does not put a file in the blast
radius. And it is bounded at 500 impacted nodes overall. A result at the cap is a
sign the symbol is central enough that "what depends on this" is the wrong question;
narrow the hops instead.
How Do These Two Connect
dots graph trace SYM-412 SYM-980
Trace returns the shortest path between two nodes as ordered steps, or an empty path when nothing connects them. No route is not an error — an empty path is a real answer, and the command succeeds.
Trace is not limited to symbol-to-symbol. It reaches across kinds, so a path can run from a function to the file that defines it, to the commit that produced it, to a conversation that discussed it, to a plan that references it. Either endpoint can be a Code Symbol, a Repo File, a commit, or an artifact.
The hop budget defaults to the company's traversal setting — 6 — and --hops raises it
per call, up to 12. --limit sets the node budget the walk may visit before it gives up
(2500 by default, 10000 at most). An empty path carrying truncated: true is the one
case where empty is not an answer: the budget ran out, so whether a route exists is
undecided — retry with a larger --limit.
What Sits Next To This
dots graph context SYM-412
Context returns the immediate neighborhood: every directly connected node, in both
directions, across every edge kind rather than just calls. Each neighbor carries its
direction, edge type, edge category, and confidence. --limit caps one page of
neighbors — 500 both by default and at most — and a truncated: true response carries a
nextCursor to replay with --cursor.
Run context first on a symbol you have never seen, before asking a narrower question
about it.
What Did A Range Of Commits Change
dots graph diff a1b2c3d 9f8e7d6
Diff takes two commit SHAs — full or a hex abbreviation of at least four characters — and reports what the range changed plus what depends on it. The range is base-exclusive and head-inclusive, so the base commit itself is not in it.
dots graph diff a1b2c3d 9f8e7d6 --repo owner/repo --hops 4
--hops is the dependent walk out from the changed symbols, defaulting to 2 and capped
at 5 like impact. --repo narrows SHA resolution to one repository — the Git Commits
repository value — and is what you reach for when an abbreviation matches commits in
more than one repo.
Three limits apply to what comes back:
- Attribution is file-grained. Commit rows carry no hunks, so every symbol defined in
a changed file is reported as changed. The response's
precisionfield states what that costs and each symbol'sattributionnames how it was reached. - Retired symbols come back separately, attributed by timestamp alone.
graphSkewis non-null when the graph was not built fromhead— the range is being read against a graph built at a different commit, which is the signal that a re-ingest is due.
Diff reads the ingested commit rows, not your checkout. dots repo ingest ledgers the
commits its shipment carried metadata for — up to a 1000-commit carry bound, and none at
all from a checkout it could not read — so dots git ingest-commits <path> is the cold
fill for the rest. With no commit rows at all, diff refuses with a typed error naming that
command rather than returning an empty range, and a range wider than the server's
1000-commit walk cap is likewise refused with a typed error naming the cap.
Why Does This Exist
dots graph why SYM-412
Why walks provenance rather than structure: out from the symbol to the file that defines it, and on to the commits, conversations, plans, rows, and findings that produced or reference it — one hop per edge, both endpoints named by human id.
dots graph why SYM-412 --limit 20
--limit caps how many producing commits the walk carries forward, newest first — 5 by
default, 50 at most.
Every response carries a narrative. A symbol that resolves but reaches nothing is a
success, not an empty result: it comes back with a typed noProvenance reason and
the remedy for it. truncated: true means a cap stopped a fan-out and the hops are a
prefix, and unresolvedEndpoints counts incident edges whose far endpoint names no
surviving row.
From An Agent Over MCP
The same graph is exposed to a connected agent as eight tools: callers_of,
callees_of, impact, trace, context, diff, why, and detect_changes. The
first seven mirror the identically named CLI verbs — the same node references, the same
optional bounds, and the same caps — with diff's repository narrowing spelled
repository rather than --repo. detect_changes maps to the hyphenated CLI command
dots graph detect-changes.
One difference from the CLI affects how you write agent instructions:
detect_changesanddots graph detect-changestake no arguments and do not re-ingest anything. They report each ingested repository's name, root path, remote, default branch, and last ingested commit — enough for an agent to notice its graph is behind and say so. Refreshing it is adots repo ingestrun, which is a deliberate boundary: reading the graph never silently rewrites it.
Every one of these tools is gated on graph.read, and an agent's tool list is filtered
to what its credential actually holds — so a credential without that atom is not offered
the graph tools at all rather than being refused when it tries. Connect an Agent via MCP
covers the connection itself, and MCP Tools is the full catalog.
When A Query Comes Back Empty Or Missing
- "Symbol not found" means the reference did not resolve. Check the id with
dots search --dotabase code-symbols, and check that the file's language is one the extractor handles — a Go or Ruby file is never ingested, so its symbols were never there to find. - An empty result means the node resolved and nothing connects it by the edges that
verb traverses. For
impactthat is specificallycallsandinherits; trycontextto see everything incident to the node instead.whyis the exception — it never answers empty, returning a typednoProvenancereason and a remedy instead. - A result that looks out of date is a freshness question, not a query one. The
repository row records the applied commit; if it is behind your checkout, re-run
dots repo ingest— re-ingest is the single refresh path. - A retired file or symbol still resolves. Rows for deleted code are archived rather than erased, and they carry an archived stamp when they come back — so a node resolving does not by itself mean the code still exists.
The Bounds In One Place
| Verb | Flag | Default | Maximum |
|---|---|---|---|
callers / callees | --limit | server default | 500 |
impact | --hops | 2 | 5 |
impact | — | — | 500 impacted nodes |
trace | --hops | 6 | 12 |
trace | --limit | 2500 nodes | 10000 nodes |
context | --limit | 500 | 500 neighbors |
diff | --hops | 2 | 5 |
diff | — | — | 1000 commits in range |
why | --limit | 5 commits | 50 commits |
Repo Graph explains what produced the structure these verbs walk; Ingest a Repository is how you keep it current.
Query The Code Graph · This page in the graph
- mentionstodots coding-agents and dots git
- mentionstoConversations
- mentionstoEdge
- mentionstoDotabase
- mentionstoDIIICE: Context
- mentionstoDIIICE: Instructions
- mentionstoDOT
- mentionstodots search and dots tags
- mentionstodots mcp, dots repo, and dots graph
- referencestoConnect An Agent Via MCP
- referencestoMCP Tools
- referencestoIngest A Repository
- referencestoRepo Graph Overview
- relevant tofromDOTs And The Knowledge Graph
- mentionsfromQuickstart: Developers
- documented byfromCLI Code Graph Query Tools
- referencesfromRepo Graph Overview
- referencesfromIngest A Repository