Loading episodes…
0:00 0:00

Kill Your CODEMAP: When Structural Tools Make Manual Symbol Indexes Obsolete

00:00
BACK TO HOME

Kill Your CODEMAP: When Structural Tools Make Manual Symbol Indexes Obsolete

10xTeam May 22, 2026 5 min read

tags: [codemap, codegraph, symbol-index, pre-commit, tooling, maintenance] related:

  • 032_pre-index-your-codebase.md
  • 033_structure-vs-intent.md status: current —

036 — Kill Your CODEMAP: When Structural Tools Make Manual Symbol Indexes Obsolete

There is a category of tooling that feels productive to maintain but is actually a liability. You know the type: a file that must be kept in sync with the code, enforced by a pre-commit hook, that blocks commits when it drifts. Every team builds at least one of these before they discover a better way.

In DarJS, that file was CODEMAP.md.

What CODEMAP Was

The idea was reasonable. DarJS is a framework spread across eight packages. New contributors — and the AI working on it — needed to know where things lived. So we built a markdown table mapping every public function to its file, its line number, and a one-line note about what it did.

## `packages/cli/commands/contracts.js`

| Symbol | Line | Notes |
|--------|------|-------|
| `runContractsCmd(subcommand, args)` | 36 | dispatches to runBuild or runServe |
| `runBuild(args)` | 49 | calls buildContractsGraph, prints stats |
| `runServe(args)` | 71 | HTTP server on port 5050; auto-builds if graph missing |

A pre-commit hook ran dar codemap --check before every commit. If any line number was stale or a new export was missing, the commit was blocked.

This worked. Until it didn’t.

The Problem With Manual Indexes

The pre-commit hook blocked commits twice in the same session. Both times for the same reason: we added a function, the lines shifted, and the CODEMAP was out of date by the time the commit ran.

The fix was mechanical — find the new line numbers, update the table, re-stage, re-commit. No thinking required. A computer could do it. In fact, a computer was doing it, just in the wrong direction: detecting the problem instead of preventing it.

This is the signature of a maintenance burden that has outgrown its justification. When you spend more time keeping a file accurate than you save by having it, the file is costing you.

But there’s a deeper problem. CODEMAP was a workaround. The question it answered — where is this symbol, what does it do, who calls it? — is a structural question about the codebase. And structural questions about a codebase should be answered by structural tools, not by a human typing line numbers into a markdown table.

What Replaced It

CodeGraph is an AST parser that builds a SQLite graph of every symbol in the project. Functions, methods, classes, imports, routes — all indexed with file paths, line numbers, docstrings, and call edges. The index updates automatically when files change.

The same questions CODEMAP answered:

# Where is runServe?
codegraph_search('runServe')
→ packages/cli/commands/contracts.js:104  function runServe(args)

# What does it call?
codegraph_callees(id)
→ buildContractsGraph, startCodeview, buildExplorerHtml, ...

# What calls it?
codegraph_callers(id)
→ runContractsCmd

Sub-millisecond. Always accurate. No maintenance.

The line numbers in CodeGraph are never stale because they come from the AST, not from a human. When you add a function and shift everything down by thirty lines, CodeGraph re-indexes on save. CODEMAP would have blocked your next commit.

The Notes Column

The one thing CODEMAP had that CodeGraph doesn’t is the Notes column: informal annotations like “auto-builds if graph missing or older than 5 minutes” or “defaults to port 5050”.

These are not structural facts. They are semantic ones. And they already have a home: the @contract blocks on the functions themselves.

/**
 * @contract
 * @does   Starts the contracts HTML explorer; auto-rebuilds graph if missing or >5min old.
 * @reuse-when  You need to browse contracts in a browser with live rebuild support.
 */
function runServe(args) {  }

When the contract is on the function, it travels with the code. It shows up in codegraph_node. It’s searchable via dar find. It doesn’t require a separate file to stay in sync because it is the file.

The Notes column was a sign that semantic annotations belonged in the code but were being stored outside it.

The Decision

We removed the CODEMAP check from the pre-commit hook. One line commented out:

# 4. CODEMAP — retired; CodeGraph provides symbol lookup with no maintenance cost
# node "$ROOT/packages/cli/bin/dar.js" codemap --check || exit 1

The file stays in the repo as historical reference. The enforcement is gone.

The pre-commit hook now runs eight checks instead of nine. The one we removed was the only one that required human maintenance to stay passing. Every other check — syntax, contracts coverage, test suite, .d.ts coverage — is fully automated and self-healing.

The Pattern

CODEMAP is not unique to DarJS. Every non-trivial codebase has at least one manually maintained index: a ROUTES.md listing every API endpoint, a COMPONENTS.md mapping component names to files, a GLOSSARY.md explaining domain terms. Some of these are enforced by hooks. Most drift within weeks.

The question to ask about any of them is: what structural tool would make this redundant?

For symbol location and call graphs, the answer is an AST indexer. For API routes, it is a route-aware tool that reads the framework’s router. For component trees, it is a component graph tool. For domain terms, it is the @contract @does fields on the code itself.

Manual indexes are gap-fillers. They exist because the structural tool doesn’t exist yet. Once the structural tool exists, the manual index becomes a maintenance burden. At that point, the right move is to retire it — not to keep maintaining both.

The test is simple: if a computer could keep this file accurate automatically, and you are keeping it accurate manually, you are doing the computer’s job.

Build the computer. Kill the file.


Join the 10xdev Community

Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.

Audio Interrupted

We lost the audio stream. Retry with shorter sentences?