Blog

Repo Wikis vs a Live Code Graph

Hand an agent a repository it has never seen and the cheapest useful thing you can give it is a map. Generated repo wikis are good at making one. DeepWiki turns any public GitHub repository into a browsable wiki by swapping the domain in the URL, and the homepage promises "AI documentation you can talk to, for every repo" (deepwiki.com). No login for public code, three MCP tools so an agent can read the wiki without a human in the loop, and a price of zero. For orientation that is a good deal.

The gap opens at the first edit, when the agent needs callers and downstream effects, which a wiki was never built to store.

What a generated wiki gets right

A wiki is a compression of a codebase into topics a person can hold in their head. Someone new to a project wants to know what the major pieces are called, which one owns bookings, where the API surface lives. Prose answers that well because the question is about meaning, and meaning is what prose carries.

DeepWiki's MCP tool set describes its own shape precisely. It exposes read_wiki_structure ("Get a list of documentation topics for a GitHub repository"), read_wiki_contents ("View documentation about a GitHub repository"), and ask_question ("Ask any question about a GitHub repository and get an AI-powered, context-grounded response") at https://mcp.deepwiki.com/mcp, with no authentication for public repositories (Devin docs, DeepWiki MCP). Three documentation verbs: list the topics, read the docs, ask about them. An agent that calls those arrives at a task knowing roughly where things live, which beats arriving blind.

The question that falls through

Then the agent picks up a ticket, opens a file, and the question changes from "what is this" to "if I change this line, what else has to change with it."

That second question has an exact answer, and the answer is a set of relationships: the call sites that reach this symbol, the symbols downstream of those call sites, the tests standing over them. A wiki can describe a module accurately and still leave that set entirely unstated, because the set was never what the document was written to hold. Ask a wiki who calls a function and you get an answer synthesized from prose about the area the function lives in. Sometimes that is right. You cannot tell from the answer whether it is. The set the wiki cannot hold is exactly what dependency mapping records: every call site, resolved from the parse itself.

Two answers to the same question in cal.com

Cal.com, a repository anyone can open, turns thrown errors into HTTP responses in packages/lib/server/getServerErrorFromUnknown.ts, and near the bottom of that file sits a nineteen-line helper:

function getHttpError<T extends Error>({
  statusCode,
  cause,
  traceId,
  tracedData,
}: {
  statusCode: number;
  cause: T;
  traceId?: string;
  tracedData?: Record<string, unknown>;
}) {
  const redacted = redactError(cause);
  return new HttpError({
    statusCode,
    message: redacted.message,
    cause: redacted,
    data: traceId ? { ...tracedData, traceId } : undefined,
  });
}

Suppose you want a trace id in data on every error, including the ones the caller never stamped. Small function, clear intent, one line of edit.

The wiki page for that directory will tell you it normalizes unknown throws into HttpError instances with a status code and a redacted message. That is correct, and it is the same paragraph before and after you ask your question.

Now the graph answer, measured against cal.com at commit 176037d. getHttpError has 2 callers, both sitting in the file with it: the exported getServerErrorFromUnknown above it and getServerErrorFromPrismaError below. If callers were the whole story you would ship the edit in a minute. Its blast radius, walked outward from those two, is 77 symbols across 66 files, and the graph marks the set as crossing into the api layer. The names in it are the ones you would want on the review: defaultResponder and defaultResponderForAppDir, the tRPC handler factory createNextApiHandler, RegularBookingService.createBooking and rescheduleBooking, StripePaymentService.refund, and both booking endpoints under apps/web/pages/api/book. getServerErrorFromUnknown, the exported wrapper that calls it, carries 25 callers of its own.

One question about cal.com's server error module splits into two answers: a wiki page describing what the module does, and a blast-radius query returning 2 callers and 77 downstream symbols across 66 files for getHttpError
The same question, answered by a generated document and by a graph traversal. Counts measured on calcom/cal.com at commit 176037d via relate (kinds callers and blast_radius); cal.com is MIT licensed. Link to this diagram Open full size

The gap between those two numbers is the whole argument. Two callers in one file reads as a safe local edit. A downstream set that includes booking creation, reschedule, and a payment refund reads as a change that wants a second pair of eyes. Both answers describe the same nineteen lines. Only one of them changes what you do next.

Generation time and question time

Timing separates the two as much as content does, and it matters more over a long project.

A wiki is written at generation time. Your question arrives later. Everything in between, every merge, every rename, every new caller someone added on Tuesday, sits in that gap. Wikis handle this with refresh: repositories that add a DeepWiki badge get regenerated when the code changes (CognitionAI/deepwiki). Refresh shortens the gap and cannot close it, because a document is a thing produced once and read many times.

A graph query runs at question time. relate walks edges that were parsed from the code as it stands on the revision you are pointed at, which is why the same call against a feature branch returns that branch's callers. The answer is computed for the question rather than retrieved from a document that anticipated it. This is the same distinction we drew for retrieval in code embeddings vs code graph: similarity finds text that reads like your query, traversal finds code that is connected to your symbol.

Reading work and editing work

The practical way to hold this: sort the work by whether the agent is about to write.

Reading work is orientation, dependency triage, understanding a library you did not author, writing a design doc, answering "how does this project do auth." Prose is the right output shape, a public wiki costs nothing, and DeepWiki is very good at it. Point an agent there for open-source dependencies and it will save you real time.

Editing work is renames, signature changes, deletions, migrations, anything where being wrong means a broken build or a silent behavior change in production. Here the useful output is a list of edges with file paths and line bounds the agent can act on: what breaks when you change a function is the shape of that question, and a graph is the thing built to answer it.

Most agent sessions contain both, and the division that holds up is simple: the wiki for the dependency you did not write, the graph for the code you own.

Known limits

A parsed graph sees what the parser can resolve. Dynamic dispatch through a string-keyed registry, a handler wired up by configuration, a call made through reflection: those edges are weak or absent, and blast radius understates the true reach in codebases that lean on them heavily. Fan-in is also not proof of breakage. A blast radius of 77 means 77 symbols sit on a path through the thing you are changing, and many of them will pass through your edit untouched. The number sizes the review; it does not do the review.

The wiki has the opposite blind spot and the opposite strength. It can tell you a module exists because of a migration that is half finished, which no edge in any graph encodes. It also indexes public repositories that you have not connected to anything, which is exactly why it is the fast answer for a dependency.

Symvanta indexes your own code and hands your agent the graph over MCP: callers, dependencies, blast radius, cross-repo edges, branch-aware. If you want the tool-by-tool version against DeepWiki specifically, that is on the DeepWiki alternative page. If you want to see the numbers above computed against a repository you actually maintain, start a free trial: 7 days, no credit card.

Start free trial →