Map — Mechanical Codebase Breakdown
/map is an engine plus a driver. Deterministic tools and analyzers compute everything algorithmically determinable; you, the driver, read the computed findings, make only the judgments code cannot, and write the breakdown. Never recompute what an analyzer already produced.
The engine has three layers you invoke as scripts; the fourth layer is you.
Setup
Resolve arguments (target default ., output default ./MAP.md) and a run dir:
RUNDIR="$(mktemp -d)/map"
| Argument | Form | Default |
|---|---|---|
| target | bare path | . |
--only |
groups: structure,flow,terminology,inconsistencies |
all |
--output |
path | ./MAP.md |
--lang |
e.g. py,ts |
all detected |
--exclude |
extra excludes on top of the defaults; bare name or glob, repeatable/comma-separated | none |
--parallel |
flag | false (see Phase 3) |
Phase 1: Extraction (the edge)
Run once; it materializes the immutable fact store. This is the only place tools run.
python3 ~/.claude/skills/map/scripts/extract.py <target> --out "$RUNDIR/facts.json" [--lang <langs>] [--exclude <pat> ...]
It resolves one canonical file list — git ls-files in a repo, else a filtered walk — through the deterministic exclude layer plus any --exclude you pass (a bare directory/name, or a glob against the relative path; repeatable or comma-separated). It probes scc/ctags/rg and degrades any missing one to a fallback. Read the printed summary and the fact store's file_source/user_excludes/excluded_sample so the breakdown can say what was skipped.
Phase 2: Analysis (the engine)
Run every registered analyzer over the fact store. Pure, deterministic, no model.
bash ~/.claude/skills/map/scripts/run-analyzers.sh "$RUNDIR/facts.json" "$RUNDIR/findings" [--only <groups>]
Each analyzer writes $RUNDIR/findings/<name>.json — an array of tagged-envelope findings ({id, analyzer, group, scope, severity, body}, the body typed by body.type). A failing analyzer is skipped, not fatal.
Phase 3: Drive — interpret and write
Read facts.json and every findings/*.json. Turn the findings into MAP.md. Your job is judgment and narration, not recomputation.
Structure — from structure-summary findings (subsystem, language-mass). Render the subsystem table (path, files, code, dominant languages, symbol-kind counts) and the language mass. Name what each subsystem appears to do from its path and symbol kinds.
Flow — from flow findings (reference-hub, entry-point). List the reference hubs and the entry-point candidates. State the caveat every time flow appears: these are textual reference counts, not a call graph — dynamic dispatch, callbacks, and cross-language calls are invisible, and generic names (run, print) inflate. Use it to orient, not to trace.
Terminology — from terminology-clusters findings (term-cluster, each a root with member identifiers and a weight). This is a proposal: merge clusters that name one concept, split ones that conflate two, and give each a plain-language name, using the member identifiers as evidence. Present the domain vocabulary, most central first.
Inconsistencies — from naming-conventions findings (naming-inconsistency). For each, judge whether the mixed conventions are a real inconsistency or an intentional/idiomatic split (e.g. constants in SCREAMING_SNAKE beside snake_case functions is normal). Report the ones that look genuinely mixed, with examples.
Write the document to --output, then print a short inline summary (language mass, subsystem count, entry-point count, top terminology clusters, inconsistency count) pointing at the file.
--parallel
For large codebases, partition the target by git-tracked, non-trivial directories, recursively (git ls-files, group by directory, fold trivial dirs into their parent), then dispatch one Agent per partition via Workflow to interpret its slice of the findings, followed by a synthesis agent that merges sections and dedups cross-partition terminology and inconsistencies — the /critique pattern. v1 note: the fan-out is not yet wired; --parallel currently drives single-context and says so. Implement when a real codebase overflows one context.
Error Recovery
| Situation | Response |
|---|---|
| A preferred tool is missing | The extractor degrades and notes it; carry that note into the breakdown. |
extract.py reports 0 files/symbols |
Report the target has no analyzable code; write no file. |
An analyzer fails (FAIL line) |
Its section is omitted; note it. The others still run. |
| Flow hubs are dominated by generic names | Expected — say so and lean on entry points and structure instead. |
| Target is a single file | Extraction and analyzers still run; the subsystem view collapses to one entry. |
--parallel on a small target |
Drive single-context (nothing to partition). |
Composition
Engine scripts live under skills/map/: scripts/extract.py (extraction), analyzers/*.py + analyzers/registry.json (the extensible engine), scripts/run-analyzers.sh (runner), lib/maplib.py (the fact/finding contract). Adding discovery logic means adding an analyzer module and a registry entry — extraction, runner, and driver are untouched. Reuses claude-lib survey where deeper tree/git detail is wanted; pairs before /critique (map to orient, critique to judge).