Codebase Cartography
Charting paths for your agents
Think about the times you’ve begun fresh with an agent, asking it to get started on some task. It begins globbing everything. “You’ve seen all that before,” you mumble under your breath to your computer. It has, of course, but a fresh agent always needs context to get started. Repeat.
To prevent this repetitive cycle and cut down on token usage, I built a “cartographer” agent. Its only responsibility is to “chart” a codebase by crawling it to produce a markdown document specifying purpose, architecture, the data layer, entry points, and conventions to name a handful. The output of this agent, while helpful for humans, is not for humans. This is a new class of files I track in repos specifically for agents.
The cartographer is specific in how it runs. It's an agent, not a skill, because we don't care about its run-time context; a distinction worth knowing to get the most out of agents. We only care about its output. It's important, too, that the “chart” it produces strikes a balance between orienting agents and surviving change. The right ceiling is directory-level: capture what components own, not what each file does. Go deeper and this file churns on every PR. That's an upkeep nightmare.
Here’s an example, lightly scrubbed, taken from a real project:
**Per-tenant GenServer architecture:** The central design decision: every active tenant runs exactly one Worker GenServer. Workers are named via a Registry keyed on tenant name, so routing an incoming event requires only a GenServer.cast to the registry-registered name. There is no database lookup on the hot path.
**Supervision tree:**
- Monitoring.Supervisor: DynamicSupervisor that owns all Worker processes
- Monitoring.Manager: loads active tenants from the database on startup and starts a Worker for each; handles runtime worker lifecycle
- Monitoring.Worker: per-tenant GenServer; traps exits to persist state on shutdown
- Monitoring.Counter: pure functions for sliding-window counter math; no process, no side effects
**Outbound Dispatcher:** A single GenServer that receives fire-and-forget casts from Workers. Keeps HTTP I/O off the Worker call path.
**Context boundary:** A Phoenix context module provides the only public API into the persistence layer. Controllers and GenServers go through it; nothing touches Repo directly.Two additions make this agent especially helpful. First, a directive in the agent’s instruction file (i.e., CLAUDE.md) to read this document before starting work. By doing this, the agent immediately grounds itself in the structure and conventions of the project. No more globbing. Second, other agents know to run the cartographer when significant work wraps up, keeping the chart current without manual upkeep.
The teams getting the most out of agents aren’t the ones with the cleverest prompts. Instead, they’re the ones who’ve made their codebase legible for agents, the same way good teams always have for humans.

