Back to Blog
ARTICLE

A map of what your project actually exposes

September 30, 2026
Milad Nalbandi
2 min read
0 readers
keel

Onboarding to a codebase produces a knowledge base you read. What nobody had was something you look at — one picture that says: here is what this system exposes, and here is what talks to what.

keel map build writes that picture. Five levels, all derived from the code rather than from somebody's memory of it.

The whole system

The system level: web, api, database, queues and scheduled jobs, with the edges between them

Endpoints come from the contract, not from scanning for annotations. Tables come from the migrations, in applied order. Queues come from the literal names at publish and listen sites. Each source is the one that already encodes the answer, so the map can't drift from the thing it describes.

Note the counts in the corner — 11 endpoints · 5 tables · 2 queues · 23 declarations. And note the line at the bottom of the legend, which is the part I care most about:

Not read: 1 publish or listen site whose queue name is not a literal

The level code cannot answer

A call graph shows which class calls which. It cannot tell you that placing an order and charging for it are one piece of business.

The business flow as swimlanes: a person, web, api, database, queue, external — with one journey stepping left to right

So this level isn't derived from the call graph at all. It's read from what a person wrote, with the same citation requirement as everything else — and until somebody writes it, from the specs, labelled as such. A step with nothing behind it is drawn dashed and counted as unsourced.

That's the honest position: the machine can draw what the code does, and it should not pretend to know why.

The schema, from the migrations

The database level: tables with their columns, primary keys marked, foreign keys drawn as edges

Read from the migrations in applied order, which means an ORM-generated schema is invisible to it — and it says so rather than drawing an empty diagram.

Saying what it could not read

This is the design decision the whole thing rests on.

A path item behind a $ref. A queue name assembled at runtime. A module grouped by endpoint prefix because the project has no role directories. Each of those is counted and named on screen.

The alternative — dropping what you can't parse — produces a map that reads as "this project has no such endpoint". That's not an omission, it's a false statement. A map that quietly under-reports is worse than one that admits its edges.

Staying honest over time

The map is keyed to a commit and to a hash of the sources it read.

Keyed to the commit alone, a map rebuilt from edited sources would read as current. Keyed to nothing, one nobody rebuilt would re-stamp itself on every commit. Both of those are ways of being confidently wrong, and .keel/memory.json had already learned that lesson.

A map older than HEAD draws dimmed and names what it knows is missing. keel map check re-resolves every citation and fails on one that no longer lands.

keel map build     # derive it
keel map check     # every citation still lands?
keel dashboard     # look at it

keel is a Claude Code plugin. github.com/MiladNalbandi/keel

Milad Nalbandi
Software Engineer & Writer