Engineering Context

Cross-Repository Symbol Search in Polyrepo Organizations

Symbol search replaces guesswork with precise code navigation.

Contributing Editor · · 12 min read
Cover illustration for “Cross-Repository Symbol Search in Polyrepo Organizations”
Enterprise Code Search · September 5, 2026 · 12 min read · 2,629 words

The reflex is predictable. An engineer needs to know where accountId is used across the estate, so they open a search box, type the string, and hit enter.

What comes back is a pile, not an answer. Comments mentioning accountId, docstrings referencing it, variable declarations that happen to share the name, call arguments, test fixtures, serialized JSON keys that look identical but belong to a completely different data model in a completely different service. Across dozens of repositories, a common field name like this can return tens of thousands of matches, and the search tool offers no way to tell which results are the canonical definition, which are legitimate usages of the same underlying symbol, and which are just a coincidence of naming.

Most teams misdiagnose this problem. They treat it as a speed or completeness issue, something a faster indexer or a bigger cluster fixes. Text search has no model of what a symbol is. It has no concept of scope, type, or identity; it treats source code as a corpus of strings to pattern-match against. A symbol-aware system treats the same code as a graph of named, typed entities with defined relationships to each other. That gap is one of kind, not degree, and no amount of better string-matching infrastructure closes it. Buying a faster grep solves the wrong problem.

The structural consequence is what makes this worth taking seriously. When engineers can't get a clean symbol-level result from the tooling, they ask a person instead, usually someone senior who's been around long enough to hold the map in their head. That relocates the problem, from a tool that scales to a person who doesn't.

How a cross-repository symbol index works technically

Closing that gap requires an index built around one idea: an exported function in one repository and its imported use in another are the same symbol, not two coincidentally matching strings. A real cross-repo index has to do three things text search structurally cannot do.

It has to resolve identity across package boundaries, recognizing that a function defined in package A and consumed in package B is one symbol wearing two different import paths. It has to track directionality, distinguishing a definition from a usage from a re-export, since those are different questions with different right answers. And it has to follow the dependency graph outward, not stopping at the first file that references something but tracing through the chain of services that consume it downstream.

Take a corrupted database field as the test case. A useful trace can't stop at the SQL query that reads it. It has to follow the value through the application code that processes it, into the batch job that transforms it, and out to whatever downstream service eventually consumes the result. That requires a language-aware model of the entire stack, not a single runtime's syntax tree.

The protocol most of the industry has converged on for this is SCIP, the Source Code Intelligence Protocol. SCIP is language-agnostic and uses Protobuf to serialize definitions, references, and documentation into a portable index format. Its useful architectural choice is decoupling indexing from querying: the index gets built once, locally or in CI, and the navigation layer queries it later without needing a live language server connection at request time. Because lookups happen against a unique symbol identifier rather than a text pattern, results are compiler-accurate rather than probabilistic, and the index can be version-aware, pointing a query at the implementation a given service's dependency manifest actually resolves to. Indexers exist for the major languages, and the protocol shows up in projects like Mozilla's Searchfox, rust-analyzer, and Meta's internal Glean system.

Not every approach here has survived, and that's worth sitting with before picking a direction. GitHub's stack-graphs project tried to solve cross-file and cross-repo name resolution through hand-maintained per-language grammar files; it was archived in September 2025. The maintenance burden of keeping those grammars current across languages proved too heavy relative to the payoff, and the broader community has drifted toward simpler, more composable designs since. C and C++ codebases remain a known hard case regardless of approach, since cross-repo indexing cost scales quadratically with dependency graph depth, a real bottleneck for any C++-heavy enterprise sizing this kind of infrastructure.

For teams that can't justify standing up a full SCIP pipeline, Tree-sitter-based knowledge graphs are the lighter alternative, and for most small or resource-constrained teams, they're the right starting point. They're syntactic rather than fully semantic, meaning they parse structure without full type resolution, but they build fast and compose well with other tooling.

The four cross-repo tasks where symbol search changes the outcome

The value of a symbol index isn't abstract. It shows up in specific, recurring tasks that polyrepo teams run into constantly, and in each one, text search underperforms in a way that goes beyond degree.

Impact analysis before a breaking change is the clearest case. Renaming or removing a method in a shared library raises an immediate question: how many services call it, and who owns those services? Symbol search returns every actual callsite across every repository. Text search returns every string match, including comments, dead code, and unrelated homonyms. One produces a checklist an engineer can work through before shipping the change. The other produces noise that has to be sorted by hand before it's usable at all.

Tracing a bug through a service boundary works the same way. When a field turns up corrupted three services downstream from where it originated, the question is where it's written, where it's transformed, and where it's finally read. A symbol-aware cross-reference follows that data structure through its full lifecycle across the dependency graph, rather than requiring an engineer to guess which service to check next.

Security and compliance remediation depends on the same precision, just at estate scale. When a vulnerable dependency or an exposed API surface needs to be found and patched everywhere it appears, the requirement is complete coverage: every actual usage of the symbol, not every string that happens to resemble its name. Missing a callsite because it didn't show up in a grep result is a compliance failure with a name attached to it later.

Onboarding is the quieter version of the same problem. New engineers, and non-engineers like PMs or support staff trying to understand how a feature is implemented, need a way to walk through a codebase without interrupting a senior engineer every time. Symbol navigation gives them a structured path: definition, usages, callers, in order. A list of string hits gives them a research project instead.

The bottleneck was never reading code once you found it. It's locating the right code in the first place, and a symbol index turns that from a probabilistic guess into a deterministic lookup.

Why AI coding agents in a polyrepo environment need symbol search more than humans do

Diagram: Symbol Index vs. Text Search: The 10x Agent Cost Gap. Visualizes: Visualize the concrete performance difference between an agent using grep/text search versus an agent using a Tree-sitter-based knowledge graph via MCP, drawn from a 2026…

Human engineers carry context between tasks. They remember which repos talk to which, roughly where things live, who owns what. An agent has none of that; it starts every session from zero, and it can only work with what's in front of it or what it can find.

Claude Code's agentic search approach traverses directories, opens files, runs grep, and follows references much the way an engineer would. That works reasonably well when the agent already has a rough sense of where to look. It degrades fast when the relevant code lives in repositories the agent was never pointed toward, which in a polyrepo environment with dozens or hundreds of repos is the default condition, not the exception. An agent working only from local or recently opened files is operating on a sliver of the codebase that actually matters to the task, and it has no way to know that's what's happening.

The cost of that gap is measurable, and this is the number that should reframe the whole conversation: a 2026 codebase-memory study found that exposing a Tree-sitter-based knowledge graph to an agent through MCP cut token use by roughly 10x and tool calls by 2.1x across 31 repositories. That's a cost, latency, and accuracy figure all at once, and it means the index functions as infrastructure for the agent, not a nice-to-have layered on top of it. An agent burning ten times the tokens on grep-and-guess isn't just slower; it's ten times more expensive to run at the same task, every time.

MCP, the Model Context Protocol, is what makes that connection possible. Anthropic introduced it as an open standard in November 2024, and it was donated to the Linux Foundation's Agentic AI Foundation in December 2025. Its structural contribution is turning what would otherwise be an N-by-M integration problem, every agent wired individually to every data source, into an N-plus-M problem: build one MCP server per data source, and any compliant agent can use it. By early 2026, that model had been adopted across Claude Code, Cursor, VS Code Copilot, Codex, Windsurf, Zed, and Continue.dev, among others.

Put an MCP server on top of a cross-repo symbol index, and an agent can ask, in effect, "find every caller of this method across the entire estate," and get back a compiler-accurate list instead of a grep guess. codebase-memory-mcp is one open-source example: it indexes a codebase into a persistent knowledge graph across 162 languages, answers queries in sub-millisecond time, runs no embedded LLM of its own, and keeps all processing local, meaning code never leaves the machine it's running on. The agent supplies the reasoning; the index just serves the graph.

That local-processing detail matters beyond convenience. For enterprises with data residency requirements, an MCP-accessible symbol index is simultaneously a productivity layer and a control mechanism: agents get full cross-repo context without code ever crossing the perimeter.

What self-hosted cross-repo search tools actually offer today

Judging these tools means asking five things: how deep the symbol resolution actually goes, whether there's an AI or MCP surface, what the deployment model looks like, how many languages it covers, and how much operational weight it puts on the team running it. Most of the well-known names in this space fail at least one of those cleanly, and it's worth being direct about which, rather than treating the category as a lineup of interchangeable options.

Zoekt is a Go-based, Apache-licensed trigram search engine, fast enough to return results in under 50 milliseconds on codebases the size of Android's, with symbol-aware ranking baked into results. It's the engine sitting inside several major code search platforms and carries roughly 1.7 thousand GitHub stars as of mid-2026. Its limit is by design: it's search, full stop, with no cross-reference graph, no caller or usage tracing, no impact analysis, and no AI surface. It fits teams that want fast raw search and are prepared to build the rest themselves, and nothing else.

OpenGrok, maintained by Oracle, is Java-based and has been in production at large enterprises for over a decade; release 1.14.17 shipped August 24, 2026. It supports more than 60 languages, cross-references symbols, and ships a working web UI on commodity hardware. The cost is real operational overhead: a Java 17 through 21 runtime, Tomcat 10.x or GlassFish, Universal Ctags, and roughly 8 GB of JVM heap to run comfortably. It has no AI, LLM, or MCP surface at all, a real gap now that agentic workflows are standard practice rather than an experiment. It suits teams with proven Java operations experience and no near-term agentic requirement, and probably shouldn't be the pick for anyone else.

Hound is about as simple to deploy as this category gets; a typical set of 20 to 30 repositories indexes in under a minute through Docker. It re-indexes from scratch on every update, though, which doesn't scale gracefully once a codebase gets large. There's no symbol graph and no AI surface, but for a small polyrepo setup where getting something running fast matters more than depth, it's a reasonable choice, and probably the fastest way to get any answer at all.

Meta's Glean indexes and queries across languages without per-repository configuration, and it can consume SCIP output directly, which extends its language coverage substantially. It was built for Meta's internal scale, though, and running it outside that environment carries real operational complexity; it's not a practical self-hosted option for most organizations. It's worth naming anyway, because its SCIP compatibility illustrates the protocol acting as a shared language across different indexing backends, not because most teams should try to run it.

Beyond these, a newer category of tools builds cross-repo context directly from repository clusters and exposes it through an MCP server to Claude Code, Cursor, VS Code, Codex, and other compatible agents, sometimes extending that context into project tools like Jira, Linear, and Confluence through MCP connectors, so the picture includes tickets and docs, not just code. Some support natural-language queries aimed at non-engineers, bring-your-own-model configuration so teams control where their code gets sent, air-gapped deployment, and Helm charts for Kubernetes. Pricing tends to run a free self-hosted option for smaller teams, with paid tiers adding cited answers and deeper agent context layers; Sourcebot Pro, for example, is available at $20 per user.

One caution applies across the entire category: check the commit history before betting on anything here. bloop, once a notable entrant in AI-assisted code search, shipped its final release in April 2024, was archived on GitHub in January 2025, and the company behind it shut down in April 2026. For any tool whose value depends on an index it actively maintains, the date of the last commit is a first-order evaluation criterion, not a footnote.

How to evaluate a cross-repo symbol search setup for your organization's constraints

Four constraints should drive the decision, and they pull in different directions, which is exactly why so many teams end up with tooling that satisfies none of them well.

How deep does the symbol resolution actually need to go: raw regex search, a cross-reference graph, or full dependency-aware navigation that follows a value across service boundaries? How much does AI and agent integration matter, not just today but within the next year, given how fast MCP adoption has moved across major coding assistants? What's the data residency and security posture, and does code need to stay inside the perimeter entirely, which rules out anything without an air-gapped deployment option? And does the team have the operational capacity to run a Java stack with an 8 GB heap requirement, or a custom indexing pipeline, or does it need something that comes up in a single container and stays up without a dedicated owner?

Language mix belongs in that calculation too. A C++-heavy codebase faces indexing cost that scales quadratically with dependency graph depth, and that has to factor into infrastructure sizing from the start, not get discovered after the pipeline is already running slow.

Weight the agentic trajectory even if the team isn't using AI coding agents yet. The 10x token reduction and 2.1x tool-call reduction from the 2026 codebase-memory study mean whatever index gets chosen now becomes load-bearing infrastructure as agent use grows, whether or not that's the buying criterion today. Evaluating an index without asking whether it's MCP-exposable is evaluating it against last year's requirements.

For organizations weighing cloud-hosted code intelligence against self-hosted alternatives, the framing of features against privacy sets up a false choice, and it's worth rejecting outright. Self-hosted options have closed most of the gap on navigation depth while keeping code inside the organization's own perimeter, so the real tradeoff is operational burden against control, not capability against privacy.

The principle underneath all of it stays fixed no matter which tool gets picked: the index's unit of analysis has to match the engineer's actual unit of work, which is the dependency graph, not the repository boundary GitHub happens to draw around it.

Sources

  1. in-com.com
  2. learn.github.com

More in Enterprise Code Search