BeClaude

archlet

New
13GitHub TrendingGeneralby superdesigndev

Interactive, provenance-backed architecture maps in .archlet/. Two modes: MAP — analyze the whole codebase into .archlet/data.js and seed a starter overlay from a recent change; DIFF — given a PR, commit, range, branch, or working-tree changes, overlay what they touch. Use when the user asks to map / diagram / visualize a codebase's architecture, refresh the map, or show what a PR / commit / change touches.

Community PluginView Source

Overview

archlet

You produce files under .archlet/ that the viewer renders. Pick the mode from the request:

  • MAP — "map / visualize the architecture", "refresh the map", no specific change given.
  • DIFF — a change is referenced (PR, commit, range A..B, branch, or "my changes / staged").

Needs an existing .archlet/data.js — run MAP first if absent.

Nodes form a tree of any depth via parent: top-level nodes (source roots / apps) contain modules, which can nest further when a module is big enough to warrant it. Keep it shallow — add a level only when it earns its keep; the viewer expands/collapses at every level. Always finish by launching the viewer (see end).


Mode 1 — MAP → .archlet/data.js

The single source of truth the viewer reads:

js
/* GENERATED by the archlet skill. */
window.ARCH = {
  config: { project, layers: { <key>: { label, border, ink, fill? }, ... } },   // project = repo name (viewer title); layers = the taxonomy YOU choose
  nodes: [{ id, name, g, parent?, brief, role, rt, path, methods? }],   // g = a layer key
  edges: [{ s, t, k, l?, src, method }],                               // src = "file:line"
  methodEdges: [{ sNode, sMethod, tNode, tMethod, src }],              // method→method calls (step 5)
};
  • nodeid internal unique slug (never shown; namespace it, e.g. coding-tools vs foundation-tools) ·

name short heading on the card · g a layer key · parent the containing node's id, nested as deep as the structure needs (omit for top-level nodes) · brief ≤ ~6-word tagline · role one sentence · rt key file(s) · path dir relative to repo root · methods (optional, leaf nodes) [{ name, src:"file:line", calls? }] — the top ~3–6 functions by call count.

  • edge.k — a short lowercase kind YOU choose (static import, runtime wire, app→engine…); keep the

Containment is implicit via parent — never emit containment edges.

  • edge.l (optional) — what flows over a wire edge (messages.create, POST /webhook); set it only where

it adds signal, never a count ().

  • methodEdge — a call from one node's method to another's. sMethod/tMethod must exist in those nodes'

methods and src is the call site, else the edge is dropped.

Procedure:

  1. Scan structure — find source roots (apps/*, packages/*, src); they become the top-level nodes. Read docs.
  2. Choose the layer taxonomy (the key judgment) — a few layers, calm palette, e.g.

frontends / control-plane / runtime / shared-pkg / external. Put them in config.layers.

  1. Extract the mechanical floor — required, via `npx`:

- Routes + import/call graph (codegraph): npx -y @colbymchenry/codegraph@latest init -i, then npx -y @colbymchenry/codegraph@latest query "" --kind route --limit 99999 --json for the route inventory. The import + call graph lives in .codegraph/codegraph.db (query it directly). - Import graph (madge), JS/TS roots only: npx -y madge@latest --json --ts-config <root>/tsconfig.json <root>/src, then collapse file→file edges to module→module. Non-JS/TS roots: use that language's tool (go mod graph, pydeps) or codegraph's import graph instead. Build on these — only drop to Grep/Read for what a static tool can't see (most wire/cross-process edges).

  1. Build — use a workflow, one agent per major module. Split the repo into its handful of large/important

modules (in a monorepo, each app/package; in a single package, the main subsystems) and give each its own agent. Each agent picks core modules (routes/controller/plugin/tool/store/service, or doc-named), emits intra-module import edges (mechanical), and stitches wire edges out of its module by matching client call sites (fetch/SDK/db/proxy/queue) to a target or external node, each with a real file:line (manual). Wire edges are NOT in the import graph and are the most valuable.

  1. Methods + methodEdges — from codegraph's call graph (.codegraph/codegraph.db; don't skip — this is

what makes nodes legible). Derive mechanically, don't invent names: - `node.methods` — top functions defined under each leaf node's path, ranked by call in-degree:

(SELECT COUNT(*) FROM edges e WHERE e.kind='calls' AND e.target=n.id) AS calls FROM nodes n WHERE n.kind IN ('method','function') AND n.file_path LIKE '<node.path>/%' ORDER BY calls DESC LIMIT 6; - **methodEdges** — calls edges crossing node boundaries, mapped to { sNode, sMethod, tNode, tMethod, src }; keep only if both method names survived into their nodes' methods. Bucket each side's file_path to its node by longest path` prefix.

  1. Write, then validate — write .archlet/data.js, run `npx archlet validate` (checks shape +

referential integrity), fix what it reports, re-run until clean. Spot-check wire edges against their file:line — drop, don't fabricate.

  1. Seed a starter diff — by default. A fresh map is static; overlaying a real recent change shows the DIFF

feature working and where activity is concentrated. Pick one coherent change (prefer a recently-merged PR via gh pr list --state merged --limit 15 --json number,title,additions,changedFiles,url; else the largest meaningful commit from git log), discounting lockfile / generated / dist noise. Build it as in Mode 2, register it in the manifest but leave default null so the clean map opens first. Skip silently if history is too thin (shallow clone, lone initial commit, only trivial changes); never fabricate one. Mention it on handoff.

Launch the viewernpx archlet view is a blocking server that auto-opens the browser; start it in the background and tell the user it's at http://localhost:4173 (stop the process to shut it down).


Mode 2 — DIFF → .archlet/diffs/<name>.js

Overlay the files a change touches onto the existing map. Read .archlet/data.js first for node paths.

1. Get the changed files (each: path, additions, deletions):

sourcecommand
PRgh pr view <n> --repo <owner/name> --json files,title,additions,deletions,changedFiles,url,number
commitgit show --numstat --format= <sha>
range / branchgit diff --numstat <A>..<B> (use <base>...<head> for branch-vs-merge-base)
working tree / stagedgit diff --numstat · git diff --numstat --staged

--numstat lines are <add>\t<del>\t<path> (- = binary).

2. Map files → nodes. For each path, find the node whose path is the longest prefix; else fall back to its top-level root/app node; else report it unmapped. Aggregate per node { files, add, del, paths }. Compute contains = ancestor node ids of every changed node (walk parent).

3. Write the overlay .archlet/diffs/<name>.js:

js
window.ARCH = window.ARCH || {};
window.ARCH.pr = {
  label: "<human label>",          // "PR #565" · "commit a1b2c3d" · "working tree"
  title: "<optional>", url: "<optional>", number: <n>,  // number only for PRs (enables ?pr=<n>)
  add, del, files,
  nodes: { "<nodeId>": { files, add, del, paths:[...] }, ... },
  contains: [ "<ancestorNodeId>", ... ],
  links: {                          // OPTIONAL — connectivity the change alters
    add: [ { s, t }, ... ],         // a dependency/wire INTRODUCED
    cut: [ { s, t }, ... ],         // one REMOVED
  },
};

links.add renders as a green + arrow, links.cut as a dashed ✕ — between the nodes' visible ancestors. Only fill links when the change actually adds/removes a node→node connection (a new/removed import, fetch, db/proxy call); omit for internal-only changes. <name>: pr-<n>, else commit-<sha7> / wip / staged.

4. Register it in .archlet/diffs/manifest.js (create if missing; keep existing entries):

js
window.DIFFS = {
  default: "<name>",
  available: [ { name, label, number?, add, del, files }, ... ],   // newest first
};

Run `npx archlet validate`, fix any issues, then launch the viewer in the background (as above) at http://localhost:4173. The viewer has a Diffs menu; switch via the menu, ?pr=<n>, or ?diff=<name>.


Rules

  • Provenance or it didn't happen — every wire edge needs a real file:line; never invent edges.
  • You decide the taxonomy (small); data.js is the single source of truth and a draft the user can hand-edit.
  • Always end by opening the map in the background, whichever mode you ran — don't leave a command to paste.
  • Monorepo gotchas: CommonJS/NestJS DI deps aren't plain imports; apps importing another app's built dist;

dynamic plugin/route registration (invisible to static tools — read the registrar).

Install & Usage

1
Create the skills directory
mkdir -p .claude/skills
2
Download the skill file
mkdir -p .claude/skills && curl -o .claude/skills/archlet.md https://raw.githubusercontent.com/superdesigndev/archlet/main/SKILL.md
3
Invoke in Claude Code
/archlet
View source on GitHub

Frequently Asked Questions

What is archlet?

Interactive, provenance-backed architecture maps in .archlet/. Two modes: MAP — analyze the whole codebase into .archlet/data.js and seed a starter overlay from a recent change; DIFF — given a PR, commit, range, branch, or working-tree changes, overlay what they touch. Use when the user asks to map / diagram / visualize a codebase's architecture, refresh the map, or show what a PR / commit / change touches.

How to install archlet?

To install archlet, create the .claude/skills directory in your project, then run the curl command to download the skill file. Once installed, invoke it in Claude Code with /archlet.

What is archlet best for?

archlet is a community categorized under General. Created by superdesigndev.