Repository Maps for Agents: Token-Cheap Overviews of Huge Monorepos

Repository Maps for Agents: Token-Cheap Overviews of Huge Monorepos

Dumping tree -L 4 into the prompt burns the context window and still misses ownership. The unfair advantage is a hierarchical repository map — packages, public entrypoints, CODEOWNERS, and generate-on-demand zooms — so agents navigate with a few hundred tokens instead of tens of thousands.

⚡ TL;DR: Precompute a map at merge time: package graph, export surfaces, owners, and “hot paths.” Serve L0 overview (~1–2k tokens) then L1 zooms by package on tool call. Never paste full trees. Pair with Cursor Notepads and Hybrid Search for Code.

Map schema

// repomap/types.ts
export type MapNode = {
  id: string;              // @acme/payments
  kind: "package" | "app" | "lib";
  path: string;
  exports: string[];       // public API names only
  owner: string;
  deps: string[];          // workspace deps
  hot?: boolean;           // touched in last 14d deploys
};

export type RepoMap = {
  sha: string;
  generatedAt: string;
  nodes: MapNode[];
  edges: { from: string; to: string }[];
};
# ✅ Generate on merge (CI artifact)
node scripts/build-repomap.mjs --out .repomap/map.json --max-exports 40

❌ Regenerating by walking the entire filesystem inside every agent turn.

L0 overview vs L1 zoom tools

// tools/repomap.ts
export function l0(map: RepoMap, budgetTokens = 1500): string {
  // compact: id, owner, deps count, hot flag — no file lists
  return renderCompact(map.nodes, budgetTokens);
}

export function zoom(map: RepoMap, packageId: string): string {
  const n = map.nodes.find((x) => x.id === packageId);
  if (!n) return "UNKNOWN_PACKAGE";
  // ✅ exports + path + owner only; agent must open files via read tool
  return JSON.stringify(n, null, 2);
}
Level Tokens Contents
L0 ~1–2k All packages, owners, hot
L1 ~300–800 One package exports + deps
L2 on demand File read / symbol search

Keep the map honest

# scripts/repomap_validate.py
def validate(map_path: str, git_sha: str):
    m = json.load(open(map_path))
    assert m["sha"] == git_sha, "stale_map"
    orphan = [n for n in m["nodes"] if not n.get("owner")]
    assert not orphan, f"unowned:{orphan[:5]}"  # ✅ fail CI

Refresh on merge like embedding pipelines — see Codebase Embeddings refresh. Tie to Amazon Q context packs so IDE and agents share one structural truth.

Closing checklist

✅ Dos
– ✅ Precompute map at merge with git SHA
– ✅ Budget L0 under ~2k tokens
– ✅ Zoom tool for package detail
– ✅ Require CODEOWNERS on every node
– ✅ Invalidate map when package graph changes

❌ Don’ts
– ❌ Don’t paste full directory trees into system prompts
– ❌ Don’t include node_modules or generated/
– ❌ Don’t list every private symbol at L0
– ❌ Don’t let maps drift across SHAs
– ❌ Don’t skip ownership metadata

Related reading

Last updated on September 11, 2026


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply