Skip to content

Map any repo from a prompt

Hand the prompt to your coding agent, paste back what it gives you, and see your codebase as a map. No install, no account.

Example repoA made-up project, so you can see the shape of the output. Run the prompt below to get this for yours.
6
modules
4
decisions
92%
structural coverage
share of your code we could turn into a map
4 decisions found. 2 of them live only in git history.
2026-01-06 → 2026-07-20 · 318 commits
Trace a flow
every page loadon cart changeon order paidorders, line itemspicks, shipmentscharges on checkoutapiHono · 41 endpointsstorefrontNext.js · 24 routescheckoutcart, tax, totalsfulfilmentpicking, shippingdbPostgres · 19 tablesstripe
SecondOS·orderly (example)scanned 2026-07-20
entryservicestoreexternal
movement, cold → hot
1 · Copy this into your coding agent
show the prompt
Map THIS repository into a portable "scan" that reads like a PRODUCT, not a folder tree. A non-engineer should understand it at a glance. Output ONE JSON object and nothing else (no markdown fences, no prose).

How to make it read well (this is the whole point):
- Name each node for what it DOES, in plain words a user would recognize: "Billing", "Support agent", "Auth", "Search", "Weekly digest" — NOT the folder ("apps/api", "lib/utils").
- Give each node a short "sub" carrying ONE CONCRETE FACT about it — the route it answers on, the schedule it runs to, the mechanism it uses, the limit it enforces, the steps it runs through: "POST /tickets/reply", "nightly 03:00 UTC", "queue + row locks", "classify -> synthesize -> verify", "45-day retention", "19 tables". A "sub" that only restates the label in other words ("answers support tickets" under a node called "Support agent") tells the reader nothing they did not already read. If you genuinely cannot find a specific fact for a node, say what it is made of ("Hono - 41 endpoints") rather than padding with adjectives.
- Label EVERY meaningful edge with the plain relationship — WHAT flows or WHEN: "charges on trial end", "nightly evals", "on signup", "escalations". A blank arrow tells the reader nothing.
- Put recognizable third-party products (Stripe, OpenAI, Postgres, Resend, S3, Slack) as their OWN "external" nodes on the receiving end, named by the product, with "sub" = what it's for ("Payments", "AI", "Database", "Email").

Rules:
- Structure only. Use paths, names, routes, and one-line paraphrased reasons from git history. NEVER include file contents, code, secrets, tokens, or connection strings.
- Limits: <=60 nodes, <=120 edges, <=40 decisions, <=12 blind spots. Prefer FEWER, clearer nodes over many.
- Be honest. If you can't tell, omit it. Do not invent edges, tools, or decisions.

Shape (ScanPayload v1):
{
  "version": 1,
  "project": { "name": "", "slug": "lowercase-dashed", "date": "YYYY-MM-DD", "window": { "from": "YYYY-MM-DD", "to": "YYYY-MM-DD", "commits": 0 } },
  "graph": {
    "nodes": [ { "id": "unique-id", "label": "Plain feature name (<=28 chars)", "kind": "entry|job|agent|service|store|external|surface", "churn": 0, "sub": "what it does (<=40 chars)", "group": "optional area", "sourceRef": "path (optional)" } ],
    "edges": [ { "from": "nodeId", "to": "nodeId", "kind": "calls|reads|writes|triggers", "label": "plain phrase (<=24 chars)" } ]
  },
  "decisions": [ { "id": "d1", "claim": "what was decided (<=120 chars)", "why": "the reason (optional)", "when": "YYYY-MM", "evidence": "shortSHA or #123", "scope": "nodeId (optional)", "recorded": "adr|pr|commit|none" } ],
  "blindSpots": [ { "node": "nodeId", "changes": 0, "lastChange": "YYYY-MM", "note": "" } ]
}

Field values:
- kind: entry=route/page/CLI/webhook/handler, job=cron/queue/worker, agent=an LLM-driven part that DECIDES (picks a tool, retries, judges) — not merely a module that calls an API, store=your DB/cache/index, external=3rd-party product (Stripe, OpenAI, Postgres…), surface=app shell (web/cli), service=an internal capability.
- churn: 0 untouched ... 3 among the most-changed in the window (from git log).
- every edge "from"/"to" MUST be an existing node "id".
- recorded: adr (a doc in the repo), pr (only the PR body), commit (only a commit message), none.
- You may omit "stats" and "coverage"; they are derived on render.

Example of the STYLE to match (yours will differ):
{"version":1,"project":{"name":"Acme","slug":"acme","date":"2026-07-25","window":{"from":"2026-01-01","to":"2026-07-25","commits":420}},"graph":{"nodes":[{"id":"job/digest","label":"Daily digest","kind":"job","churn":2,"sub":"nightly 06:00 UTC"},{"id":"svc/support","label":"Support agent","kind":"service","churn":3,"sub":"POST /tickets/reply"},{"id":"svc/billing","label":"Billing","kind":"service","churn":1,"sub":"3 plans, 5 quotas"},{"id":"ext/stripe","label":"Stripe","kind":"external","churn":0,"sub":"Payments - webhooks"},{"id":"ext/postgres","label":"Postgres","kind":"external","churn":0,"sub":"Database - 19 tables"}],"edges":[{"from":"svc/support","to":"ext/postgres","kind":"writes","label":"answers, scores"},{"from":"svc/billing","to":"ext/stripe","kind":"calls","label":"charges on trial end"},{"from":"job/digest","to":"svc/support","kind":"triggers","label":"nightly evals"}]},"decisions":[],"blindSpots":[]}

Output ONLY the JSON object.
Works with Claude Code, Cursor, or any agent that can read your repo. It returns one JSON object — your source never leaves your machine, because the agent reads it there and sends back only the structure.
2 · Paste what it gives you back