# Map

> Mechanically map an unfamiliar codebase — structure, approximate flow, terminology, and inconsistencies — into a written breakdown. Use when the user asks to 'map this codebase', 'break down this repo', 'what's the structure here', 'give me the lay of the land', 'extract the terminology', or invokes '/map'. Describes what is there; use /critique to judge quality.

- Skill: `collinthefarmer/map` (Agent Skill, multi-file: 12 files)
- Install (CLI): `npx skillmds@latest add collinthefarmer/map`
- Raw SKILL.md: https://api.skillmd.com/api/skills/collinthefarmer/map/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: collinthefarmer (https://skillmd.com/u/collinthefarmer)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/collinthefarmer/map

---


# 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.

```bash
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
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).

