mcpField
A
architecture-map

architecture-map

github.com/almendiliDevelopment383110 installsUpdated 10w ago
Repository

About architecture-map

architecture-map is a skill for turning a code repository into an interactive map of its subsystems, call paths, and payload flows. It combines human-authored descriptions with measured file coverage and geometry, while requiring edges and flows to reflect actual code.

Key features

  1. 01Repository structure detection
  2. 02Measured file coverage and geometry
  3. 03Authored subsystem descriptions
  4. 04Code-traced edges and payload flows
  5. 05Sync checks for unmapped files

Use cases

  1. 01Orienting newcomers in a repository
  2. 02Mapping real subsystem and call relationships
  3. 03Updating an existing architecture map
  4. 04Checking source coverage after code changes

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/almendili/skills --skill architecture-map

After installing, type/architecture-mapin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

assets/components/
ArchitectureMap.tsx
BuildingGlyph.tsx
DistrictLayer.tsx
EdgeLayer.tsx
IsoCanvas.tsx
keyframes.css
SidePanels.tsx
theme.ts
assets/core/
archetypes.ts
districts.ts
iso.ts
layout.ts
program.ts
README.md
routes.ts
scene.ts
types.ts
assets/stores/
useFlowClock.ts
useMapCamera.ts
useMapView.ts
references/
authoring.md
frameworks.md
geometry.md
scripts/
architecture-sync.mjs
propose-coverage.mjs

Details

From the project README

Architecture map

Turn a repository into a place you can walk around: an isometric city where every building is a real subsystem sized by its real weight, every line is a call path that exists in the code, and every moving dot is a payload the app actually ships.

The one rule

Prose, groups and flows are authored. Counts, coverage and geometry are measured.

No scanner can say what a subsystem is for, and no human can keep file counts honest. Every good property of this page falls out of that line — including the fact that it does not rot, because "unmapped files" is only meaningful once a human has claimed the rest.

Do not try to generate the authored half mechanically. Read the code and write about it. That is the work, and it is why this is a skill rather than a codegen script.

Before you start

Read references/authoring.md. It has the voice, the archetype vocabulary, and worked examples of good and bad node prose. Read references/geometry.md only if you need to hand-tune footprints or edge routes.

Step 1 — Detect

Answer these from the repo. Do not ask.

QuestionWhere to look
Framework and routerpackage.json, app/ vs pages/ vs src/routes/, vite.config, next.config, remix.config
Design tokensglobal stylesheet for --* custom properties; tailwind.config; any tokens/theme module
Dark mode mechanism.dark class, [data-theme], or prefers-color-scheme
Test runnerpackage.json scripts, vitest.config, jest.config
Package managerlockfile
Monorepoworkspaces, pnpm-workspace.yaml, turbo.json
Existing mapa previous architecture.config.json — if present, this is an update

Then run the proposer to get a first read of the shape. It lives beside this file, not in the repo you are mapping, so resolve its path first:

SKILL_DIR — the absolute path of the directory containing this SKILL.md, which your harness reported when it loaded this file. It differs per tool (~/.claude/skills/architecture-map, ~/.codex/skills/architecture-map, ~/.agents/skills/architecture-map, a plugin cache, or a project-local .claude/skills/…). Substitute the literal path; do not rely on an environment variable.

node "$SKILL_DIR/scripts/propose-coverage.mjs" --root . --target 22

It returns directory clusters with file counts and line totals, plus suggested groups. Treat it as a draft, not an answer — it knows where code is, not what it does.

Step 2 — Ask exactly four questions

Ask them together — in one structured-question call if your harness has one (Claude Code: AskUserQuestion), otherwise as a single numbered message — then work uninterrupted. Do not drip-feed them one at a time.

  1. Where should it live? Recommend /~/architecture — a ~ segment reads as "internal tool" and sorts away from real routes. Offer /architecture and /internal/architecture.
  2. What should it cover? Whole repo / source only / one package. Preselect sensibly if it is a monorepo.
  3. Design system. State what you detected — "Tailwind v4 with CSS custom properties" — and offer: use it, or the bundled neutral palette.
  4. Extras. Wire the freshness check into CI? Add the sync to predev/ prebuild? Include the version-history dropdown?

Step 3 — Install the core

Copy $SKILL_DIR/assets/core/, assets/stores/ and assets/components/ into the repo under the path you agreed (e.g. src/architecture/). These are dependency-free apart from React, and typecheck under strict.

Then write architecture.config.json at the repo root:

{
  "coverage": "src/architecture/coverage.json",
  "output": "src/architecture/measured.generated.ts",
  "sources": ["src/**/*.{ts,tsx}", "scripts/**/*.mjs"],
  "ignore": ["next-env.d.ts"]
}

Copy $SKILL_DIR/scripts/architecture-sync.mjs into the repo's own scripts/ and add "architecture:sync": "node scripts/architecture-sync.mjs".

Adapt the theme

Edit components/theme.ts only. Point each semantic name at the repo's tokens:

export const paint = {
  surface: 'var(--tsc-background)',
  border: 'var(--tsc-foreground-tertiary)',
  accent: 'var(--tsc-brand)',
  // …
}

If the repo has no design system, leave the defaults — they define --am-* fallbacks and work standalone. Never reach for a host token anywhere except this file.

Step 4 — Author the graph

This is the real work. Write graph.ts exporting GROUPS, NODES, EDGES, FLOWS and INTRO, typed by core/types.ts.

Groups — 4–7 neighborhoods, named the way the team talks: "Entry & control", "The pixel pipeline", "Outside world". Not "utils" and "lib".

Nodes — aim for 15–25. For each, read the actual files and write:

  • whatItDoes — one or two sentences, plain language, no jargon
  • howItsBuilt — the interesting decision, not a dependency list
  • role — a short noun phrase for the flow captions: "the session gate"
  • files — real paths a reader can open

Derive archetype, params, height and footprint with core/layout.ts:

const { archetype, params } = deriveArchetype(measure)
const height = deriveHeight(measure)
const footprints = packLayout(inputs, GROUPS.map((g) => g.id))

Keep a hand-written footprint if a human already tuned one — the merge prefers the authored value.

Edges — real call and data paths only. If you cannot point at the code that makes the call, do not draw the line. Add via waypoints when a route would otherwise cut through a building.

Flows — 3–6, each an ordered list of edge ids with a payload name. These are the page's verbs and the first thing a newcomer presses. Find them by tracing real paths: sign-in, the main create/read loop, the expensive background job.

Coverage — write coverage.json so every source file is claimed exactly once. $-prefixed keys are notes. Use priority when a nested directory must win over its parent. Then:

node scripts/architecture-sync.mjs

Iterate until it reports zero unmapped, or until what remains genuinely is not part of the system.

Step 5 — Mount it

Create the route for the detected framework — see references/frameworks.md. Import keyframes.css once. Pass ArchitectureData in from your graph module plus UNCLAIMED from the generated file.

Add robots: noindex if the route is public: this is a tool handed out by link, not a search result.

Step 6 — Verify, then be honest

  1. Typecheck and lint.
  2. node scripts/architecture-sync.mjs --check — must pass.
  3. Run the app and look at it. Screenshot it. Check: no overlapping buildings, no edge cutting through a facade, every flow plays start to finish, the rail and the map agree on what is lit.
  4. Both themes if the repo has two.

Then tell the user plainly:

The geometry and measurements are correct — they are derived. The prose is a first draft. I read the code, but "what this subsystem does" is where a single pass is weakest. Edit graph.ts; nothing else needs to change.

Do not leave mediocre writing behind a confident-looking map without saying so.

Updating an existing map

If architecture.config.json exists, this is an update. Never clobber authored content.

  1. Run the sync. New numbers land in the generated file; nothing else moves.
  2. Read UNCLAIMED. Each entry is either a subsystem the map has not been told about, or an existing module whose pattern is too narrow.
  3. For genuinely new subsystems: append a node with derived geometry and drafted prose, and extend coverage.json. Leave every existing node's prose, footprint and edges exactly as they are.
  4. Report what you added and what you left alone.

Scale

Past ~25 buildings the map stops being readable. The proposer folds the smallest siblings into a parent node that owns the wider glob — the partition stays total, only the drawing simplifies. If a repo genuinely needs more, map one package at a time rather than shrinking everything.

What not to do

  • Do not draw an edge you cannot trace to a call in the code.
  • Do not set prose in the mono face. Monospace is for codes and paths.
  • Do not import a host repo's Button or Dropdown — the map ships its own.
  • Do not hand-write file counts. That is what the scanner is for.
  • Do not invent flows that sound good. A flow nobody can follow in the source is a lie the page tells confidently.

Comments

Markdown supported