From 8f21644221511059919f041c803fa70b696ee7b5 Mon Sep 17 00:00:00 2001 From: Sutu Sebastian Date: Mon, 20 Jul 2026 11:34:12 +0300 Subject: [PATCH 1/8] feat(docs): ship Blume public docs site at /codemap Add apps/docs (guides, recipes, concepts, reference + curated roadmap), TypeDoc API pipeline, CI/deploy workflows, and docs-voice agent skills. --- .agents/lessons.md | 4 + .agents/rules/docs-voice-priming.md | 14 + .agents/skills/docs-governance/LIFECYCLE.md | 17 + .agents/skills/docs-voice/SKILL.md | 115 + .agents/skills/product-tenets/SKILL.md | 47 + .agents/skills/update-docs/SKILL.md | 36 + .changeset/config.json | 2 +- .changeset/docs-site.md | 5 + .cursor/rules/docs-voice-priming.mdc | 1 + .cursor/skills/docs-voice | 1 + .cursor/skills/product-tenets | 1 + .cursor/skills/update-docs | 1 + .github/workflows/ci.yml | 42 + .github/workflows/deploy-docs.yml | 83 + AGENTS.md | 2 +- README.md | 306 +-- apps/docs/.gitignore | 10 + apps/docs/.oxfmtrc.json | 9 + apps/docs/blume.config.ts | 108 + apps/docs/components.ts | 12 + apps/docs/components/blume/Footer.astro | 168 ++ apps/docs/components/blume/Pagination.astro | 63 + apps/docs/components/curated-popular.ts | 16 + .../docs/content/concepts/index-lifecycle.mdx | 39 + apps/docs/content/concepts/index.mdx | 17 + apps/docs/content/concepts/meta.ts | 12 + .../docs/content/concepts/schema-overview.mdx | 59 + apps/docs/content/concepts/when-to-skip.mdx | 21 + apps/docs/content/concepts/why-codemap.mdx | 40 + apps/docs/content/guides/agents-mcp.mdx | 70 + apps/docs/content/guides/apply.mdx | 75 + apps/docs/content/guides/audit-baselines.mdx | 67 + apps/docs/content/guides/cli-overview.mdx | 102 + apps/docs/content/guides/config.mdx | 54 + apps/docs/content/guides/coverage-churn.mdx | 43 + apps/docs/content/guides/getting-started.mdx | 58 + apps/docs/content/guides/github-action.mdx | 95 + apps/docs/content/guides/index.mdx | 22 + apps/docs/content/guides/meta.ts | 17 + apps/docs/content/guides/programmatic.mdx | 48 + apps/docs/content/recipes/affected-tests.mdx | 37 + apps/docs/content/recipes/fan-in.mdx | 21 + .../recipes/find-symbol-definitions.mdx | 25 + apps/docs/content/recipes/index.mdx | 137 + apps/docs/content/recipes/meta.ts | 7 + apps/docs/content/reference/api/index.mdx | 41 + apps/docs/content/reference/api/meta.ts | 8 + apps/docs/content/reference/cli.mdx | 103 + apps/docs/content/reference/env.mdx | 22 + apps/docs/content/reference/formats.mdx | 30 + apps/docs/content/reference/index.mdx | 17 + apps/docs/content/reference/mcp.mdx | 78 + apps/docs/content/reference/meta.ts | 8 + apps/docs/content/reference/roadmap.mdx | 59 + apps/docs/package.json | 16 + apps/docs/pages/404.astro | 81 + apps/docs/pages/_home/Batteries.astro | 56 + apps/docs/pages/_home/FinalCta.astro | 43 + apps/docs/pages/_home/Hero.astro | 72 + apps/docs/pages/_home/HowItWorks.astro | 49 + apps/docs/pages/_home/InstallBox.astro | 31 + apps/docs/pages/_home/UseCases.astro | 59 + apps/docs/pages/_home/source-snippets.ts | 12 + apps/docs/pages/index.astro | 49 + apps/docs/public/.htaccess | 46 + apps/docs/public/apple-touch-icon.png | Bin 0 -> 3887 bytes apps/docs/public/favicon-96x96.png | Bin 0 -> 1961 bytes apps/docs/public/favicon.ico | Bin 0 -> 672 bytes apps/docs/public/favicon.svg | 9 + apps/docs/public/icon.svg | 9 + apps/docs/public/logo.svg | 21 + apps/docs/public/site.webmanifest | 22 + apps/docs/public/web-app-manifest-192x192.png | Bin 0 -> 4365 bytes apps/docs/public/web-app-manifest-512x512.png | Bin 0 -> 12452 bytes apps/docs/scripts/rewrite-api-links.ts | 571 ++++ apps/docs/theme.css | 45 + apps/docs/tsconfig.json | 12 + bun.lock | 2442 ++++++++++++++--- docs/README.md | 2 + docs/plans/docs-site.md | 230 ++ docs/plans/lsp-diagnostic-push.md | 4 +- docs/roadmap.md | 3 + lint-staged.config.js | 4 +- package.json | 47 +- src/adapters/types.ts | 2 +- src/api.ts | 2 +- src/config.ts | 6 +- typedoc.json | 85 + 88 files changed, 5843 insertions(+), 682 deletions(-) create mode 100644 .agents/rules/docs-voice-priming.md create mode 100644 .agents/skills/docs-voice/SKILL.md create mode 100644 .agents/skills/product-tenets/SKILL.md create mode 100644 .agents/skills/update-docs/SKILL.md create mode 100644 .changeset/docs-site.md create mode 120000 .cursor/rules/docs-voice-priming.mdc create mode 120000 .cursor/skills/docs-voice create mode 120000 .cursor/skills/product-tenets create mode 120000 .cursor/skills/update-docs create mode 100644 .github/workflows/deploy-docs.yml create mode 100644 apps/docs/.gitignore create mode 100644 apps/docs/.oxfmtrc.json create mode 100644 apps/docs/blume.config.ts create mode 100644 apps/docs/components.ts create mode 100644 apps/docs/components/blume/Footer.astro create mode 100644 apps/docs/components/blume/Pagination.astro create mode 100644 apps/docs/components/curated-popular.ts create mode 100644 apps/docs/content/concepts/index-lifecycle.mdx create mode 100644 apps/docs/content/concepts/index.mdx create mode 100644 apps/docs/content/concepts/meta.ts create mode 100644 apps/docs/content/concepts/schema-overview.mdx create mode 100644 apps/docs/content/concepts/when-to-skip.mdx create mode 100644 apps/docs/content/concepts/why-codemap.mdx create mode 100644 apps/docs/content/guides/agents-mcp.mdx create mode 100644 apps/docs/content/guides/apply.mdx create mode 100644 apps/docs/content/guides/audit-baselines.mdx create mode 100644 apps/docs/content/guides/cli-overview.mdx create mode 100644 apps/docs/content/guides/config.mdx create mode 100644 apps/docs/content/guides/coverage-churn.mdx create mode 100644 apps/docs/content/guides/getting-started.mdx create mode 100644 apps/docs/content/guides/github-action.mdx create mode 100644 apps/docs/content/guides/index.mdx create mode 100644 apps/docs/content/guides/meta.ts create mode 100644 apps/docs/content/guides/programmatic.mdx create mode 100644 apps/docs/content/recipes/affected-tests.mdx create mode 100644 apps/docs/content/recipes/fan-in.mdx create mode 100644 apps/docs/content/recipes/find-symbol-definitions.mdx create mode 100644 apps/docs/content/recipes/index.mdx create mode 100644 apps/docs/content/recipes/meta.ts create mode 100644 apps/docs/content/reference/api/index.mdx create mode 100644 apps/docs/content/reference/api/meta.ts create mode 100644 apps/docs/content/reference/cli.mdx create mode 100644 apps/docs/content/reference/env.mdx create mode 100644 apps/docs/content/reference/formats.mdx create mode 100644 apps/docs/content/reference/index.mdx create mode 100644 apps/docs/content/reference/mcp.mdx create mode 100644 apps/docs/content/reference/meta.ts create mode 100644 apps/docs/content/reference/roadmap.mdx create mode 100644 apps/docs/package.json create mode 100644 apps/docs/pages/404.astro create mode 100644 apps/docs/pages/_home/Batteries.astro create mode 100644 apps/docs/pages/_home/FinalCta.astro create mode 100644 apps/docs/pages/_home/Hero.astro create mode 100644 apps/docs/pages/_home/HowItWorks.astro create mode 100644 apps/docs/pages/_home/InstallBox.astro create mode 100644 apps/docs/pages/_home/UseCases.astro create mode 100644 apps/docs/pages/_home/source-snippets.ts create mode 100644 apps/docs/pages/index.astro create mode 100644 apps/docs/public/.htaccess create mode 100644 apps/docs/public/apple-touch-icon.png create mode 100644 apps/docs/public/favicon-96x96.png create mode 100644 apps/docs/public/favicon.ico create mode 100644 apps/docs/public/favicon.svg create mode 100644 apps/docs/public/icon.svg create mode 100644 apps/docs/public/logo.svg create mode 100644 apps/docs/public/site.webmanifest create mode 100644 apps/docs/public/web-app-manifest-192x192.png create mode 100644 apps/docs/public/web-app-manifest-512x512.png create mode 100644 apps/docs/scripts/rewrite-api-links.ts create mode 100644 apps/docs/theme.css create mode 100644 apps/docs/tsconfig.json create mode 100644 docs/plans/docs-site.md create mode 100644 typedoc.json diff --git a/.agents/lessons.md b/.agents/lessons.md index b8985a1a..e8c278e8 100644 --- a/.agents/lessons.md +++ b/.agents/lessons.md @@ -25,3 +25,7 @@ Persistent log of corrections and insights from past sessions. Read when relevan - **Never fabricate quantitative explanations to rationalize surprising data** — when a CI / perf / benchmark number is unexpected (e.g. went up after a "performance" PR), the failure mode is to invent a plausible-sounding cause without verification ("+8 doc files were added since the baseline"). This is intellectual dishonesty that compounds: the fabricated cause gets baked into PR bodies, commit messages, follow-up reasoning, and other agents inherit it as fact. **Pattern:** when a number surprises you, say "I don't know yet" and either (a) instrument / re-run to find the real cause, or (b) accept the unknown and surface it explicitly to the user. Verifiable claim formats: `git diff --name-status A..B | grep '^A'` for file-add counts, `gh run view --log` for CI numbers, repeated CI runs on the same commit for variance characterisation. **Never** invent a numeric explanation that "sounds right". Hit on PR #104 (perf-baseline refresh) — claimed "8 new doc files indexed since cc8daed" explaining a +71ms CI regression; actual delta was 1 file. User caught it; PR was closed. - **PR titles: no `SCHEMA N` / `SCHEMA_VERSION` suffix** — schema bumps belong in the PR body, changeset, and `db.ts`; putting `(SCHEMA 37)` in the title adds noise and duplicates what reviewers see in the diff. Title = what shipped (`feat(index): callback dispatch synthesis`), not the integer. - **Perf-baseline flakes are often GHA runner tiers, not code regressions** — `ubuntu-latest` jobs on the same commit can land on fast (~630 ms total) or slow (~1117 ms) runners; cross-job spread dwarfs the +25% gate. **Pattern:** compare pass vs fail CI logs on the same SHA before re-baselining or blaming a PR; capture baseline medians from slow-tier CI logs, use `CODEMAP_PERF_RUNS=5` in CI, and honour `CODEMAP_PERF_REGRESSION_PCT` env during compare (not just `--update`). Hit on main CI May 2026 — #136 merge blocked by `index_create_ms` +31.7% while `total_ms` was only +15%. +- **Workspaces need `"."` listed explicitly** — `workspaces: ["apps/*"]` alone drops the root package from changesets: Release fails with "changeset … which is not in the workspace". Always `workspaces: [".", "apps/*"]` from day one when adding `apps/docs`. +- **Blume `audit` skips `basePath`-relative paths** — with `deployment.base: "/codemap"`, the canonical-bad-target / non-canonical-in-sitemap / indexable-page-not-in-sitemap checks fire on paths that are correct under the subpath. Skip them: `blume audit --fail-on error --skip canonical_bad_target,non_canonical_in_sitemap,indexable_page_not_in_sitemap`. +- **Blume `audit` also skips `BLUME_AUDIT_LINK_TO_BROKEN` for github-releases changelog** — release-note bodies are immutable and link to maintainer `docs/` paths that aren't on the site. Stubs under `apps/docs/content/docs/` satisfy `validate --strict`; `audit` still flags residual `.md` links, so skip `BLUME_AUDIT_LINK_TO_BROKEN` globally. Trade-off: hand-authored broken links also go quiet — re-run `blume audit` without the skip when editing body prose. +- **Don't override root `zod` onto Blume with `"zod": "$zod"`** — forcing the workspace onto zod 4 breaks Blume's frontmatter schema (`config.frontmatter.extend` null). Pin `js-yaml` to `4.3.0` (not `>=4.1.2`) so Astro/Blume don't pull js-yaml v5 ESM breakage. Drop the `$zod` override when adding `apps/docs`; keep root `dependencies.zod` at 4.x for codemap itself. diff --git a/.agents/rules/docs-voice-priming.md b/.agents/rules/docs-voice-priming.md new file mode 100644 index 00000000..b024bc52 --- /dev/null +++ b/.agents/rules/docs-voice-priming.md @@ -0,0 +1,14 @@ +--- +description: Docs voice primer — read docs-voice skill before authoring apps/docs prose. +globs: + - "apps/docs/**" +alwaysApply: false +--- + +# Docs voice (priming) + +Before authoring or editing public docs prose, **read the [`docs-voice` skill](../skills/docs-voice/SKILL.md)**. + +Voice, peer framing (code-index / agent-context tools only — never store/adapter middlewares), card/header grammar, and anti-pitch live in the skill — not duplicated here. + +Product north-star: [`product-tenets`](../skills/product-tenets/SKILL.md). diff --git a/.agents/skills/docs-governance/LIFECYCLE.md b/.agents/skills/docs-governance/LIFECYCLE.md index dc5acf82..edf09200 100644 --- a/.agents/skills/docs-governance/LIFECYCLE.md +++ b/.agents/skills/docs-governance/LIFECYCLE.md @@ -225,3 +225,20 @@ Shipped agent templates under `templates/agent-content/**` follow the same consu | **Maintainer-only** | Never leak into served shards | Module paths under `src/`, CI wiring, dual-file sync, dogfood paths | When lifting durable policy from a closed plan or audit into agent-content, verify parity across CLI help, MCP tool descriptions, served shards, root README, and changeset bodies — not just one surface. + +--- + +## README surfaces (public site vs npm landing vs maintainer docs) + +Codemap has three reading surfaces with distinct jobs; never blur them. + +| Surface | Canonical home | Job | Deploy | +| ----------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------- | -------------------------------------------------- | +| **Public docs site** | `https://stainless-code.com/codemap` | Canonical user docs — install, guides, concepts, recipes, reference, generated API | FTP `/codemap` on merge of a **`docs`**-labeled PR | +| **Root `README.md``** (npm landing) | repo root | npm/repo landing digest only — install + one-query hook + pointer to the site | ships in the npm package | +| **Maintainer `docs/`** | `docs/` at repo root (Tier B) | Governance, architecture internals, plans, audits, research — never leaked to the site | tracked in-repo; not deployed | + +- **Site is canonical for user docs.** Root `README.md` summarizes and links; it does not restate guide/reference prose ([`docs/README.md` Rule 1](../../../docs/README.md)). +- **`docs` label deploys.** A PR merged with the **`docs`** label triggers `deploy-docs.yml` → FTP to `/codemap`. Releases and `workflow_dispatch` also deploy. +- **Maintainer `docs/` stays separate.** Curated lifts to the site only; never dump `docs/*.md` wholesale into `apps/docs/` ([`docs/README.md` Rule 1](../../../docs/README.md)). +- **Docs-only changeset = `patch`** (pre-1.0; schema-breaking is the only `minor` trigger — see [`.agents/lessons.md`](../../lessons.md)). diff --git a/.agents/skills/docs-voice/SKILL.md b/.agents/skills/docs-voice/SKILL.md new file mode 100644 index 00000000..d02f4f8f --- /dev/null +++ b/.agents/skills/docs-voice/SKILL.md @@ -0,0 +1,115 @@ +--- +name: docs-voice +description: Voice, tone, and format for the public Codemap docs (`apps/docs`, built with Blume). Use when authoring or editing apps/docs prose — landing, guides, concepts, recipes, reference, generated API — or deciding headline grammar, benefit framing, peer framing, or anti-pitch wording. +--- + +# Docs voice — Codemap docs (`apps/docs`, built with Blume) + +Keep landing, guides, concepts, recipes, reference, and generated API reading like one voice. + +## Voice in one line + +Senior-dev to senior-dev: concrete, SQL-literate, dry, honest about scope. No +hype. The differentiators are radical honesty (say what's planned / diverges / +was rejected) and the "when **not** to use it" anti-pitch — keep both. + +## Do + +- **Lead with the pain, then the mechanism.** "Agents burn tokens scanning files + to find one symbol…" → then "`codemap query --json` returns the row in one SQL + round-trip." +- **Concrete before abstract.** Name `codemap query` / `--recipe` / `createCodemap` + / `defineConfig` before the coinage "predicate-as-API" or "structural index." +- **CLI-first AND programmatic.** Show the CLI shape first; pair with the library + shape (`createCodemap`, `defineConfig`, adapters) when the page is API-shaped. + The published package entry is the SSOT for generated `/reference/api` (TypeDoc). +- **SQL is the API.** When a page answers a structural question, show the SQL or + the `--recipe` — not a paragraph of prose pretending to be the answer. Recipes + are named SQL patterns; cite the recipe id. +- **Section headers by page type.** Marketing = period-terminated benefit + sentence ("Query your codebase."); guides = action verb ("Find a symbol with + one query"); reference = precise noun; concepts = model noun + consequence. +- **Card titles = the outcome; card bodies = the API / SQL.** +- **One idea per sentence in leads.** Short claim first, then expand. +- **State experimental / pre-1.0 status once per surface, one wording** (see + Canonical patterns). +- **Sidebar icons: all-or-none per sibling list.** Blume does not reserve an + icon column — sparse `sidebar.icon` jaggeds labels. Guides, Concepts, + Recipes, Reference leaves: none unless every peer has a natural glyph. + Section `meta.ts` icons and tab icons stay. +- **Peer framing is structural, not brand-vs-brand.** When comparing, contrast + axes (query API, semantic layer, extraction depth, CI substrate) — see + [`docs/why-codemap.md`](../../../docs/why-codemap.md) § Codemap vs alternatives. + Do not clone peer design in prose; reach for the underlying spec + ([`plan-pr-inspiration-discipline`](../../rules/plan-pr-inspiration-discipline.md)). + +## Don't + +- Don't open a page with a 60+ word sentence. +- Don't restate the frontmatter `description` in the first body sentence — the + docs site renders `description` as the page subtitle, so an echoing opener + duplicates content. Open with a concrete scenario/pain instead. +- Don't title cards with bare feature nouns ("Fan-in") when the outcome is the + hook ("Find what depends on a file in one query"). +- Don't manufacture social proof, download counts, "trusted by", or maturity + adjectives ("production-grade", "battle-tested", "world-class") at pre-1.0 — + live queries, source, the changelog, and the benchmark are the proof. +- Don't claim Codemap owns semantic search, refactoring, or editor ergonomics — + peers (LSP, embeddings, verdict linters) own those slots; Codemap owns + structural facts + predicate-as-API. Say when to reach for something else. +- Don't hype ("blazing-fast", "revolutionary", "AI-powered"). Indexed queries + are sub-ms; let the number and the benchmark carry it. +- Don't treat store/adapter middlewares as competitors — different problem + space. Codemap's peers are code-index / agent-context tools; the contrast is + structural-SQL + recipes vs pre-baked graph verbs / embeddings. +- Don't invent Lucide icons for prose nav leaves to "fill out" a section — + strip to none instead of decorating half the list. +- Don't paste maintainer internals (`src/` module names, CI wiring, dual-file + sync, dogfood paths) into public pages — see + [`consumer-surfaces`](../../rules/consumer-surfaces.md). + +## Canonical patterns (use verbatim) + +- **Experimental disclaimer** (banner / pill / callout / stability page): + "Experimental — the API may change between minor releases. Pin your version." +- **Pre-1.0 semver:** breaking changes are expected and ship in **minor + releases** (`0.x` → `0.y`), **not majors**. Schema-breaking changes that force + a `.codemap/index.db` rebuild are the trigger for `minor`; everything else + (additive CLI, public types, docs) is `patch`. +- **Brand one-liner** (memorable beat, not hype): "Query your codebase." +- **Category label** (what it is — pair with the brand beat, then the + mechanism): "local codebase intelligence" / "codebase intelligence tool". + Same breath as SQLite / SQL / recipes — never as a standalone slogan. +- **Public site URL:** `https://stainless-code.com/codemap` (canonical user + docs). Root `README.md` is the npm landing digest; maintainer `docs/` is + separate. +- **Peer set:** other codebase intelligence / code-index / agent-context tools + — static-analysis linters (knip / ts-prune / jscpd / ESLint), Aider RepoMap, + LSP servers, and the SQLite-backed cohort (srclight, ctxpp, KotaDB, …). Not + store/adapter middlewares. +- **Anti-pitch source of truth:** [`docs/why-codemap.md`](../../../docs/why-codemap.md) + § When to reach for something else — link, don't restate. + +## Product tenets + +Decisions and messaging should align with [`product-tenets`](../product-tenets/SKILL.md). + +## Verify + +`content/**` MDX is excluded from oxfmt (nested `.oxfmtrc.json` ignores +`content/**` — the `:::` directive collapse bug); `.astro` is not oxfmt-managed. +Build green before commit ([`verify-after-each-step`](../../rules/verify-after-each-step.md)): + +```bash +bun run docs:validate -- --strict && bun run docs:check -- --isolated && bun run docs:build && bun run docs:audit +``` + +Scheduled drift sync: [`update-docs`](../update-docs/SKILL.md). + +## Reference + +- Priming: [`docs-voice-priming`](../../rules/docs-voice-priming.md) +- Tenets: [`product-tenets`](../product-tenets/SKILL.md) +- Lifecycle / README surfaces: [`docs-governance`](../docs-governance/SKILL.md) +- Anti-pitch + peer framing: [`docs/why-codemap.md`](../../../docs/why-codemap.md) +- Consumer-vs-maintainer split: [`consumer-surfaces`](../../rules/consumer-surfaces.md) diff --git a/.agents/skills/product-tenets/SKILL.md b/.agents/skills/product-tenets/SKILL.md new file mode 100644 index 00000000..1239bd79 --- /dev/null +++ b/.agents/skills/product-tenets/SKILL.md @@ -0,0 +1,47 @@ +--- +name: product-tenets +description: The product north-star — four Codemap tenets (structural over semantic, predicate-as-API, local-first / agent-native surfaces, honest scope). Use when making a design, API, or architecture decision, evaluating a trade-off, justifying a feature, or writing/reviewing a docs/plans entry. +--- + +# Product tenets (north-star) + +These four tenets are the design north-star for `@stainless-code/codemap`; reach for them whenever a decision needs justifying. Codemap is a local codebase intelligence tool: a deterministic, AST-backed SQLite index of structural facts that an agent queries with SQL instead of scanning files — the tenets fall out of that thesis. + +## 1. Structural over semantic + +The index carries facts the AST and resolver can prove: symbols, imports, exports, components, calls, dependencies, CSS tokens, markers, scopes, bindings. No embeddings, no LLM-in-the-box, no relevance verdict the tool invented. The agent decides relevance; Codemap answers. + +- Rules out: embedding search as a core surface; "smart" context ranking baked into the index; verdicts dressed as facts. +- Codemap shape: `symbols` / `dependencies` / `references` / `coverage` tables; opt-in FTS5 (`--with-fts`) for body search that JOINs with structure — never the foundation. + +## 2. Predicate-as-API (SQL + recipes) + +SQL is the API. Every structural question is a `SELECT`; every repeated pattern is a named recipe (`codemap query --recipe`). Verdicts (SARIF, annotations, exit codes) are an **output mode** of recipes, never a primitive — `codemap apply` executes diff rows you provide, it doesn't invent fixes. + +- Rules out: pre-baked graph verbs that hide the query; magic "find dead code" buttons with no SQL behind them; severity engines that can't be recomposed. +- Codemap shape: `query --json` / `--print-sql` / `--recipe` / `--recipes-json`; `apply` / `apply_rows` / `apply_diff_input` over explicit rows; recipes compose (`untested-and-dead`, `boundary-violations`, `churn-complexity-hotspots`, …). + +## 3. Local-first, agent-native surfaces + +A small SQLite file on disk (`.codemap/index.db`), queried through whatever surface the agent host speaks: CLI, MCP, HTTP. No daemon required to answer; no remote service in the path. The same recipes run in a terminal, an MCP tool, a `codemap serve` route, or a GitHub Action. + +- Rules out: cloud-only indexes; mandatory long-running daemons; surfaces that only work inside one editor. +- Codemap shape: `codemap` CLI verbs; MCP tools (`query`, `show`, `impact`, `trace`, `affected`, `apply`, …); HTTP `codemap serve`; GitHub Action for CI gates; `codemap agents init` wires the surface the consumer's PM prefers. + +## 4. Honest scope (anti-pitch) + +Say what Codemap does **not** do, on the same page that sells it. Whole-file semantic understanding, editor-time refactoring, verdict-shaped linting, and NL Q&A over the repo are someone else's slot — link to them. Non-goals are a product floor, not a backlog in disguise. + +- Rules out: scope creep into embeddings / LSP-shim / verdict engine / one-shot daemon; marketing that hides the seams. +- Codemap shape: [`docs/why-codemap.md`](../../../docs/why-codemap.md) § When to reach for something else; [`roadmap.md § Non-goals (v1)`](../../../docs/roadmap.md) as a durable floor; pre-1.0 semver honesty (breaks ship in minors; schema bumps earn the `minor`). + +## Using the tenets + +When a proposal conflicts with a tenet, explicitly address why and how the conflict is justified (a `docs/plans/` entry for new surface, inline for a line-level change). Maintainers use these as a PR checklist. Peer-tool design is **not** a tenet — reach for the underlying spec, not a rival's implementation ([`plan-pr-inspiration-discipline`](../../rules/plan-pr-inspiration-discipline.md)). + +## Reference + +- [`architecture-priming`](../../rules/architecture-priming.md) — STOP signals for structurally significant changes. +- [`improve-codebase-architecture`](../improve-codebase-architecture/SKILL.md) · [`docs/architecture.md`](../../../docs/architecture.md) +- [`docs-voice`](../docs-voice/SKILL.md) — public docs tone + peer framing (Canonical patterns). +- [`plan-pr-inspiration-discipline`](../../rules/plan-pr-inspiration-discipline.md) — cite specs, not peer implementations. diff --git a/.agents/skills/update-docs/SKILL.md b/.agents/skills/update-docs/SKILL.md new file mode 100644 index 00000000..228c5b2c --- /dev/null +++ b/.agents/skills/update-docs/SKILL.md @@ -0,0 +1,36 @@ +--- +name: update-docs +description: Keep apps/docs in sync with merged product changes. On each run, audit recently merged PRs against docs content, update only drifted pages, regenerate API MDX when public exports/JSDoc drifted, verify with blume validate/check/build/audit, and open or update a docs/* PR — or report a clean no-op. +--- + +# Update docs — sync apps/docs with merged PRs + +Upstream workflow: [`npx skills add haydenbleasel/blume --skill blume-update-docs`](https://github.com/haydenbleasel/blume). This local skill encodes it for scheduled agents in this repo. + +## When to use + +- **Scheduled** — weekly (or similar) run to catch docs drift from merged PRs. +- **On demand** — after a batch of merged PRs that may have changed public API surfaces, recipes, schema, or Blume config. + +## Workflow + +1. **Collect merged PRs** in the lookback window (default **7 days**): `git log --since="7 days ago" --merges --first-parent` and `gh pr list --state merged --search "merged:>$DATE"`. _Done: every merged PR in the window listed with title, number, and surfaces touched._ +2. **Drop feature-flagged work** — skip PRs/commits touching flag-gated code; never document unreleased surfaces. _Done: flag-gated PRs removed from the list._ +3. **Map changed surfaces to docs pages** — trace diffs in `src/cli/`, `src/application/`, `src/adapters/`, `src/db.ts` (`createTables()` / `SCHEMA_VERSION`), `package.json` `exports`, `blume.config.ts` / `apps/docs/**`, `templates/recipes/*.{sql,md}`, `templates/agent-content/**`, and TypeDoc-facing JSDoc to the pages that document them (`content/reference/api/**` generated, `content/reference/**` hand, `content/guides/**`, `content/recipes/**`, `content/concepts/**`, plus homepage `_home/**` when behavior framing changed). Regenerate API MDX via `bun run docs:api` when public exports/JSDoc drifted. _Done: every changed public surface mapped to zero or more docs pages._ +4. **Edit only drifted facts** — signatures, option tables, recipe ids, schema columns, behavior descriptions, entry-point peers. Use [`docs-voice`](../docs-voice/SKILL.md); do not rewrite stable prose. Peer framing stays code-index / agent-context tools only — never store/adapter middlewares. _Done: every drifted fact updated; no stable prose touched._ +5. **Verify** — `bun run docs:validate -- --strict && bun run docs:check -- --isolated && bun run docs:build && bun run docs:audit` (run from `apps/docs/` or via root `docs:*` scripts); fix until green. **Do not commit if any fail.** Per [`verify-after-each-step`](../../rules/verify-after-each-step.md). _Done: all four green._ +6. **Open or update a PR** on branch `docs/sync-` with a summary of what drifted and the fixes. Label it **`docs`** so merge deploys `/codemap` via FTP ([`docs-governance/LIFECYCLE.md`](../docs-governance/LIFECYCLE.md) § README surfaces). Follow commit/PR conventions; never `--no-verify` ([`no-bypass-hooks`](../../rules/no-bypass-hooks.md)). Changeset for a docs-only sync is **`patch`** (pre-1.0; schema-breaking is the only `minor` trigger). _Done: PR open with `docs` label and drift summary, or step 7 applies._ +7. **Clean no-op** — if nothing drifted, report the PRs checked and surfaces audited; **do not open a PR.** _Done: report lists every PR checked and every surface audited._ + +## Boundaries + +- **Only `apps/docs/`** (+ root scripts/config the docs app requires, e.g. `typedoc.json` when regenerating API) — never edit maintainer `docs/` plans/research/audits in a sync PR; never edit library `src/` in a docs-sync PR. +- **Minimal diffs** — drifted facts only; no cosmetic rewrites, unrelated refactors, or removing source comments in touched files ([`authoring-discipline`](../../rules/authoring-discipline.md)). +- **No PR on a clean no-op; no commit on a failing build.** + +## Reference + +- Verify loop: [`verify-after-each-step`](../../rules/verify-after-each-step.md) · [`harden-pr`](../harden-pr/SKILL.md) (lite before commit, full before merge) +- Authoring: [`authoring-discipline`](../../rules/authoring-discipline.md) +- Voice/tone/format for the public site: [`docs-voice`](../docs-voice/SKILL.md) +- Docs site scope + deploy label: [`docs-governance`](../docs-governance/SKILL.md) (governs `docs/` + `apps/docs/` README surfaces; this skill governs `apps/docs/` sync only) diff --git a/.changeset/config.json b/.changeset/config.json index 75684d4b..e942d6a9 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -10,5 +10,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": [] + "ignore": ["@stainless-code/codemap-docs"] } diff --git a/.changeset/docs-site.md b/.changeset/docs-site.md new file mode 100644 index 00000000..da5d968e --- /dev/null +++ b/.changeset/docs-site.md @@ -0,0 +1,5 @@ +--- +"@stainless-code/codemap": patch +--- + +Add public docs site at https://stainless-code.com/codemap (Blume + TypeDoc API reference). diff --git a/.cursor/rules/docs-voice-priming.mdc b/.cursor/rules/docs-voice-priming.mdc new file mode 120000 index 00000000..e1a7f65a --- /dev/null +++ b/.cursor/rules/docs-voice-priming.mdc @@ -0,0 +1 @@ +../../.agents/rules/docs-voice-priming.md \ No newline at end of file diff --git a/.cursor/skills/docs-voice b/.cursor/skills/docs-voice new file mode 120000 index 00000000..a5a7397c --- /dev/null +++ b/.cursor/skills/docs-voice @@ -0,0 +1 @@ +../../.agents/skills/docs-voice \ No newline at end of file diff --git a/.cursor/skills/product-tenets b/.cursor/skills/product-tenets new file mode 120000 index 00000000..07b8f76a --- /dev/null +++ b/.cursor/skills/product-tenets @@ -0,0 +1 @@ +../../.agents/skills/product-tenets \ No newline at end of file diff --git a/.cursor/skills/update-docs b/.cursor/skills/update-docs new file mode 120000 index 00000000..74594110 --- /dev/null +++ b/.cursor/skills/update-docs @@ -0,0 +1 @@ +../../.agents/skills/update-docs \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d66f36e..4ad3be40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,6 +193,46 @@ jobs: bun run dev --full bun run benchmark + docs: + name: 📖 Docs site + needs: skip-ci + if: needs['skip-ci'].outputs.skip != 'true' + runs-on: ubuntu-latest + # Token for github-releases changelog — avoids offline changelog failures under --strict. + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + persist-credentials: false + # Sitemap lastmod uses `git log` per file. + fetch-depth: 0 + + - name: Setup + uses: ./.github/actions/setup + + # Lib dist — cheap; keep for parity / future islands that resolve package entrypoints. + - name: Build + run: bun run build + + - name: Generate API reference (Markdown) + run: bun run docs:api + + # Site content graph. No --external (offline). + - name: Validate docs links + run: bun run docs:validate -- --strict + + - name: Typecheck docs site + run: bun run docs:check -- --isolated + + - name: Build docs site + run: bun run docs:build + + # Post-build; skips live in apps/docs `audit` script (+ lessons). + - name: Audit docs site + run: bun run docs:audit + audit: # `bun audit` exits 0 regardless of severity — the scan below blocks on high/critical. # Transitive-dep CVE visibility; advisory-API outage doesn't block. @@ -262,6 +302,7 @@ jobs: test, build, check-pack, + docs, audit, benchmark, ] @@ -277,6 +318,7 @@ jobs: needs.test.result != 'success' || needs.build.result != 'success' || needs['check-pack'].result != 'success' || + needs.docs.result != 'success' || needs.audit.result != 'success' || needs.benchmark.result != 'success' ) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 00000000..22395302 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,83 @@ +name: Deploy docs + +# Unversioned /codemap FTP. `docs` label = deploy on merge without waiting for a package release. +on: + workflow_dispatch: + release: + types: [published] + pull_request: + types: [closed] + branches: [main] + +permissions: + contents: read + +# Single FTP root — don't overlap uploads. +concurrency: + group: deploy-docs-production + cancel-in-progress: false + +jobs: + deploy: + name: 🚀 Build & Deploy docs (FTP) + if: > + github.event_name == 'workflow_dispatch' || + github.event_name == 'release' || + (github.event_name == 'pull_request' && + github.event.pull_request.merged == true && + contains(github.event.pull_request.labels.*.name, 'docs')) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + persist-credentials: false + # Closed PR checkout defaults to a dead merge ref — pin the merge commit on main. + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.merge_commit_sha || github.sha }} + # Sitemap lastmod uses `git log` per file. + fetch-depth: 0 + + - name: Setup Bun + uses: ./.github/actions/setup + + # Lib dist — cheap; keep for parity / future islands that resolve package entrypoints. + - name: Build + run: bun run build + + - name: Generate API reference (Markdown) + run: bun run docs:api + + # Same gates as CI `docs` — workflow_dispatch must not FTP an unaudited tree. + - name: Validate docs links + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bun run docs:validate -- --strict + + - name: Typecheck docs site + run: bun run docs:check -- --isolated + + - name: Build docs site + env: + # Changelog github-releases source + avoid unauthenticated API rate limits. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bun run docs:build + + - name: Audit docs site + run: bun run docs:audit + + # FTP account root is already /codemap — server-dir ./ is correct (not ./codemap/). + - name: Upload to /codemap via FTP + uses: SamKirkland/FTP-Deploy-Action@v4.4.0 + with: + server: ${{ secrets.FTP_HOST }} + username: ${{ secrets.FTP_USERNAME }} + password: ${{ secrets.FTP_PASSWORD }} + protocol: ftps + port: 21 + security: strict + local-dir: ./apps/docs/dist/ + server-dir: ./ + exclude: | + **/.git* + **/.git*/** + **/node_modules/** diff --git a/AGENTS.md b/AGENTS.md index d98e3b16..3c128768 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,6 +18,6 @@ Canonical read order: [`.agents/rules/agents-first-convention.md`](.agents/rules | PR comments | [`.agents/rules/pr-comment-fact-check.md`](.agents/rules/pr-comment-fact-check.md) | | Plan-PR inspiration | [`.agents/rules/plan-pr-inspiration-discipline.md`](.agents/rules/plan-pr-inspiration-discipline.md) | -Intent (not always-on): `agents-tier-system`, `ask-agents`, `audit-pr-architecture`, `authoring-discipline`, `codemap`, `diagnosing-bugs`, `docs-governance`, `docs-lifecycle-sweep`, `domain-modeling`, `grill-me`, `grilling`, `grill-with-docs`, `harden-pr`, `improve-codebase-architecture`, `pr-comment-fact-check`, `tdd`, `teach`, `tracer-bullets`, `verify-after-each-step`, `writing-agents-config`, `writing-great-skills`. +Intent (not always-on): `agents-tier-system`, `ask-agents`, `audit-pr-architecture`, `authoring-discipline`, `codemap`, `diagnosing-bugs`, `docs-governance`, `docs-lifecycle-sweep`, `docs-voice`, `domain-modeling`, `grill-me`, `grilling`, `grill-with-docs`, `harden-pr`, `improve-codebase-architecture`, `pr-comment-fact-check`, `product-tenets`, `tdd`, `teach`, `tracer-bullets`, `update-docs`, `verify-after-each-step`, `writing-agents-config`, `writing-great-skills`. Human Day-1: [README](README.md) Getting Started · [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md). diff --git a/README.md b/README.md index 8ef5a253..6c26c752 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,17 @@ # Codemap -**Query your codebase.** Codemap builds a **local SQLite index** of structural metadata (symbols, imports, exports, components, dependencies, CSS tokens, markers, and more) so **AI agents and tools** can answer “where / what / who” questions with **SQL** instead of scanning the whole tree. +**Query your codebase.** Local codebase intelligence for AI agents — a SQLite index of structural metadata (symbols, imports, exports, components, dependencies, CSS tokens, markers, and more) so agents and tools answer “where / what / who” with **SQL** instead of scanning the tree. -- **Not** grep semantics by default — use `ripgrep` / your IDE for raw text matches. Codemap ships **opt-in FTS5** (`--with-fts` / `fts5: true`) when you want body matches that JOIN with `symbols` / `coverage` / `markers` in one SQL. -- **Is** a fast, token-efficient way to navigate **structure**: definitions, imports, dependency direction, components, and other extracted facts. +- **Not** grep by default — use ripgrep / your IDE for raw text. Opt-in FTS5 (`--with-fts` / `fts5: true`) when body matches need to JOIN with structure. +- **Is** a fast, token-efficient way to navigate **structure**. -**Documentation:** [docs/README.md](docs/README.md) is the hub (topic index + single-source rules). Topics: [architecture](docs/architecture.md), [agents](docs/agents.md) (`codemap agents init`), [benchmark](docs/benchmark.md), [golden queries](docs/golden-queries.md), [packaging](docs/packaging.md), [roadmap](docs/roadmap.md), [why Codemap](docs/why-codemap.md). **Bundled rules/skills:** [`.agents/rules/`](.agents/rules/), [`.agents/skills/codemap/SKILL.md`](.agents/skills/codemap/SKILL.md). **Consumers:** [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md). +**Docs:** [https://stainless-code.com/codemap](https://stainless-code.com/codemap) --- ## What you get -Structural questions answered in **one SQL round-trip** instead of 3–5 file reads: - -| Question | Grep / Read (today) | Codemap | -| -------------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | -| Find a symbol by exact name | Glob + Read + filter by hand | `SELECT name, file_path, line_start FROM symbols WHERE name = 'X'` | -| Who imports `~/utils/date`? | Grep + resolve `tsconfig` aliases manually | `SELECT DISTINCT from_path FROM dependencies WHERE to_path LIKE '%utils/date%'` | -| Components using the `useQuery` hook | Grep `useQuery` + filter to component files | `SELECT name, file_path FROM components WHERE hooks_used LIKE '%useQuery%'` | -| Heaviest files by import fan-out | Impractical without a parser | `SELECT from_path, COUNT(*) AS n FROM dependencies GROUP BY from_path ORDER BY n DESC` | -| All CSS keyframes / design tokens / module classes | Grep `@keyframes`, `--var-`, `.module.css` then disambiguate | One `SELECT` against `css_keyframes` / `css_variables` / `css_classes` | -| Deprecated symbols (`@deprecated` JSDoc) | Grep `@deprecated` + cross-reference symbol | `SELECT name, kind FROM symbols WHERE doc_comment LIKE '%@deprecated%'` | - -Full schema and recipe catalog: [docs/architecture.md § Schema](docs/architecture.md#schema) · [docs/why-codemap.md](docs/why-codemap.md) · `codemap query --recipes-json`. +Structural questions in **one SQL round-trip** instead of 3–5 file reads — symbol definitions, import direction, components, CSS tokens, `@deprecated` symbols, and more. Named patterns ship as recipes (`codemap query --recipe …`); full catalog and schema live in the docs. --- @@ -33,249 +22,21 @@ bun add @stainless-code/codemap # or: npm install @stainless-code/codemap ``` -**Engines:** Node **`^20.19.0 || >=22.12.0`** and/or Bun **`>=1.0.0`** — see `package.json` and [docs/packaging.md](docs/packaging.md). +**Engines:** Node **`^20.19.0 || >=22.12.0`** and/or Bun **`>=1.0.31`**. --- ## CLI -- **Installed package:** `codemap`, `bunx @stainless-code/codemap`, or `node node_modules/@stainless-code/codemap/dist/index.mjs` -- **This repo (dev):** `bun src/index.ts` (same flags) - -### Daily commands - ```bash -codemap # incremental index (run once per session) -codemap dead-code --json # outcome alias → query --recipe untested-and-dead -codemap query --json --recipe fan-out # recipe SQL by id (alias: -r) -codemap query --json "SELECT name, file_path FROM symbols WHERE name = 'foo'" # ad-hoc SQL -codemap --files src/a.ts src/b.tsx # targeted re-index after edits -codemap validate --json # detect stale / missing / unindexed / rejected files -codemap context --compact --for "refactor auth" # JSON envelope + intent-matched recipes -codemap ingest-coverage coverage/coverage-final.json --json # Istanbul / LCOV (auto-detected) → coverage table; joins with symbols -NODE_V8_COVERAGE=.cov bun test && codemap ingest-coverage .cov --runtime --json # V8 protocol (per-process dumps); local-only -codemap ingest-churn metrics/churn.json --json # precomputed file_churn → churn-complexity-hotspots (non-git / CI) -codemap query --json --recipe churn-complexity-hotspots # change-frequency × complexity (not the hotspots alias) -codemap agents init # scaffold .agents/ rules + skills -codemap agents init --mcp # PM-aware project MCP config (see docs/agents.md) -codemap apply rename-preview --params old=foo,new=bar --dry-run # preview recipe-driven edits (substrate executor) +codemap # incremental index +codemap query --json --recipe find-symbol-definitions --params name=foo +codemap query --json "SELECT name, file_path FROM symbols WHERE name = 'foo'" +codemap show foo +codemap agents init --mcp # agent templates + MCP ``` -**Version-matched agent guidance:** `codemap agents init` writes **thin pointer files** to `.agents/` (short SKILL + rule). The full content is served live by **`codemap skill`** / **`codemap rule`** (CLI) and **`codemap://skill`** / **`codemap://rule`** (MCP / HTTP) — so `bun update @stainless-code/codemap` auto-refreshes the content agents see, no re-init needed. See [docs/agents.md](docs/agents.md). - -### Full reference - -```bash -# Index project root (optional /config.{ts,js,json}; --state-dir overrides .codemap/) -codemap - -# Version (also: codemap --version, codemap -V) -codemap version - -# Full rebuild -codemap --full - -# SQL against the index (after at least one index run). Bundled agent rules/skills use --json first; omit it for console.table in a terminal. -codemap query --json "SELECT name, file_path FROM symbols LIMIT 10" -# With --json: JSON array on success; {"error":"..."} on stdout for bad SQL, DB open, or query bootstrap (config/resolver) -codemap query "SELECT name, file_path FROM symbols LIMIT 10" -# Query is not row-capped — add LIMIT in SQL for large selects -# Bundled SQL (same as skill examples): fan-out rankings -codemap query --json --recipe fan-out -codemap query --json --recipe fan-out-sample -# Outcome aliases — thin wrappers over `query --recipe `; every query flag passes through. -# Capped at 5 to avoid alias-sprawl. -codemap dead-code --json # → query --recipe untested-and-dead -codemap deprecated --ci # → query --recipe deprecated-symbols --ci -codemap boundaries --format sarif > boundary-findings.sarif # → query --recipe boundary-violations --format sarif -codemap hotspots --json --group-by directory # → query --recipe fan-in (import hubs — not churn×complexity) -codemap coverage-gaps --json --summary # → query --recipe worst-covered-exports --json --summary -# Parametrised recipes validate params from .md frontmatter before SQL binding. -codemap query --json --recipe find-symbol-by-kind --params kind=function,name_pattern=%Query% -codemap query --recipe rename-preview --params old=usePermissions,new=useAccess,kind=function --format diff -# Architecture-boundary rules (declare in .codemap/config.ts): -# boundaries: [{ name: "ui-cant-touch-server", from_glob: "src/ui/**", to_glob: "src/server/**" }] -# Default action is "deny"; the table is reconciled from config on every index pass. -codemap query --recipe boundary-violations --format sarif > boundary-findings.sarif -# Counts only (skip the rows) — pairs well with --recipe for dashboards / agent context windows -codemap query --json --summary -r deprecated-symbols -# PR-scoped: filter result rows to those touching files changed since -codemap query --json --changed-since origin/main -r fan-out -codemap query --json --summary --changed-since HEAD~5 "SELECT file_path FROM symbols" -# Group rows by directory, CODEOWNERS owner, or workspace package -codemap query --json --summary --group-by directory -r fan-in -codemap query --json --group-by owner -r deprecated-symbols -codemap query --json --summary --group-by package "SELECT file_path FROM symbols" -# Snapshot a result, refactor, then diff (saved inside .codemap/index.db, no JSON files) -codemap query --save-baseline -r visibility-tags # save under name "visibility-tags" -codemap query --json --baseline -r visibility-tags # full diff: {baseline, current_row_count, added, removed} -codemap query --json --summary --baseline -r visibility-tags # counts only: {baseline, current_row_count, added: N, removed: N} -codemap query --save-baseline=pre-refactor "SELECT file_path FROM symbols" # ad-hoc SQL needs an explicit = -codemap query --baseline=pre-refactor "SELECT file_path FROM symbols" -codemap query --baselines # list saved baselines -codemap query --drop-baseline visibility-tags # delete -# --group-by is mutually exclusive with --save-baseline / --baseline (different output shapes) -# Diff per-delta baselines vs current — files / dependencies / deprecated drift in one envelope -codemap query --save-baseline=base-files "SELECT path FROM files" -codemap query --save-baseline=base-dependencies "SELECT from_path, to_path FROM dependencies" -codemap query --save-baseline=base-deprecated -r deprecated-symbols -codemap audit --baseline base # auto-resolves base-{files,dependencies,deprecated} -codemap audit --json --summary --baseline base # counts-only — useful for CI dashboards -codemap audit --files-baseline base-files # explicit per-delta — runs only the slots provided -codemap audit --baseline base --files-baseline hotfix-files # mixed — auto-resolve deps + deprecated; override files -codemap audit --baseline base --no-index # skip the auto-incremental-index prelude (frozen-DB CI) -codemap audit --base origin/main --json # ad-hoc — added[].attribution; --summary adds added_introduced/inherited -codemap audit --base origin/main --format sarif # emit SARIF 2.1.0 directly (Code Scanning); also: --ci alias -codemap audit --base origin/main --ci # CI shortcut: --format sarif + non-zero exit on additions -codemap audit --base v1.0.0 --files-baseline pre-release-files # mix --base with per-delta override -# --base materialises via `git archive | tar -x` to .codemap/audit-cache//, reindexes into -# a cached `.codemap/index.db` at that sha, then diffs. Cache hit on second run against same sha is sub-100ms. Requires git; -# non-git projects get a clean `codemap audit: --base requires a git repository.` error. -# Recipes that define per-row action templates append "actions" hints (kebab-case verb + -# description) in --json output; ad-hoc SQL never carries actions. Inspect via --recipes-json. -# --format — SARIF for GitHub -# Code Scanning; annotations for GH Actions ::notice lines; codeclimate for GitLab Code Quality; -# badge for issue-count summaries; mermaid/diff for graph and edit previews. All -# formatted outputs require a flat row list -# (no --summary / --group-by / baseline). SARIF / annotations / codeclimate / badge -# auto-detect file_path / path / to_path / from_path; rule.id is codemap. -# (or codemap.adhoc). codeclimate/badge skip aggregate-only rows. Mermaid -# requires {from, to, label?, kind?} rows and rejects unbounded inputs (>50 edges) with a -# scope-suggestion error — alias columns via SELECT col AS "from", col2 AS "to". -codemap query --recipe deprecated-symbols --format sarif > findings.sarif -codemap query --recipe deprecated-symbols --ci # CI shortcut: --format sarif + non-zero exit + quiet -codemap query --recipe deprecated-symbols --format annotations # one ::notice per row -# GitLab Code Quality artifact (locatable rows only; flat minor severity): -codemap query --recipe boundary-violations --format codeclimate > gl-code-quality-report.json -# Badge summary for README paste or CI (counts locatable rows only): -codemap query --recipe boundary-violations --format badge -codemap query --recipe boundary-violations --format badge --badge-style json | jq -e '.status == "pass"' -# Render any audit/SARIF output as a markdown PR-summary comment (for repos without -# Code Scanning / aggregate audit deltas / bot-context seeding): -codemap audit --base origin/main --json | codemap pr-comment - | gh pr comment -F - -codemap query --format mermaid 'SELECT from_path AS "from", to_path AS "to" FROM dependencies LIMIT 50' -codemap query --format diff 'SELECT "README.md" AS file_path, 1 AS line_start, "# Codemap" AS before_pattern, "# Codemap Preview" AS after_pattern' -codemap query --format diff-json 'SELECT "README.md" AS file_path, 1 AS line_start, "# Codemap" AS before_pattern, "# Codemap Preview" AS after_pattern' | jq '.summary' -# --with-fts — opt-in FTS5 virtual table populated at index time. Default OFF (preserves -# .codemap/index.db size); CLI flag wins over .codemap/config.ts `fts5` field. Toggle change -# auto-detects and forces a full rebuild so `source_fts` stays consistent. -codemap --with-fts --full -codemap query --recipe text-in-deprecated-functions # demonstrates FTS5 ⨯ symbols ⨯ coverage JOIN -# HTTP API — same tool taxonomy as `codemap mcp`, exposed over POST /tool/{name} for -# non-MCP consumers (CI scripts, curl, IDE plugins). Loopback default; --token required on non-loopback. -TOKEN=$(openssl rand -hex 32) -codemap serve --port 7878 --token "$TOKEN" & # --token required when --host is not loopback -curl -s -X POST http://127.0.0.1:7878/tool/query \ - -H 'Content-Type: application/json' \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"sql":"SELECT name, file_path FROM symbols LIMIT 5"}' -# Watch mode — long-running process; debounced reindex on file changes (default 250ms). -# `mcp` / `serve` boot the watcher in-process by default since 2026-05 — every tool -# reads a live index without per-request prelude: -codemap mcp # default-ON watcher -codemap serve --port 7878 # default-ON watcher -codemap watch --quiet # standalone (decoupled from a transport) -codemap mcp --no-watch # opt out for one-shot fire-and-forget calls -CODEMAP_WATCH=0 codemap mcp # env-var opt-out (mirrors --no-watch) -# List recipe catalog (bundled + project-local) as JSON, or print one recipe's SQL (no DB required) -codemap query --recipes-json -codemap query --print-sql fan-out -# `components-by-hooks` ranks by hook count without SQLite JSON1 (comma-based count on the stored JSON array). - -# Project-local recipes — drop SQL files into `/recipes/` (default `.codemap/recipes/`) to make them discoverable across the team -# Bundled recipes live in templates/recipes/ in the npm package; project recipes win on id collision -# (shadowing is signalled via a `shadows: true` field in --recipes-json so agents notice the override) -mkdir -p .codemap/recipes # or: codemap --state-dir .cm --full && mkdir -p .cm/recipes -echo "SELECT path FROM files WHERE language IN ('ts', 'tsx') AND line_count > 500" \ - > .codemap/recipes/big-ts-files.sql -codemap query --recipe big-ts-files # auto-discovered alongside bundled - -# Targeted reads — precise lookup by symbol name without composing SQL -codemap show runQueryCmd # metadata: file:line + signature -codemap show foo --kind function --in src/cli # narrow ambiguous matches -codemap show --query 'kind:function name:Auth path:src/' # field-qualified discovery -codemap show --query 'kind:function name:foo' --print-sql # Moat-A SQL transparency -codemap snippet runQueryCmd # same lookup + source text from disk -codemap snippet --query 'kind:function name:run' --json # field-qualified + source body -codemap snippet foo --json # {matches: [{...metadata, source, stale, missing}]} -# Output envelope is always {matches, disambiguation?, warning?} — single match → {matches: [{...}]}; -# multi-match adds disambiguation: {n, by_kind, files, hint} for agent-friendly narrowing; -# warning when FTS was requested but source_fts is empty (re-index with --with-fts or fts5: true). - -# Impact analysis — symbol/file blast-radius walker (callers, callees, dependents, dependencies) -codemap impact handleQuery # both directions, depth 3, all compatible graphs -codemap impact dup --in src/a.ts --via calls # homonym symbol scoped to one defining file -codemap impact src/db.ts --direction up # what depends on db.ts (file-level, deps + imports) -codemap impact handleAudit --depth 1 --via calls # direct callers via the calls table only -codemap impact runWatchLoop --json --summary | jq '.summary.nodes' # CI-gate fan-in score -# Replaces hand-composed `WITH RECURSIVE` queries. Cycle-detected, depth-bounded -# (default 3, --depth 0 = unbounded), limit-capped (default 500). Result envelope: -# {target, matches: [...], summary: {nodes, terminated_by}, skipped_scope?}. -# Homonym symbols: unscoped unions per-defining-file graphs; --in scopes one file. - -# Affected tests — reverse dependency walk from changed sources → test files to run -codemap affected --json # working-tree changes vs HEAD (git status + diff) -git diff --name-only origin/main | codemap affected --stdin --json -codemap affected src/lib/cache.ts --json # explicit changed paths -codemap affected --changed-since origin/main --json # committed delta + working tree vs ref -# Moat-A twin: `affected-tests` recipe. Output: [{test_path, impact_depth}] — CI composes the runner command. - -# Apply — substrate-shaped fix executor (recipe SQL describes hunks; codemap validates + writes) -# Row contract (same as --format diff-json): {file_path, line_start, before_pattern, after_pattern} -# Preview first: codemap query --recipe rename-preview --params old=foo,new=bar --format diff-json -codemap apply rename-preview --params old=usePermissions,new=useAccess,kind=function --dry-run -codemap apply rename-preview --params old=usePermissions,new=useAccess,kind=function --yes # TTY prompts without --yes -# Homonym-safe: add define_in=src/path/to/definition.ts (scopes target; in_file only filters output rows) -# Alias: codemap rename helper worker --define-in src/path/to/definition.ts --dry-run -codemap apply migrate-import-source --params old_source=legacy,new_source=@app/core --dry-run -codemap apply stale-imports --params in_file=src/widget --dry-run # preview; writes need --force --yes -codemap apply migrate-jsx-prop --params old_name=data-id,new_name=data-testid,component_name=ProductCard --dry-run --force -# Agent/codemod rows (no recipe policy gates): echo '[{...}]' | codemap apply --rows - --yes -# External unified diff: codemap apply --diff-input /tmp/patch.diff --dry-run -# Fixpoint (recipe mode): codemap apply rename-preview --params old=a,new=b --until-empty --yes -# Optional git commit (recipe id required): codemap apply rename-preview --params old=a,new=b --yes --commit "chore: rename a→b" -# Bundled diff-shape recipes: rename-preview, migrate-import-source, replace-marker-kind, stale-imports, migrate-deprecated, deprecated-usages, migrate-jsx-prop, add-jsdoc-deprecated -# All-or-nothing: any conflict aborts before any file is written. MCP: apply, apply_rows, apply_diff_input (yes: true for writes). - -# Live agent content (pointer protocol — full body served from installed package version) -codemap skill # full codemap SKILL markdown to stdout -codemap rule # full codemap rule markdown to stdout - -# MCP server (Model Context Protocol) — for agent hosts (Claude Code, Cursor, Codex, generic MCP clients) -codemap mcp # JSON-RPC on stdio (21 tools; watcher default-ON) -# Tools (21): query, query_batch, query_recipe, audit, save_baseline, -# list_baselines, drop_baseline, context, validate, show, snippet, impact, -# affected, trace, explore, node, apply, apply_rows, apply_diff_input, -# ingest_coverage, ingest_churn -# CLI twins: query batch, trace, explore, node, file, schema, symbols, context --include-snippets, ingest-coverage, ingest-churn (same JSON as MCP/HTTP). -# query / query_recipe also accept baseline (same diff envelope as codemap query --baseline). -# Resources: codemap://schema, codemap://skill, codemap://rule, codemap://mcp-instructions (lazy-cached); -# codemap://recipes, codemap://recipes/{id} (live read-per-call — recency fields stay fresh); -# codemap://files/{path}, codemap://symbols/{name} (live read-per-call) -# Output shape verbatim from `--json` envelopes (no re-mapping). Snake_case throughout. - -# Another project -codemap --root /path/to/repo --full - -# Explicit config -codemap --config /path/to/config.json --full -# Override the state directory (default `.codemap/`): -codemap --state-dir .cm --full # or: CODEMAP_STATE_DIR=.cm codemap --full -codemap unlock # clear stale /index.lock after a crashed indexer - -# Re-index only given paths (relative to project root) -codemap --files src/a.ts src/b.tsx - -# Scaffold .agents/ from bundled templates — full matrix: docs/agents.md -codemap agents init -codemap agents init --force -codemap agents init --mcp # PM-aware project MCP config (see docs/agents.md) -codemap agents init --interactive # -i; IDE wiring + symlink vs copy -``` - -**Environment / flags:** `--root` overrides **`CODEMAP_ROOT`** / **`CODEMAP_TEST_BENCH`**, then **`process.cwd()`**; **`--state-dir`** overrides **`CODEMAP_STATE_DIR`** (default `.codemap/`); **`CODEMAP_WATCH=0`** / **`CODEMAP_NO_WATCH=1`** opt out of the default-ON watcher on `mcp` / `serve` (mirrors `--no-watch`); **`CODEMAP_FORCE_WATCH=1`** overrides WSL `/mnt/*` auto-disable. Use **`codemap agents init --git-hooks`** when the watcher is off for background sync on git events. **`CODEMAP_MCP_TOOLS`** registers a subset of MCP tools (comma-separated snake_case names; see [agents.md § MCP tool allowlist](docs/agents.md#mcp-tool-allowlist)). **`CODEMAP_PARSE_TIMEOUT_MS`** — fixed per-file parse budget (ms); unset uses 10s + size scaling capped at 30s. **`CODEMAP_WORKER_RECYCLE_EVERY`** — recycle worker threads after N files (default **250**). **`CODEMAP_PARSE_WORKERS`** — worker pool size (positive integer, max 32). Indexing a project outside this clone: [docs/benchmark.md § Indexing another project](docs/benchmark.md#indexing-another-project). - -**Configuration:** optional **`/config.{ts,js,json}`** (default `.codemap/config.*`; default export object or async factory). Shape: [codemap.config.example.json](codemap.config.example.json). Runtime validation (**Zod**, strict keys) and API surface: [docs/architecture.md § User config](docs/architecture.md#user-config). When developing inside this repo you can use `defineConfig` from `@stainless-code/codemap` or `./src/config`. If you set **`include`**, it **replaces** the default glob list entirely. **Self-healing files (D11):** `/.gitignore` is rewritten to canonical on every codemap boot; JSON config gets unknown-key pruning + key-sort drift; TS/JS configs are validate-only. +Full command reference, recipes, MCP/HTTP, config, and the GitHub Action: **[docs site](https://stainless-code.com/codemap)**. --- @@ -286,61 +47,26 @@ import { createCodemap } from "@stainless-code/codemap"; const cm = await createCodemap({ root: "/path/to/repo" }); await cm.index({ mode: "incremental" }); -await cm.index({ mode: "full" }); -await cm.index({ mode: "files", files: ["src/a.ts"] }); -await cm.index({ quiet: true }); - const rows = cm.query("SELECT name FROM symbols LIMIT 5"); ``` -`createCodemap` configures a process-global runtime (`initCodemap`); only **one active project per process** is supported. Advanced: `runCodemapIndex` when you hold a `CodemapDatabase` handle (library integration — not a separate public `openDb()` export; use `createCodemap` for the supported path). **Module layout:** [docs/architecture.md § Layering](docs/architecture.md#layering). +API reference: [https://stainless-code.com/codemap/reference/api](https://stainless-code.com/codemap/reference/api). --- ## Development -Tooling: **Oxfmt**, **Oxlint**, **tsgo** (`@typescript/native-preview`). - -| Command | Purpose | -| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `bun run dev` | Run the CLI from source (same as `bun src/index.ts`) | -| `bun run check` | Build, format check, lint, tests, typecheck, golden queries + agent-eval harness smoke — run before pushing | -| `bun run fix` | Apply lint fixes, then format | -| `bun run test` / `bun run typecheck` | Focused checks | -| `bun run test:golden` | SQL snapshot regression on `fixtures/minimal` (included in `check`) | -| `bun run test:agent-eval` | Agent-eval harness smoke on `fixtures/minimal` — probe + live MCP handlers (included in `check`; [docs/benchmark.md § Agent eval harness](docs/benchmark.md#agent-eval-harness)) | -| `bun run test:golden:external` | Tier B: local tree via `CODEMAP_*` / `--root` (not in default `check`) | -| `bun run benchmark:query` | Compare `console.table` vs `--json` stdout size (needs local `.codemap/index.db`; [docs/benchmark.md § Query stdout](docs/benchmark.md#query-stdout-table-vs-json-benchmarkquery)) | -| `bun run qa:external` | Index + sanity checks + benchmark on `CODEMAP_ROOT` / `CODEMAP_TEST_BENCH` | +Contributor workflow, checks, and conventions: [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md). ```bash bun install -bun run check # build + format:check + lint:ci + test + typecheck + test:golden + test:agent-eval -bun run fix # oxlint --fix, then oxfmt -``` - -**Readability & DX:** Prefer clear names and small functions; keep **JSDoc** on public exports. [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) has contributor workflow and conventions. - ---- - -## Benchmark - -Use a **real** project path (the repo must exist on disk). See [docs/benchmark.md § Indexing another project](docs/benchmark.md#indexing-another-project). - -```bash -CODEMAP_ROOT=/absolute/path/to/indexed-repo bun src/benchmark.ts +bun run check ``` -Optional **`CODEMAP_BENCHMARK_CONFIG`** for repo-specific scenarios: [docs/benchmark.md § Custom scenarios](docs/benchmark.md#custom-scenarios-codemap_benchmark_config). - -To compare **query** stdout size (`console.table` vs **`--json`**) on an existing index, see [docs/benchmark.md § Query stdout](docs/benchmark.md#query-stdout-table-vs-json-benchmarkquery) (**`bun run benchmark:query`**). +Maintainer hub: [docs/README.md](docs/README.md). --- -## Organization - -Developed under **[stainless-code](https://github.com/stainless-code)** on GitHub. - ## License MIT — see [LICENSE](LICENSE). diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore new file mode 100644 index 00000000..41dc2b3a --- /dev/null +++ b/apps/docs/.gitignore @@ -0,0 +1,10 @@ +# Generated docs runtime, isolated verify output, and build output +.blume/ +.blume-verify/ +dist/ + +# TypeDoc-generated API reference (meta.ts stays tracked) +content/reference/api/**/*.mdx +content/reference/api/**/*.md +!content/reference/api/meta.ts +!content/reference/api/index.mdx diff --git a/apps/docs/.oxfmtrc.json b/apps/docs/.oxfmtrc.json new file mode 100644 index 00000000..748e4e3a --- /dev/null +++ b/apps/docs/.oxfmtrc.json @@ -0,0 +1,9 @@ +{ + "$schema": "../.././node_modules/oxfmt/configuration_schema.json", + "sortImports": {}, + "sortPackageJson": { + "sortScripts": true + }, + "ignorePatterns": ["content/**", ".blume/**", "dist/**", ".blume-verify/**"], + "printWidth": 80 +} diff --git a/apps/docs/blume.config.ts b/apps/docs/blume.config.ts new file mode 100644 index 00000000..daa9a408 --- /dev/null +++ b/apps/docs/blume.config.ts @@ -0,0 +1,108 @@ +import { defineConfig } from "blume"; + +import { CURATED_POPULAR } from "./components/curated-popular"; + +const title = "Codemap"; +/** Custom `.astro` pages have no frontmatter — name OG cards (else humanized segment). */ +const homeTitle = `${title} — Query your codebase.`; +const notFoundTitle = "Page not found"; + +export default defineConfig({ + title, + description: + "Query your codebase — local codebase intelligence for AI agents", + + logo: { image: "/logo.svg", text: "Codemap" }, + + github: { + owner: "stainless-code", + repo: "codemap", + branch: "main", + dir: "apps/docs", + }, + + lastModified: true, + + content: { + sources: [ + { type: "filesystem", root: "content" }, + { + type: "github-releases", + prefix: "changelog", + owner: "stainless-code", + repo: "codemap", + limit: 100, + }, + ], + }, + + navigation: { + tabs: [ + { label: "Guides", path: "/guides", icon: "book-open" }, + { label: "Recipes", path: "/recipes", icon: "flask-conical" }, + { label: "Concepts", path: "/concepts", icon: "lightbulb" }, + { label: "Reference", path: "/reference", icon: "code" }, + ], + featured: [ + { label: "Changelog", href: "/changelog", icon: "sparkles" }, + { + label: "GitHub", + href: "https://github.com/stainless-code/codemap", + icon: "github", + }, + ], + sidebar: { display: "flat" }, + }, + + // Accent + zinc backgrounds; full token map in theme.css. + theme: { + accent: { light: "#1d4ed8", dark: "#60a5fa" }, + background: { light: "#fafafa", dark: "#18181b" }, + radius: "sm", + mode: "system", + fonts: { + display: "inter-tight", + body: "inter", + mono: "geist-mono", + }, + }, + search: { + provider: "orama", + // Cmd+K empty-state + shared with 404 via CURATED_POPULAR. + popular: CURATED_POPULAR.map(({ route, label }) => ({ + href: route, + label, + })), + }, + + markdown: { + code: { icons: true }, + codeBlocks: { theme: { light: "github-light", dark: "github-dark" } }, + }, + + toc: { minHeadingLevel: 2, maxHeadingLevel: 3 }, + + export: { epub: true, pdf: true }, + + ai: { + llmsTxt: true, + }, + + seo: { + og: { + enabled: true, + titles: { "/": homeTitle, "/404": notFoundTitle }, + }, + rss: { enabled: true, types: ["changelog"] }, + sitemap: true, + robots: true, + structuredData: true, + agentReadability: true, + }, + + deployment: { + output: "static", + site: "https://stainless-code.com", + base: "/codemap", + }, +}); diff --git a/apps/docs/components.ts b/apps/docs/components.ts new file mode 100644 index 00000000..d3e173d3 --- /dev/null +++ b/apps/docs/components.ts @@ -0,0 +1,12 @@ +import { defineComponents } from "blume"; + +import Footer from "./components/blume/Footer.astro"; +import Pagination from "./components/blume/Pagination.astro"; + +export default defineComponents({ + layout: { + Footer, + // Theme radius (rounded-blume) instead of built-in pill corners. + Pagination, + }, +}); diff --git a/apps/docs/components/blume/Footer.astro b/apps/docs/components/blume/Footer.astro new file mode 100644 index 00000000..3df8d7c9 --- /dev/null +++ b/apps/docs/components/blume/Footer.astro @@ -0,0 +1,168 @@ +--- +import data from "blume:data"; +import { contentHref } from "blume/components/content/base-href.ts"; +import { EN_UI } from "blume/core/i18n-ui.ts"; +import type { UIStrings } from "blume/core/i18n-ui.ts"; +import type { Navigation } from "blume/core/types.ts"; +import Logo from "blume/components/layout/Logo.astro"; + +interface Props { + site: { title: string; description?: string }; + navigation: Navigation; + ui: UIStrings; +} + +const { site, navigation, ui } = Astro.props; + +// `layout.Footer` is wired by RootLayout, which does not forward `logo` — pull +// the resolved brand mark from the generated data module so the footer stays in +// sync with the header logo. +const logo = data.config.logo; +const repoUrl = navigation.repoUrl; +const year = new Date().getFullYear(); + +// Merge over the English defaults so a label missing from a translation still +// renders instead of coming out blank — the PageActions pattern. +const strings = { ...EN_UI, ...ui }; + +// Grouped, intentional columns (not derived from the flat `navigation.tabs` +// list). Base-path-correct links come from `contentHref`. +const groups: { + label: string; + links: { href: string; label: string; external?: boolean }[]; +}[] = [ + { + label: "Guides", + links: [ + { + href: contentHref("/guides/getting-started"), + label: "Getting started", + }, + { href: contentHref("/guides/agents-mcp"), label: "Agents & MCP" }, + { href: contentHref("/guides"), label: "All guides" }, + ], + }, + { + label: "Recipes", + links: [ + { href: contentHref("/recipes"), label: "Catalog" }, + { + href: contentHref("/recipes/find-symbol-definitions"), + label: "find-symbol-definitions", + }, + { href: contentHref("/recipes/affected-tests"), label: "affected-tests" }, + ], + }, + { + label: "Concepts", + links: [ + { href: contentHref("/concepts/why-codemap"), label: "Why Codemap" }, + { + href: contentHref("/concepts/schema-overview"), + label: "Schema overview", + }, + { href: contentHref("/concepts"), label: "All concepts" }, + ], + }, + { + label: "Reference", + links: [ + { href: contentHref("/reference/cli"), label: "CLI" }, + { href: contentHref("/reference/mcp"), label: "MCP" }, + { href: contentHref("/reference/api"), label: "API" }, + { href: contentHref("/reference/roadmap"), label: "Roadmap" }, + ], + }, + { + label: "Project", + links: [ + { href: contentHref("/changelog"), label: "Changelog" }, + ...(repoUrl + ? [{ href: repoUrl, label: "GitHub", external: true as const }] + : [ + { + href: "https://github.com/stainless-code/codemap", + label: "GitHub", + external: true as const, + }, + ]), + ], + }, +]; +--- + +
+
+
+
+ + { + site.description && ( +

+ {site.description} +

+ ) + } + { + repoUrl && ( + + + + + GitHub + + ) + } +
+ + +
+ +
+

+ © {year} Codemap · MIT +

+
+
+
diff --git a/apps/docs/components/blume/Pagination.astro b/apps/docs/components/blume/Pagination.astro new file mode 100644 index 00000000..0203bd0a --- /dev/null +++ b/apps/docs/components/blume/Pagination.astro @@ -0,0 +1,63 @@ +--- +import { withBase } from "blume/components/islands/base-path.ts"; +import { EN_UI } from "blume/core/i18n-ui.ts"; +import type { UIStrings } from "blume/core/i18n-ui.ts"; +import type { FlatPage } from "blume/components/layout/nav-utils.ts"; +import Icon from "blume/components/Icon.astro"; + +interface Props { + /** Previous page in reading order, or `null` at the start. */ + prev: FlatPage | null; + /** Next page in reading order, or `null` at the end. */ + next: FlatPage | null; + /** Localized page-level strings (`previous`, `next`, the landmark label). */ + strings: UIStrings["page"]; +} + +const { prev, next, strings } = Astro.props; + +// Merge over the English defaults so a label missing from a translation (or +// from a not-yet-regenerated snapshot) still renders instead of coming out +// blank — the PageActions pattern. +const s = { ...EN_UI.page, ...strings }; +--- + +{ + (prev || next) && ( + + ) +} diff --git a/apps/docs/components/curated-popular.ts b/apps/docs/components/curated-popular.ts new file mode 100644 index 00000000..2ecfb81b --- /dev/null +++ b/apps/docs/components/curated-popular.ts @@ -0,0 +1,16 @@ +/** Shared Cmd+K (`search.popular`) + 404 destinations — not sidebar order. */ +export const CURATED_POPULAR = [ + { route: "/guides/getting-started", label: "Getting started" }, + { route: "/recipes", label: "Recipe catalog" }, + { route: "/guides/agents-mcp", label: "Agents & MCP" }, + { route: "/guides/apply", label: "Apply & rename" }, + { route: "/guides/audit-baselines", label: "Audit & baselines" }, + { route: "/concepts/why-codemap", label: "Why Codemap" }, + { route: "/reference/cli", label: "CLI reference" }, + { + route: "/recipes/find-symbol-definitions", + label: "find-symbol-definitions", + }, + { route: "/guides/github-action", label: "GitHub Action" }, + { route: "/concepts/schema-overview", label: "Schema overview" }, +] as const; diff --git a/apps/docs/content/concepts/index-lifecycle.mdx b/apps/docs/content/concepts/index-lifecycle.mdx new file mode 100644 index 00000000..14bae428 --- /dev/null +++ b/apps/docs/content/concepts/index-lifecycle.mdx @@ -0,0 +1,39 @@ +--- +title: Index lifecycle +description: How Codemap indexes, when to full-rebuild, and how agents read freshness. +search: + tags: ["concept"] +--- + +Default `codemap` is **incremental** — re-parse what changed, keep the rest. Agents should treat results as authoritative only when freshness looks clean. + +## Modes + +```bash +codemap # incremental (git-aware when available) +codemap --full # wipe + rebuild +codemap --files src/a.ts … # targeted paths after edits +codemap validate --json # per-file stale / missing / unindexed / rejected +``` + +Use `--full` after a schema-breaking package upgrade (forces `.codemap/index.db` rebuild), after toggling `fts5` / `--with-fts`, or when the index is clearly wrong. + +## Watcher + +`codemap mcp` and `codemap serve` embed a debounced file watcher by default (≈250ms). Standalone: `codemap watch`. Opt out: `--no-watch` or `CODEMAP_WATCH=0`. When the watcher is disabled (WSL `/mnt/*`, etc.), `codemap agents init --git-hooks` installs background incremental index on git events. + +Concurrent indexers coordinate via `/index.lock`. After a crash: `codemap unlock`. Per-file parse failures append to `/errors.log`. + +## Freshness signals + +Session bootstrap (`codemap context` / MCP `context`) exposes `index_freshness`: + +| Field | Meaning | +| --------------- | ---------------------------------------------------- | +| `pending_sync` | Debounce queue or in-flight reindex | +| `commit_drift` | `HEAD` ≠ `last_indexed_commit` | +| `warning` | Single agent-readable line when something is off | + +If `pending_sync`, wait briefly and retry (or call `validate`). If `commit_drift` / `warning`, run `codemap` (or rely on watch) before trusting structural queries. Snippet rows may set `stale: true` when disk drifted past indexed line ranges. + +State dir details: [Config](/guides/config). Env knobs: [Env](/reference/env). diff --git a/apps/docs/content/concepts/index.mdx b/apps/docs/content/concepts/index.mdx new file mode 100644 index 00000000..c620e53d --- /dev/null +++ b/apps/docs/content/concepts/index.mdx @@ -0,0 +1,17 @@ +--- +title: Concepts +description: Why Codemap, when to skip it, index lifecycle, and schema overview. +search: + tags: ["concept"] +--- + +These pages explain the model — not every CLI flag. + +| Concept | Read when you need… | +| -------------------------------------------- | -------------------------------------------- | +| [Why Codemap](/concepts/why-codemap) | Positioning vs grep, LSP, linters, peers | +| [When to skip](/concepts/when-to-skip) | Honest anti-pitch — wrong tool for the job | +| [Index lifecycle](/concepts/index-lifecycle) | Incremental vs full, freshness signals | +| [Schema overview](/concepts/schema-overview) | Tables agents query most | + +Hands-on: [Getting started](/guides/getting-started). Named patterns: [Recipes](/recipes). diff --git a/apps/docs/content/concepts/meta.ts b/apps/docs/content/concepts/meta.ts new file mode 100644 index 00000000..422e7f6d --- /dev/null +++ b/apps/docs/content/concepts/meta.ts @@ -0,0 +1,12 @@ +import { defineMeta } from "blume"; + +export default defineMeta({ + title: "Concepts", + icon: "lightbulb", + pages: [ + "why-codemap", + "when-to-skip", + "index-lifecycle", + "schema-overview", + ], +}); diff --git a/apps/docs/content/concepts/schema-overview.mdx b/apps/docs/content/concepts/schema-overview.mdx new file mode 100644 index 00000000..702fd822 --- /dev/null +++ b/apps/docs/content/concepts/schema-overview.mdx @@ -0,0 +1,59 @@ +--- +title: Schema overview +description: High-level Codemap SQLite tables — files, symbols, imports, calls, and friends. +search: + tags: ["concept"] +--- + +Prefer [recipes](/recipes) until you know the join paths. Live DDL: MCP/HTTP `codemap://schema`, or the schema section of `codemap skill`. + +## Core structure + +| Table | Holds | +| ---------------- | ------------------------------------------------------------------ | +| `files` | Every indexed path + language + line counts | +| `symbols` | Functions, classes, interfaces, types, enums, … | +| `imports` | Import statements | +| `exports` | Export declarations | +| `dependencies` | Resolved file→file edges (import graph) | +| `components` | React components (PascalCase + JSX / hooks heuristic) | +| `calls` | Function-scoped call edges | +| `references` | Identifier uses | +| `bindings` | Use → originating symbol | +| `markers` | TODO / FIXME / HACK / NOTE | + +## Types & modules + +| Table | Holds | +| ------------------- | -------------------------------------------------- | +| `type_members` | Interface / object-literal members | +| `type_heritage` | extends / implements | +| `import_specifiers` | Per-specifier breakdown of imports | +| `re_export_chains` | Materialised re-export resolution | +| `module_cycles` | Files in import cycles | +| `dynamic_imports` | `import()` sites | +| `scopes` | Lexical scope graph | + +## CSS & JSX + +| Table | Holds | +| --------------- | ------------------------------ | +| `css_variables` | Custom properties / tokens | +| `css_classes` | Class definitions | +| `css_keyframes` | `@keyframes` | +| `jsx_elements` / `jsx_attributes` | JSX substrate | + +## Ops & CI facts + +| Table | Holds | +| ------------------ | ------------------------------------------------------------- | +| `test_suites` | describe / it / test blocks | +| `file_churn` | Git (or ingested) churn metrics | +| `file_metrics` | Per-file aggregates | +| `coverage` | Statement coverage after `ingest-coverage` | +| `boundary_rules` | From config `boundaries` | +| `query_baselines` | Saved query snapshots for `--baseline` / `audit` | +| `source_fts` | Opt-in FTS5 over file bodies (`fts5: true` / `--with-fts`) | +| `meta` | Key-value index metadata | + +Languages: deep extraction for JS/TS/JSX/TSX/CSS; markers-only for markdown/json/yaml/sh and similar. Adapters: [Programmatic](/guides/programmatic). diff --git a/apps/docs/content/concepts/when-to-skip.mdx b/apps/docs/content/concepts/when-to-skip.mdx new file mode 100644 index 00000000..11400fd8 --- /dev/null +++ b/apps/docs/content/concepts/when-to-skip.mdx @@ -0,0 +1,21 @@ +--- +title: When to skip +description: Cases where Codemap is the wrong tool — use grep, LSP, or another index instead. +search: + tags: ["concept"] +--- + +Codemap is intentionally narrow. Pick the right tool: + +| Need | Reach for | Reach for Codemap when… | +| -------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------ | +| Raw text / grep semantics | `ripgrep` / IDE search | Body matches that JOIN with structure — opt-in FTS5 | +| In-editor types / rename / hover | `tsserver` / LSP | Read-side blast radius — `show` / `snippet` / `impact` | +| Verdict lints (severity, suppressions, autofix) | knip / jscpd / `eslint --fix` | Predicate-as-API analysis you compose — recipes + `--format sarif`; `apply` runs **your** diff rows, it doesn’t invent fixes | +| Semantic / embedding search | An embedding index | Structural facts only — no LLM-in-the-box | +| Whole-file reading | Editor / `Read` tool | Paths + line ranges + signatures; agent still reads snippets | +| Agent reasoning / generation | Your agent host | Codemap answers; it doesn’t decide | +| Polyglot “who calls X” across many languages | Multi-language index tools | JS/TS/CSS-ecosystem depth is the focus | +| NL Q&A over the whole repo | Agent host + embeddings | — | + +Positioning detail: [Why Codemap](/concepts/why-codemap). diff --git a/apps/docs/content/concepts/why-codemap.mdx b/apps/docs/content/concepts/why-codemap.mdx new file mode 100644 index 00000000..816bce17 --- /dev/null +++ b/apps/docs/content/concepts/why-codemap.mdx @@ -0,0 +1,40 @@ +--- +title: Why Codemap +description: Local codebase intelligence for AI agents — what Codemap is for and what it is not. +search: + tags: ["concept"] +--- + +Agents discover code by globbing, grepping, and reading files. On medium TypeScript trees that often means 3–5 tool calls and multi-MB context per structural question. AST-backed facts in `.codemap/index.db` make the answer one SQL (or recipe) round-trip. + +Not grep semantics by default — use ripgrep / your IDE for raw text. Opt-in FTS5 (`--with-fts` / `fts5: true`) when body matches need to JOIN with `symbols` / `coverage` / `markers`. + +## What you get + +| Question | Without index | With Codemap | +| -------------------------------- | ------------------------------------- | ------------------------------------------------- | +| Where is `UserService` defined? | Glob + Read + filter | `find-symbol-definitions` / `show` | +| Who imports `~/utils/date`? | Grep + resolve aliases by hand | `dependencies` / `impact` | +| Components using `useQuery` | Grep + filter to components | `components` table / recipes | +| Heaviest import hubs | Impractical without a graph | `fan-in` | + +Indexed structural queries stay sub-millisecond on typical trees; the real win for agents is **token cost** — rows instead of whole-file reads, compounded across a session. + +## Four tenets (short) + +1. **Structural over semantic** — facts the AST and resolver can prove; no embeddings in the box. +2. **Predicate-as-API** — SQL + named recipes; SARIF/annotations are output modes, not primitives. +3. **Local-first, agent-native** — SQLite on disk; CLI, MCP, HTTP, GitHub Action share the same recipes. +4. **Honest scope** — say what not to use it for. See [When to skip](/concepts/when-to-skip). + +## Vs alternatives (axes, not brands) + +| Axis | Codemap | Static linters (knip / ESLint / …) | Repo-map style tools | LSP | +| ----------------- | ------------------------------- | ---------------------------------- | ------------------------- | --------------------------- | +| Thesis | Query structure with SQL | Emit findings / fixes | Summarize into a blob | Per-edit semantic helpers | +| Who decides | The agent (via SQL) | The tool’s rules | The tool’s ranking | The editor | +| Best for | Where / what / who lookups | “Did this PR introduce dead code?” | First-touch priming | Refactor / hover / types | + +SQLite-backed code-index peers often ship pre-baked graph verbs or NL over the index. Codemap’s differentiation: **SQL + recipes**, **pure structural**, **JS/TS/CSS-ecosystem depth**, plus **CI substrate** (SARIF, audit, Action). + +They don’t compete for the same slot — use Codemap **and** a linter **and** an LSP. diff --git a/apps/docs/content/guides/agents-mcp.mdx b/apps/docs/content/guides/agents-mcp.mdx new file mode 100644 index 00000000..9190a88b --- /dev/null +++ b/apps/docs/content/guides/agents-mcp.mdx @@ -0,0 +1,70 @@ +--- +title: Agents & MCP +description: Wire Codemap into Cursor and other agents via templates, MCP, and HTTP. +search: + tags: ["guide", "agents", "mcp"] +--- + +`codemap agents init` drops thin pointer files into `.agents/`; the full skill and rule are served live from the installed package version. Updating `@stainless-code/codemap` refreshes what agents see — no re-init unless the pointer shape itself changes. + +## Scaffold + +```bash +codemap agents init +codemap agents init --force +codemap agents init --mcp +codemap agents init --interactive # -i; TTY multiselect +codemap agents init --targets cursor,copilot --mcp +codemap agents init --git-hooks # background index on git events +``` + +`--force` refreshes only bundled template paths under `.agents/` (and IDE mirrors marked ``). Your other rules stay. + +## Live content (CLI + MCP + HTTP) + +| Surface | Skill | Rule | +| ---------------------- | -------------------------- | ------------------------- | +| CLI | `codemap skill` | `codemap rule` | +| MCP | `codemap://skill` | `codemap://rule` | +| HTTP (`codemap serve`) | `GET /resources/{uri}` | same for `codemap://rule` | + +Also useful: `codemap://schema`, `codemap://recipes`, `codemap://mcp-instructions`. + +## MCP wiring + +```bash +codemap agents init --mcp +``` + +Writes PM-aware spawn for the project’s package manager (`npx`, `pnpm exec`, `yarn exec`, `bunx`, or dlx of `@stainless-code/codemap@latest` when not installed). Merge is idempotent — foreign MCP servers are preserved. + +| Target | Typical files written | +| ----------------- | ---------------------------------------------------------- | +| Cursor | `.cursor/mcp.json` | +| Claude Code | `.mcp.json` + `.claude/settings.json` | +| VS Code / Copilot | `.vscode/mcp.json` | +| Continue / Cline / Gemini / Amazon Q | project MCP JSON under each tool’s path | +| Windsurf | user-global Cascade MCP config (when Windsurf is selected) | + +Optional IDE mirrors for rules/skills: Cursor, Windsurf, Continue, Cline, Amazon Q, plus root pointers (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `.github/copilot-instructions.md`). + +## Session start + +Long-running `codemap mcp` stays up for the IDE session (no idle timeout). At session start, call **`context`** — project root, schema version, recipe cards, hub leaders, and `index_freshness` (`pending_sync`, `commit_drift`, optional `warning`). + +Watcher is default-ON for `mcp` / `serve`. Opt out: `--no-watch` or `CODEMAP_WATCH=0`. When the watcher is off (e.g. WSL `/mnt/*`), use `codemap agents init --git-hooks`. + +Tool taxonomy and resources: [MCP reference](/reference/mcp). Allowlist: `CODEMAP_MCP_TOOLS` — see [Env](/reference/env). + +## HTTP twin + +```bash +TOKEN=$(openssl rand -hex 32) +codemap serve --port 7878 --token "$TOKEN" +curl -s -X POST http://127.0.0.1:7878/tool/query \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"sql":"SELECT name, file_path FROM symbols LIMIT 5"}' +``` + +Same tools as MCP; `--token` required when `--host` is not loopback. diff --git a/apps/docs/content/guides/apply.mdx b/apps/docs/content/guides/apply.mdx new file mode 100644 index 00000000..70797980 --- /dev/null +++ b/apps/docs/content/guides/apply.mdx @@ -0,0 +1,75 @@ +--- +title: Apply & rename +description: Turn recipe diff rows into on-disk edits — dry-run, fixpoint, and rename. +search: + tags: ["guide", "apply", "rename"] +--- + +You’ve got rows that say what to change — `file_path`, `line_start`, `before_pattern`, `after_pattern`. `codemap apply` validates the on-disk line still matches `before_pattern`, then writes `after_pattern`. + +Apply recipes live under [Recipes → Apply / migrate](/recipes#apply--migrate). Preview shape: `--format diff` or `diff-json` ([Formats](/reference/formats)). + +## Recipe apply + +```bash +codemap query --recipe rename-preview \ + --params old=usePermissions,new=useAccess,kind=function \ + --format diff + +codemap apply rename-preview \ + --params old=usePermissions,new=useAccess,kind=function \ + --dry-run + +codemap apply rename-preview \ + --params old=usePermissions,new=useAccess,kind=function \ + --yes +``` + +`--dry-run` validates only. `--yes` is required for real writes (and on non-TTY). Recipes that are not `auto_fixable` need `--force` (or config allowlist) before writes. + +## Rename alias + +`codemap rename` is `apply rename-preview` with friendlier argv. Homonyms: pass `--define-in ` to anchor the definition file (`--in-file` only narrows output paths). + +```bash +codemap rename usePermissions useAccess --kind function --dry-run +codemap rename helper worker --define-in lib/helper.ts --yes +codemap rename --params old=foo,new=bar,define_in=lib/a.ts --dry-run +``` + +## Rows and unified diffs + +Skip the recipe when you already have rows (agent / codemod / audit `added`): + +```bash +codemap query --recipe stale-imports --format diff-json > rows.json +codemap apply --rows rows.json --dry-run +codemap apply --rows - --yes < rows.json + +codemap apply --diff-input edits.patch --dry-run +codemap apply --diff-input edits.patch --yes --commit "chore: drop stale imports" +``` + +## Fixpoint and commit + +```bash +codemap apply migrate-import-source \ + --params from=@old/pkg,to=@new/pkg \ + --yes --until-empty --max-passes 10 + +codemap apply rename-preview \ + --params old=foo,new=bar \ + --yes --commit "refactor: rename foo → bar" +``` + +`--until-empty` loops apply → reindex → repeat until no rows (or `--max-passes`). `--commit` runs `git add` on touched files + commit after a clean apply. + +## MCP twins + +| CLI | MCP | +| --------------------------- | ------------------- | +| `codemap apply ` | `apply` | +| `codemap apply --rows …` | `apply_rows` | +| `codemap apply --diff-input`| `apply_diff_input` | + +Writes still need `yes: true`. Non-`auto_fixable` recipes need `force: true`. Full tool table: [MCP](/reference/mcp). diff --git a/apps/docs/content/guides/audit-baselines.mdx b/apps/docs/content/guides/audit-baselines.mdx new file mode 100644 index 00000000..a95aaf18 --- /dev/null +++ b/apps/docs/content/guides/audit-baselines.mdx @@ -0,0 +1,67 @@ +--- +title: Audit & baselines +description: Diff the index against a saved baseline or a git merge-base — PR attribution included. +search: + tags: ["guide", "audit", "baseline", "ci"] +--- + +“Did this PR introduce new deprecated symbols?” needs a before picture. Save a row snapshot with `--save-baseline`, or diff against a git ref with `audit --base`. + +## Query baselines + +Snapshot any query / recipe result into `query_baselines` inside the index DB (survives `--full` and schema rebuilds): + +```bash +codemap query --json --recipe deprecated-symbols --save-baseline +codemap query --json --recipe deprecated-symbols --save-baseline=pre-refactor + +codemap query --json --recipe deprecated-symbols --baseline +codemap query --json --recipe deprecated-symbols --baseline=pre-refactor --summary + +codemap query --baselines +codemap query --drop-baseline pre-refactor +``` + +`--baseline` returns `{ baseline, current_row_count, added, removed }` (exact row identity via `JSON.stringify`). Incompatible with non-`json` `--format` / `--group-by`. Ad-hoc SQL must pass an explicit `=` on `--save-baseline`. + +## audit --base (PR merge-base) + +Materialises `` via `git archive`, reindexes into a sha-keyed cache, then diffs. No baseline setup required: + +```bash +codemap audit --base origin/main --json +codemap audit --base origin/main --summary +codemap audit --base origin/main --ci # SARIF + non-zero on additions +``` + +With `--format json`, each **added** row carries `attribution`: `introduced` (branch-new) or `inherited` (already present at the merge base). Summary adds `added_introduced` / `added_inherited` per delta. + +v1 deltas: `files`, `dependencies`, `deprecated`. + +## audit --baseline (prefix) + +Convention: save `-files`, `-dependencies`, `-deprecated`, then: + +```bash +codemap query --save-baseline=base-files "SELECT path FROM files" +# … or the recipes / SQL you care about for each delta slot + +codemap audit --baseline base --json +``` + +Missing slots are silently absent. Per-delta overrides: `--files-baseline`, `--dependencies-baseline`, `--deprecated-baseline` (compose with `--base` or `--baseline`). + +## GitHub Action + +Default `mode: audit` on `pull_request` runs against `github.base_ref` (override with `audit-base`). Recipe mode can pass `baseline` for `--baseline` on `query --recipe`. Details: [GitHub Action](/guides/github-action). + +## MCP + +| Goal | Tool | +| ----------------- | ---------------- | +| Save snapshot | `save_baseline` | +| List | `list_baselines` | +| Drop | `drop_baseline` | +| Diff vs base / prefix | `audit` | + +`audit` accepts `base` (git ref) and/or `baseline_prefix` / per-delta `baselines`. One-shot row diff on `query` / `query_recipe` also accepts `baseline`. diff --git a/apps/docs/content/guides/cli-overview.mdx b/apps/docs/content/guides/cli-overview.mdx new file mode 100644 index 00000000..f5cdee20 --- /dev/null +++ b/apps/docs/content/guides/cli-overview.mdx @@ -0,0 +1,102 @@ +--- +title: CLI overview +description: Common Codemap CLI commands — index, query, recipes, serve, and agents init. +search: + tags: ["guide", "cli"] +--- + +Index the tree once per session, then ask structural questions with SQL or a recipe id. Full flag list: [CLI reference](/reference/cli). + +## Index + +```bash +codemap # incremental +codemap --full # full rebuild +codemap --files src/a.ts src/b.tsx # targeted re-index after edits +codemap validate --json # stale / missing / unindexed / rejected +``` + +State lives under `.codemap/` by default (`--state-dir` / `CODEMAP_STATE_DIR` overrides). + +## Query + +```bash +codemap query --json "SELECT name, file_path FROM symbols WHERE name = 'foo'" +codemap query --json --recipe fan-in +codemap query --json --recipe find-symbol-definitions --params name=usePermissions +codemap query --recipes-json # full catalog (bundled + project-local) +codemap query --print-sql fan-in # SQL only — no DB required +``` + +N statements in one bootstrap: + +```bash +echo '{"statements":["SELECT COUNT(*) AS n FROM symbols","SELECT COUNT(*) AS n FROM files"]}' \ + | codemap query batch --stdin --compact +``` + +Outcome aliases are thin wrappers over `query --recipe` (every query flag passes through): + +```bash +codemap dead-code --json # → untested-and-dead +codemap deprecated --ci # → deprecated-symbols --ci +codemap hotspots --json # → fan-in (import hubs — not churn×complexity) +codemap boundaries --format sarif # → boundary-violations +``` + +## Lookups & graphs + +```bash +codemap show runQueryCmd +codemap show foo --kind function --in src/cli +codemap snippet runQueryCmd --json +codemap impact handleQuery # blast radius (callers / dependents) +codemap affected --json # changed sources → tests to run +codemap trace --from createCodemap --to openDatabase +codemap explore handleQuery executeQuery --depth 1 +codemap node handleQuery +``` + +## Apply / ingest (one-liners) + +```bash +codemap apply rename-preview --params old=foo,new=bar --dry-run +codemap rename foo bar --kind function --dry-run +codemap ingest-coverage coverage/coverage-final.json +codemap ingest-churn churn.json +``` + +Full workflows: [Apply](/guides/apply) · [Coverage & churn](/guides/coverage-churn). + +## Resource cards + +```bash +codemap file src/db.ts +codemap schema +codemap symbols handleQuery +``` + +Same JSON as `codemap://files/…`, `codemap://schema`, `codemap://symbols/…`. + +## Agents & transports + +```bash +codemap agents init # scaffold .agents/ pointers +codemap agents init --mcp # + PM-aware MCP config +codemap mcp # stdio MCP (watcher default-ON) +codemap serve --port 7878 # HTTP twin: POST /tool/{name} +codemap skill # live skill markdown +codemap rule # live rule markdown +``` + +Opt out of the embedded watcher: `codemap mcp --no-watch` or `CODEMAP_WATCH=0`. + +## CI-shaped output + +```bash +codemap query --recipe deprecated-symbols --format sarif +codemap query --recipe boundary-violations --ci +codemap audit --base origin/main --json +``` + +Formats: [Formats](/reference/formats). Baselines: [Audit & baselines](/guides/audit-baselines). CI wiring: [GitHub Action](/guides/github-action). diff --git a/apps/docs/content/guides/config.mdx b/apps/docs/content/guides/config.mdx new file mode 100644 index 00000000..6f1039f5 --- /dev/null +++ b/apps/docs/content/guides/config.mdx @@ -0,0 +1,54 @@ +--- +title: Config +description: Project config for Codemap — include/exclude globs, boundaries, synthesis, and churn. +search: + tags: ["guide", "config"] +--- + +Optional config lives at `/config.{ts,js,json}` (default `.codemap/config.*`). Default export: a plain object or an async factory. Unknown keys are rejected (Zod, strict). + +## Minimal shape + +```ts +import { defineConfig } from "@stainless-code/codemap"; + +export default defineConfig({ + include: ["src/**/*.{ts,tsx}", "src/**/*.css"], + excludeDirNames: ["node_modules", ".git", "dist", "build"], + boundaries: [ + { + name: "ui-cant-touch-server", + from_glob: "src/ui/**", + to_glob: "src/server/**", + }, + ], + synthesis: { + heuristicCalls: false, + }, +}); +``` + +JSON works the same (no `defineConfig`). Setting **`include` replaces** the default glob list entirely — it does not merge. + +## Common knobs + +| Field | Role | +| ------------------ | -------------------------------------------------------------------- | +| `include` | Globs relative to project root (replaces defaults when set) | +| `excludeDirNames` | Directory name segments to skip (replaces defaults when set) | +| `tsconfigPath` | Alias resolution; `null` disables | +| `fts5` | Opt-in full-text (`source_fts`); CLI `--with-fts` wins | +| `boundaries` | Architecture rules → `boundary_rules` / `boundary-violations` recipe | +| `synthesis` | e.g. `heuristicCalls` for opt-in heuristic call edges | +| `churn` | Half-life / `since` / optional precomputed `file` | +| `apply` | `autoApplyRecipes` allowlist for `codemap apply` | + +Types and helpers: [API reference](/reference/api). Library entry: [Programmatic](/guides/programmatic). + +## State directory + +Default `.codemap/`. Override with `--state-dir` or `CODEMAP_STATE_DIR`. Codemap rewrites `/.gitignore` to a canonical blacklist on every boot (`index.db`, WAL/SHM, …). Project-tracked sources (`recipes/`, config) stay trackable. + +## Project-local recipes + +Drop SQL into `.codemap/recipes/.sql` (+ optional `.md` for params/actions). Discoverable via `codemap query --recipes-json`; project ids win on collision (`shadows: true` in the catalog). diff --git a/apps/docs/content/guides/coverage-churn.mdx b/apps/docs/content/guides/coverage-churn.mdx new file mode 100644 index 00000000..b02f9fc1 --- /dev/null +++ b/apps/docs/content/guides/coverage-churn.mdx @@ -0,0 +1,43 @@ +--- +title: Coverage & churn +description: Load coverage and churn into the index so risk recipes have measured numbers. +search: + tags: ["guide", "coverage", "churn"] +--- + +Structural dead-code guesses without runtime evidence are noisy. Load coverage (and optional churn) once, then rank with the [Coverage & churn recipes](/recipes#coverage--churn-risk). + +## Ingest coverage + +```bash +codemap ingest-coverage coverage/coverage-final.json # Istanbul +codemap ingest-coverage lcov.info # LCOV +codemap ingest-coverage ./coverage/tmp --runtime # V8 directory +codemap ingest-coverage ./coverage --json +``` + +Auto-detects Istanbul `.json` / LCOV `.info`; pass `--runtime` for V8 dirs. MCP: `ingest_coverage` (`path`, optional `runtime`). + +## Ingest churn + +Git history fills `file_churn` on each index by default. For fixtures or non-git trees: + +```bash +codemap ingest-churn churn.json --json +``` + +Config `churn.file` can replace git-derived churn. MCP: `ingest_churn`. + +## Recipes that unlock + +| After ingest | Recipe ids | +| ------------------------------------ | -------------------------------------------------------------------------- | +| Coverage | `worst-covered-exports`, `files-by-coverage`, `coverage-confirmed-dead`, `untested-and-dead`, `high-complexity-untested`, `text-in-deprecated-functions` | +| Coverage (improves / overrides) | `high-crap-score`, `refactor-risk-ranking` | +| Churn (git default or ingest/config) | `churn-complexity-hotspots` | + +Empty `file_churn` → check `context` / `churn_hint`. Full catalog: [Recipes](/recipes). + +## high-crap-score caveat + +Without measured coverage, `high-crap-score` can still emit rows using **graph-estimated** coverage tiers (85% / 40% / 0%). Parse `coverage_source` on each row before CI gates — prefer `ingest-coverage` first so scores use measured data. diff --git a/apps/docs/content/guides/getting-started.mdx b/apps/docs/content/guides/getting-started.mdx new file mode 100644 index 00000000..ae468b9b --- /dev/null +++ b/apps/docs/content/guides/getting-started.mdx @@ -0,0 +1,58 @@ +--- +title: Getting started +description: Install Codemap and run your first structural query against a local SQLite index. +search: + tags: ["guide", "install"] +--- + +Agents burn tokens scanning files to find one symbol. A SQLite index (`.codemap/index.db`) answers the same question in one SQL round-trip. + +Experimental — the API may change between minor releases. Pin your version. + +## Install + +```package-install +npm i -D @stainless-code/codemap +``` + +Or run the published binary without adding a dependency — same CLI either way: + +```package-install +npx @stainless-code/codemap +``` + +**Engines:** Node `^20.19.0 || >=22.12.0` and/or Bun `>=1.0.31`. + +## Index once + +```bash +codemap +``` + +Default is incremental. Use `codemap --full` for a clean rebuild after a schema bump or when the index looks wrong. + +## First query + +Ad-hoc SQL: + +```bash +codemap query --json "SELECT name, kind, file_path, line_start FROM symbols WHERE name = 'createCodemap'" +``` + +Or a bundled recipe (no SQL to invent): + +```bash +codemap query --json --recipe find-symbol-definitions --params name=createCodemap +``` + +`--json` is what agents and automation want; omit it for `console.table` in a terminal. + +## Wire agents (optional) + +```bash +codemap agents init --mcp +``` + +That scaffolds thin pointer rules/skills under `.agents/` and writes PM-aware MCP config (`npx`, `pnpm exec`, `bunx`, …). Full content is served live by `codemap skill` / `codemap rule` (and MCP resources `codemap://skill` / `codemap://rule`) — updating the package refreshes what agents see. + +Next: [CLI overview](/guides/cli-overview) · [Agents & MCP](/guides/agents-mcp) · [Recipes](/recipes). diff --git a/apps/docs/content/guides/github-action.mdx b/apps/docs/content/guides/github-action.mdx new file mode 100644 index 00000000..a4b33bf0 --- /dev/null +++ b/apps/docs/content/guides/github-action.mdx @@ -0,0 +1,95 @@ +--- +title: GitHub Action +description: Run Codemap audits in CI — SARIF, PR comments, and fail-on gates. +search: + tags: ["guide", "ci", "action"] +--- + +The composite Action runs the Codemap CLI in CI — default on `pull_request` is an audit against the PR base, emitting SARIF for Code Scanning. + +## Minimal workflow + +```yaml +name: Codemap +on: + pull_request: +jobs: + audit: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write # SARIF upload + pull-requests: write # only if pr-comment: true + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: stainless-code/codemap@main # pin a tag/sha in production +``` + +Default `mode: audit` uses `github.base_ref` when `audit-base` is empty. On non-PR events with no explicit `command:`, the Action no-ops. + +## Modes + +| `mode` | Behavior | +| --------- | ------------------------------------------------------------------------ | +| `audit` | `codemap audit --base --format ` (default on PRs) | +| `recipe` | `codemap query --recipe ` — set `recipe` (+ optional `params`) | +| `command` | Escape hatch — raw CLI args; overrides mode/recipe inputs | + +`mode: aggregate` is reserved and currently rejected. + +## Inputs + +| Input | Notes | +| ------------------- | ---------------------------------------------------------------------- | +| `working-directory` | Monorepo subdirectory | +| `package-manager` | Override autodetect (`npm` / `pnpm` / `yarn` / `bun`, …) | +| `version` | Pin CLI; empty → project dep or `dlx @latest` | +| `mode` / `recipe` | See Modes | +| `params` | Multiline `key=value` for parametrised recipes (`mode: recipe`) | +| `baseline` | Saved baseline name → `query --baseline` (`mode: recipe`) | +| `audit-base` | Git ref for `audit --base`; empty → `github.base_ref` on PRs | +| `format` | Default `sarif`; also `json`, `annotations`, … | +| `output-path` | Written artifact path (default `codemap.sarif`) | +| `upload-sarif` | Default `true` — needs Advanced Security on private repos | +| `pr-comment` | Opt-in markdown summary via `codemap pr-comment` | +| `fail-on` | `any` (default) or `never` | +| `changed-since` | Filter rows to files changed since a ref | +| `group-by` | `owner` / `directory` / `package` | +| `state-dir` | Override `.codemap/` | +| `token` | SARIF upload + PR comment; empty → `github.token` | +| `command` | Raw CLI args (overrides mode / recipe / baseline / …) | + +## Outputs + +| Output | Notes | +| ---------------- | -------------------------------------------------- | +| `agent` | Resolved package manager | +| `exec` | Shell-ready invoke string | +| `install_method` | `project-installed` / `dlx-pinned` / `dlx-latest` | +| `output-file` | Echo of `output-path` | + +Recipe example: + +```yaml +- uses: stainless-code/codemap@main + with: + mode: recipe + recipe: deprecated-symbols + format: sarif + params: | + # optional key=value lines +``` + +Audit against an explicit base: + +```yaml +- uses: stainless-code/codemap@main + with: + mode: audit + audit-base: origin/main + output-path: codemap-audit.sarif +``` + +List recipe ids locally with `codemap query --recipes-json`. Baselines: [Audit & baselines](/guides/audit-baselines). Formats: [Formats](/reference/formats). CLI twin: [CLI overview](/guides/cli-overview). diff --git a/apps/docs/content/guides/index.mdx b/apps/docs/content/guides/index.mdx new file mode 100644 index 00000000..ceca7cbe --- /dev/null +++ b/apps/docs/content/guides/index.mdx @@ -0,0 +1,22 @@ +--- +title: Guides +description: Task-oriented guides — CLI, MCP, config, CI, and the library API. +search: + tags: ["guide"] +--- + +Pick a guide by job: + +| Guide | Job | +| ---------------------------------------------- | ------------------------------------------------ | +| [Getting started](/guides/getting-started) | Install, index, first query | +| [CLI overview](/guides/cli-overview) | Daily commands — query, recipes, show, impact | +| [Agents & MCP](/guides/agents-mcp) | Templates, MCP, HTTP (`codemap serve`) | +| [Apply & rename](/guides/apply) | Recipe apply, rows, diffs, rename | +| [Audit & baselines](/guides/audit-baselines) | `--save-baseline`, `audit --base`, PR attribution| +| [Coverage & churn](/guides/coverage-churn) | `ingest-coverage` / `ingest-churn` + risk recipes| +| [Config](/guides/config) | Globs, boundaries, FTS5, churn | +| [GitHub Action](/guides/github-action) | CI audits → SARIF / PR comments | +| [Programmatic](/guides/programmatic) | `createCodemap` / `defineConfig` | + +Product framing: [Concepts](/concepts). Named SQL patterns: [Recipes](/recipes). Flags and types: [Reference](/reference). diff --git a/apps/docs/content/guides/meta.ts b/apps/docs/content/guides/meta.ts new file mode 100644 index 00000000..699e4cb7 --- /dev/null +++ b/apps/docs/content/guides/meta.ts @@ -0,0 +1,17 @@ +import { defineMeta } from "blume"; + +export default defineMeta({ + title: "Guides", + icon: "book-open", + pages: [ + "getting-started", + "cli-overview", + "agents-mcp", + "apply", + "audit-baselines", + "coverage-churn", + "config", + "github-action", + "programmatic", + ], +}); diff --git a/apps/docs/content/guides/programmatic.mdx b/apps/docs/content/guides/programmatic.mdx new file mode 100644 index 00000000..8610f340 --- /dev/null +++ b/apps/docs/content/guides/programmatic.mdx @@ -0,0 +1,48 @@ +--- +title: Programmatic +description: Use Codemap as a library — createCodemap, defineConfig, and language adapters. +search: + tags: ["guide", "api"] +--- + +Embed the same index the CLI uses — scripts, custom tools, test harnesses. Exhaustive types and JSDoc: [API reference](/reference/api). + +## Quick start + +```ts +import { createCodemap } from "@stainless-code/codemap"; + +const cm = await createCodemap({ root: "/path/to/repo" }); +await cm.index({ mode: "incremental" }); +await cm.index({ mode: "full" }); +await cm.index({ mode: "files", files: ["src/a.ts"] }); + +const rows = cm.query("SELECT name FROM symbols LIMIT 5"); +``` + +`createCodemap` configures a process-global runtime. **One active project root per process** — a second call with a different `root` throws. Re-init with the same root is fine. + +## Config helpers + +```ts +import { defineConfig, parseCodemapUserConfig } from "@stainless-code/codemap"; + +export default defineConfig({ + include: ["src/**/*.{ts,tsx}"], + fts5: false, +}); +``` + +Pass inline overrides: `createCodemap({ root, config: { fts5: true } })`. File path: `configFile` (same as CLI `--config`). See [Config](/guides/config). + +## Also exported + +| Export | Role | +| --------------------------------------------------- | ----------------------------------------- | +| `createCodemap` / `Codemap` | Index + `query` handle | +| `defineConfig` / `codemapUserConfigSchema` | User config | +| `BUILTIN_ADAPTERS` / `getAdapterForExtension` | Language adapters | +| `LanguageAdapter` / `ParsedFilePayload` / … | Adapter types | +| `CODEMAP_VERSION` | Package version string | + +Prefer `createCodemap` over holding a raw DB handle. Generated TypeDoc for every export: [/reference/api](/reference/api). diff --git a/apps/docs/content/recipes/affected-tests.mdx b/apps/docs/content/recipes/affected-tests.mdx new file mode 100644 index 00000000..2f44c4a2 --- /dev/null +++ b/apps/docs/content/recipes/affected-tests.mdx @@ -0,0 +1,37 @@ +--- +title: affected-tests +description: Find tests likely affected by changed source paths. +search: + tags: ["recipe"] +--- + +Reverse dependency walk from changed sources → test files that import them (or match test detection). Not a verdict — CI composes the runner and exit policy. + +Prefer the CLI/MCP convenience verb (builds `changed_files` for you): + +```bash +codemap affected --json +git diff --name-only origin/main | codemap affected --stdin --json +codemap affected src/lib/cache.ts --json +codemap affected --changed-since origin/main --json +``` + +Recipe form (when you already have paths): + +```bash +codemap query --json --recipe affected-tests --params changed_files=src/lib/cache.ts +``` + +Multiple paths for `query_recipe` / recipe params are joined with ASCII RS (char 30) — the `affected` verb handles that. + +## Params + +| Param | Required | Default | Notes | +| --------------- | -------- | ------- | --------------------------------------------------------------------- | +| `changed_files` | yes | — | Project-relative paths (RS-delimited when multiple) | +| `test_glob` | no | — | SQLite `GLOB` on `files.path`; **replaces** default `*.test.*` / `*.spec.*` suffix globs when set. Empty string keeps `test_suites` only. | +| `max_depth` | no | `50` | Max reverse-dependency hops (`0` = only directly-changed test files) | + +## Rows + +Each row: `test_path`, `impact_depth` (`0` = the test file itself changed). Catalog: `codemap query --recipes-json`. diff --git a/apps/docs/content/recipes/fan-in.mdx b/apps/docs/content/recipes/fan-in.mdx new file mode 100644 index 00000000..4f466c6f --- /dev/null +++ b/apps/docs/content/recipes/fan-in.mdx @@ -0,0 +1,21 @@ +--- +title: fan-in +description: Rank files by how many other files import them (import hubs). +search: + tags: ["recipe"] +--- + +High fan-in means changes ripple through many consumers — protect with tests before refactoring. + +```bash +codemap query --json --recipe fan-in +codemap hotspots --json # outcome alias → same recipe +``` + +No params. The `dependencies` table aggregates static imports, dynamic imports, and resolved module-graph edges. + +:::note +`hotspots` / `fan-in` rank **import hubs**. Change-frequency × complexity is a different recipe: `churn-complexity-hotspots`. +::: + +Inspect SQL: `codemap query --print-sql fan-in`. Full catalog: `codemap query --recipes-json`. Related: `codemap impact ` for a single target’s dependents. diff --git a/apps/docs/content/recipes/find-symbol-definitions.mdx b/apps/docs/content/recipes/find-symbol-definitions.mdx new file mode 100644 index 00000000..b39dafd0 --- /dev/null +++ b/apps/docs/content/recipes/find-symbol-definitions.mdx @@ -0,0 +1,25 @@ +--- +title: find-symbol-definitions +description: Locate every definition of a named symbol with column-precise positions. +search: + tags: ["recipe"] +--- + +Fast tier — equality on `name` (same idea as `codemap show `). + +```bash +codemap query --json --recipe find-symbol-definitions --params name=usePermissions +``` + +## Params + +| Param | Required | Notes | +| ------ | -------- | --------------------------------------------------------------------- | +| `name` | yes | Exact symbol name (case-sensitive). For `LIKE` patterns, use `find-symbol-by-kind` or `show --query 'name:%pat%'`. | + +## When to use it + +- Jump-to-definition for agents before grepping +- Feed `rename-preview` — preview with `codemap apply rename-preview --params old=,new=NEW --dry-run` + +Rows include `file_path`, `line_start`, and `name_column_start` / `name_column_end` (byte offsets on that line). Full catalog: `codemap query --recipes-json`. Twin without a recipe: `codemap show `. diff --git a/apps/docs/content/recipes/index.mdx b/apps/docs/content/recipes/index.mdx new file mode 100644 index 00000000..4a3dccbe --- /dev/null +++ b/apps/docs/content/recipes/index.mdx @@ -0,0 +1,137 @@ +--- +title: Recipes +description: Bundled query recipes — find symbols, fan-in, affected tests, and more. +search: + tags: ["recipe"] +--- + +Hand-rolling joins across `symbols`, `calls`, and `dependencies` is slow. Recipes are named SQL patterns — `codemap query --recipe ` (MCP: `query_recipe`). Prefer a recipe until you know the join paths. + +## Featured + +| Recipe | Outcome | +| ----------------------------------------------------------- | ------------------------------------------------ | +| [find-symbol-definitions](/recipes/find-symbol-definitions) | Exact-name definition rows (file + column range) | +| [affected-tests](/recipes/affected-tests) | Tests that transitively import changed sources | +| [fan-in](/recipes/fan-in) | Top files by how many others depend on them | + +## Catalog truth + +```bash +codemap query --recipes-json +codemap query --print-sql +``` + +Project overrides live in `.codemap/recipes/` ([Config](/guides/config)). Params and per-row actions are in each recipe’s companion `.md`. Tables below list every bundled id by theme — one-line outcome only; SQL stays in the catalog / `--print-sql`. + +CI presentation (`--format sarif` / `codeclimate` / `badge`): [Formats](/reference/formats). Diff-shape rows → [Apply](/guides/apply). Coverage / churn unlock: [Coverage & churn](/guides/coverage-churn). + +## Symbol & reference lookup + +| Id | Outcome | +| -------------------------- | ----------------------------------------------------------------------- | +| `find-symbol-definitions` | Exact-name definitions (`WHERE name = ?` — same tier as `codemap show`) | +| `find-symbol-by-kind` | Symbols by `kind` + `name_pattern` (`LIKE`) | +| `find-symbol-references` | Binding-resolved references to a definition (name + defining file) | +| `find-references` | Every identifier use matching a name (write flag + enclosing scope) | +| `find-call-sites` | Parse-resolved call sites of a named function (AST provenance only) | +| `find-export-sites` | Direct exports and re-exports of a named binding | +| `find-import-sites` | Import sites of a named binding across files | +| `find-jsx-usages` | JSX element rows for a component / tag name | +| `find-by-param-type` | Parameters whose type annotation exactly matches a string | +| `find-decorator-usage` | Decorator sites linked to decorated symbols when resolvable | +| `find-async-functions` | Async functions with stringified return type | +| `find-throws-jsdoc` | Structured `@throws` tags from JSDoc | +| `find-write-sites` | Writes to an identifier (assignments, mutations, declarations) | +| `find-re-exported-bindings` | Identifier refs resolved via a re-export chain | +| `find-dynamic-imports` | Dynamic `import()` sites (literal specs may resolve to a path) | +| `markers-by-kind` | Marker counts by kind (`TODO`, `FIXME`, …) | +| `visibility-tags` | Symbols with JSDoc visibility tags (`public` / `private` / …) | +| `components-by-hooks` | React components ranked by hook count | +| `tests-by-file` | Test counts per test file | +| `env-var-audit` | Distinct `process.env.X` accesses with use count and file fan-out | + +## Graphs & types + +| Id | Outcome | +| --------------------------- | ------------------------------------------------------------------------------------------------ | +| `call-path` | Shortest path between two symbols on `calls` (optional import fallback; AST provenance) | +| `fan-in` | Top files by how many others depend on them | +| `fan-out` | Top files by dependency edge count | +| `fan-out-sample` | Fan-out leaders plus sample dependency targets | +| `fan-out-sample-json` | Same as `fan-out-sample` with `sample_targets` as a JSON array | +| `type-ancestors` | Transitive `extends` + direct `implements` for a class / interface | +| `type-descendants` | Symbols that `extends` / `implements` a type (pass `file_path` on homonyms) | +| `symbol-neighborhood` | Callers, callees, and one-hop file dependencies around a symbol | +| `circular-imports` | Files in import cycles, grouped by `cycle_id` | +| `calls-including-heuristic` | Heuristic callback-synthesis edges (`provenance = 'heuristic'`) — needs `synthesis.heuristicCalls: true` | +| `unresolved-call-sites` | Call sites that did not resolve after the call-resolution pass | +| `barrel-chains` | Resolved re-export chains to terminal definitions | +| `barrel-files` | Top files by export count (barrel / public-API candidates) | +| `find-barrel-files` | Files flagged `is_barrel = 1` | +| `affected-tests` | Tests that transitively import changed sources (also `codemap affected`) | + +## CI / dead code / boundaries + +| Id | Outcome | +| ------------------------------- | ------------------------------------------------------------------------------------ | +| `deprecated-symbols` | Symbols with `@deprecated` JSDoc (`reason` / `evidence_json` on rows) | +| `unimported-exports` | Exports with no import row for that file + name | +| `boundary-violations` | Import edges matching a `boundaries.deny` rule in config | +| `untested-and-dead` | Exported functions that look structurally dead and lack measured coverage | +| `stale-imports` | Diff-shape unused import specifiers (structural; not a formatter) | +| `unused-type-members` | Exported type members never directly imported | +| `components-touching-deprecated` | Components that hook or call `@deprecated` symbols | +| `text-in-deprecated-functions` | `@deprecated` functions in files with TODO/FIXME/HACK and low coverage | +| `find-side-effect-files` | Files with module-level side effects (`has_side_effects = 1`) | +| `find-side-effect-imports` | Side-effect-only imports (`import "./mod"` with no bindings) | + +## Coverage & churn risk + +Needs coverage and/or churn data in the index — see [Coverage & churn](/guides/coverage-churn). Without ingest, some recipes still run on graph estimates; parse `coverage_source` before gating CI. + +| Id | Outcome | +| ---------------------------- | ----------------------------------------------------------------------------------------------- | +| `worst-covered-exports` | Worst-covered exported functions (test-writing targets) | +| `files-by-coverage` | Files ranked ascending by statement coverage | +| `coverage-confirmed-dead` | Structurally dead exports with an explicit coverage `confidence` column | +| `high-crap-score` | Symbols ranked by CRAP (`CC² × (1 − coverage/100)³ + CC`) — check `coverage_source` | +| `churn-complexity-hotspots` | Files/symbols by churn × cyclomatic complexity (not the `hotspots` alias → `fan-in`) | +| `refactor-risk-ranking` | Files by `(fan_in + 1) × (100 − avg_coverage_pct)` | +| `high-complexity-untested` | Functions with cyclomatic complexity ≥ 10 and measured coverage < 50% | + +## Apply / migrate + +Diff-shape rows (`file_path`, `line_start`, `before_pattern`, `after_pattern`) feed `codemap apply`. Workflow: [Apply](/guides/apply). Preview with `--format diff` / `diff-json`. + +| Id | Outcome | +| ---------------------- | ---------------------------------------------------------------------------- | +| `rename-preview` | Diff preview for symbol renames (also `codemap rename`) | +| `migrate-deprecated` | Migrate call sites / usages of a deprecated symbol to a replacement | +| `migrate-import-source` | Exact-match import `source` path migration | +| `migrate-jsx-prop` | JSX attribute name renames | +| `add-jsdoc-deprecated` | Prepend `@deprecated` JSDoc above `export function ` definitions | +| `deprecated-usages` | Rewrite the first line of an existing `@deprecated` block (docs sync) | +| `replace-marker-kind` | Replace marker kind tokens on disk (e.g. `TODO` → `FIXME`) | + +## Smells & quality + +| Id | Outcome | +| -------------------------- | -------------------------------------------------------------------- | +| `duplicates` | Symbols whose `body_hash` collides (identical function bodies) | +| `large-functions` | Functions / methods with `body_line_count` ≥ 50 | +| `deeply-nested-functions` | Functions with nesting depth ≥ 4 | +| `high-cognitive-complexity` | Functions above cognitive-complexity threshold (default 15) | +| `find-await-in-loop` | `await` sites inside loop bodies | +| `find-swallowed-errors` | `catch` bodies that only log to `console.*` | +| `find-leftover-console` | Every `console.*` call site | +| `find-skipped-tests` | `describe.skip` / `it.skip` / `.only` / `.todo` sites | +| `files-largest` | Top files by line count | + +## Index / ops + +| Id | Outcome | +| ----------------------- | ------------------------------------------------------------------------ | +| `index-summary` | Single row: counts for files, symbols, imports, components, dependencies | +| `files-hashes` | Indexed files with `content_hash` (staleness inputs) | +| `call-resolution-stats` | Counts from the call-resolution phase (AST vs unresolved, …) | diff --git a/apps/docs/content/recipes/meta.ts b/apps/docs/content/recipes/meta.ts new file mode 100644 index 00000000..1057bc54 --- /dev/null +++ b/apps/docs/content/recipes/meta.ts @@ -0,0 +1,7 @@ +import { defineMeta } from "blume"; + +export default defineMeta({ + title: "Recipes", + icon: "flask-conical", + pages: ["find-symbol-definitions", "affected-tests", "fan-in"], +}); diff --git a/apps/docs/content/reference/api/index.mdx b/apps/docs/content/reference/api/index.mdx new file mode 100644 index 00000000..06c5662c --- /dev/null +++ b/apps/docs/content/reference/api/index.mdx @@ -0,0 +1,41 @@ +--- +title: API +description: Exhaustive CI-generated TypeDoc reference for the published @stainless-code/codemap library surface. +sidebar: + label: Overview +search: + tags: ["api", "reference"] +--- + +import Card from "blume/components/content/Card.astro"; +import CardGroup from "blume/components/content/CardGroup.astro"; + +One package entry — everything below is re-exported from `@stainless-code/codemap`. Quick start: [Programmatic](/guides/programmatic). Hub: [Reference](/reference). + +Experimental — the API may change between minor releases. Pin your version. Pre-1.0: breaking changes ship in **minor** releases (`0.x` → `0.y`), not majors. + +## Library surface + + + + Index / query runtime — `createCodemap`, `Codemap` + + + Config helpers + Zod schemas + + + `LanguageAdapter`, `BUILTIN_ADAPTERS`, … + + + Config, parse, and adapter types + + + +```ts +import { + createCodemap, + defineConfig, + BUILTIN_ADAPTERS, + CODEMAP_VERSION, +} from "@stainless-code/codemap"; +``` diff --git a/apps/docs/content/reference/api/meta.ts b/apps/docs/content/reference/api/meta.ts new file mode 100644 index 00000000..c2ece689 --- /dev/null +++ b/apps/docs/content/reference/api/meta.ts @@ -0,0 +1,8 @@ +import { defineMeta } from "blume"; + +export default defineMeta({ + title: "API", + icon: "code", + // TypeDoc single entry (`src/index.ts`) → `modules.mdx` (see typedoc.json entryFileName). + pages: ["modules"], +}); diff --git a/apps/docs/content/reference/cli.mdx b/apps/docs/content/reference/cli.mdx new file mode 100644 index 00000000..94cf25ac --- /dev/null +++ b/apps/docs/content/reference/cli.mdx @@ -0,0 +1,103 @@ +--- +title: CLI +description: Codemap CLI commands and flags. +search: + tags: ["reference", "cli"] +--- + +Live help always wins: `codemap --help` and `codemap --help`. Digest below mirrors the published CLI surface. + +## Index (default argv) + +```bash +codemap +codemap --full +codemap --files +codemap --root +codemap --config +codemap --state-dir +codemap --with-fts +codemap version # also: --version / -V +codemap unlock # clear stale index.lock +``` + +## query + +```bash +codemap query --json "" +codemap query --json --recipe [--params k=v,…] +codemap query --recipes-json +codemap query --print-sql +codemap query --summary +codemap query --changed-since +codemap query --group-by directory|owner|package +codemap query --save-baseline[=name] +codemap query --baseline[=name] +codemap query --baselines +codemap query --drop-baseline +codemap query --format +codemap query --ci # SARIF + non-zero on findings + quiet +``` + +N statements, one bootstrap (MCP `query_batch`): + +```bash +echo '{"statements":["SELECT 1","SELECT COUNT(*) AS n FROM symbols"]}' \ + | codemap query batch --stdin +codemap query batch --file queries.json --summary --compact +``` + +Outcome aliases (pass query flags through): `dead-code`, `deprecated`, `boundaries`, `hotspots` (→ `fan-in`), `coverage-gaps`. + +## Lookups & graphs + +```bash +codemap show [--kind …] [--in ] [--query '…'] [--print-sql] +codemap snippet […] +codemap impact [--direction up|down|both] [--via …] [--depth N] [--in ] +codemap affected [paths…] [--stdin] [--changed-since ] [--json] +codemap trace --from --to +codemap explore … [--depth N] [--kind …] [--budget-chars N] +codemap node +``` + +## Resource twins + +Same JSON as MCP / HTTP resources: + +```bash +codemap file # → codemap://files/{path} +codemap schema # → codemap://schema +codemap symbols [--in ] +``` + +## audit / apply / rename / ingest + +```bash +codemap audit --base [--json] [--summary] [--format sarif] [--ci] +codemap audit --baseline +codemap apply --params … [--dry-run|--yes] [--force] +codemap apply --yes --until-empty [--max-passes N] +codemap apply --yes --commit "" +codemap apply --rows - --yes +codemap apply --diff-input --dry-run +codemap rename [--define-in ] [--kind …] [apply flags…] +codemap ingest-coverage [--runtime] [--json] +codemap ingest-churn [--json] +codemap pr-comment +``` + +## Agents & transports + +```bash +codemap agents init [--force] [--mcp] [--interactive] [--targets …] [--git-hooks] +codemap skill +codemap rule +codemap mcp [--no-watch] +codemap serve [--port N] [--host …] [--token …] [--no-watch] +codemap watch [--debounce ms] [--quiet] +codemap context [--compact] [--for ""] [--json] +codemap validate [--json] +``` + +Guides: [CLI overview](/guides/cli-overview) · [Apply](/guides/apply) · [Audit & baselines](/guides/audit-baselines) · [Agents & MCP](/guides/agents-mcp). Env: [Env](/reference/env). Formats: [Formats](/reference/formats). diff --git a/apps/docs/content/reference/env.mdx b/apps/docs/content/reference/env.mdx new file mode 100644 index 00000000..055a28c4 --- /dev/null +++ b/apps/docs/content/reference/env.mdx @@ -0,0 +1,22 @@ +--- +title: Env +description: Environment variables that affect Codemap CLI and serve. +search: + tags: ["reference", "env"] +--- + +CLI flags override env when both exist. Prefer project config ([Config](/guides/config)) for durable settings. + +| Variable | Role | +| ---------------------------- | -------------------------------------------------------------------- | +| `CODEMAP_ROOT` | Project root when `--root` omitted (also `CODEMAP_TEST_BENCH`) | +| `CODEMAP_STATE_DIR` | State directory (default `.codemap/`); `--state-dir` wins | +| `CODEMAP_WATCH` | `0` / `false` opts out of default-ON watcher on `mcp` / `serve` | +| `CODEMAP_NO_WATCH` | `1` — same opt-out as `CODEMAP_WATCH=0` | +| `CODEMAP_FORCE_WATCH` | `1` — override WSL `/mnt/*` auto-disable | +| `CODEMAP_MCP_TOOLS` | Comma-separated MCP tool allowlist (snake_case names) | +| `CODEMAP_PARSE_TIMEOUT_MS` | Fixed per-file parse budget (ms); unset = 10s + size scaling (cap 30s) | +| `CODEMAP_PARSE_WORKERS` | Worker pool size (positive integer, max 32) | +| `CODEMAP_WORKER_RECYCLE_EVERY` | Recycle workers after N files (default `250`) | + +HTTP serve auth uses `--token` (not an env default). Watcher / git-hooks guidance: [Index lifecycle](/concepts/index-lifecycle) · [Agents & MCP](/guides/agents-mcp). diff --git a/apps/docs/content/reference/formats.mdx b/apps/docs/content/reference/formats.mdx new file mode 100644 index 00000000..43051820 --- /dev/null +++ b/apps/docs/content/reference/formats.mdx @@ -0,0 +1,30 @@ +--- +title: Formats +description: Codemap query output formats — JSON, SARIF, Code Climate, badge, and more. +search: + tags: ["reference", "formats"] +--- + +`--format` (and `--ci`) apply to flat row lists — not `--summary` / `--group-by` / baseline envelopes. Use JSON for triage; use SARIF / badge / annotations for gates. Full set: `text` | `json` | `sarif` | `annotations` | `mermaid` | `diff` | `diff-json` | `codeclimate` | `badge`. + +| Format | Use | +| -------------- | ---------------------------------------------------------------- | +| `text` | Human table / text (CLI default) | +| `json` | Machine shape (`--json`); agents and automation | +| `sarif` | SARIF 2.1.0 → GitHub Code Scanning | +| `annotations` | GitHub Actions `::notice` lines | +| `mermaid` | Graph edges — needs `{from, to, …}` rows; rejects >50 edges | +| `diff` | Unified edit preview from `{file_path, line_start, before_pattern, after_pattern}` | +| `diff-json` | Same row contract as JSON (feeds [Apply](/guides/apply)) | +| `codeclimate` | GitLab Code Quality artifact (locatable rows; flat `minor`) | +| `badge` | Issue-count summary; `--badge-style json` for CI gates | + +```bash +codemap query --recipe deprecated-symbols --format sarif +codemap query --recipe deprecated-symbols --ci +codemap query --recipe boundary-violations --format codeclimate +codemap query --recipe boundary-violations --format badge --badge-style json +codemap audit --base origin/main --format sarif +``` + +`rule.id` is `codemap.` (or `codemap.adhoc`). SARIF / annotations / codeclimate / badge auto-detect path columns (`file_path` / `path` / `to_path` / `from_path`). CI wiring: [GitHub Action](/guides/github-action). diff --git a/apps/docs/content/reference/index.mdx b/apps/docs/content/reference/index.mdx new file mode 100644 index 00000000..27872cb3 --- /dev/null +++ b/apps/docs/content/reference/index.mdx @@ -0,0 +1,17 @@ +--- +title: Reference +description: CLI flags, env vars, MCP tools, output formats, and the generated library API. +search: + tags: ["reference"] +--- + +| Page | Contents | +| ----------------------------- | ------------------------------------------------------- | +| [CLI](/reference/cli) | Commands and common flags | +| [Env](/reference/env) | Environment variables | +| [MCP](/reference/mcp) | Tools and resources | +| [Formats](/reference/formats) | JSON, SARIF, Code Climate, badge, … | +| [API](/reference/api) | Generated TypeDoc for `@stainless-code/codemap` | +| [Roadmap](/reference/roadmap) | Forward-looking work (not a changelog) | + +Task-oriented walkthroughs: [Guides](/guides). Named SQL patterns: [Recipes](/recipes). diff --git a/apps/docs/content/reference/mcp.mdx b/apps/docs/content/reference/mcp.mdx new file mode 100644 index 00000000..d317b752 --- /dev/null +++ b/apps/docs/content/reference/mcp.mdx @@ -0,0 +1,78 @@ +--- +title: MCP +description: Codemap MCP tools and resources for agent sessions. +search: + tags: ["reference", "mcp"] +--- + +Start with `codemap agents init --mcp`, then `codemap mcp` (stdio; watcher default-ON). HTTP twin: `codemap serve` → `POST /tool/{name}`. Wiring guide: [Agents & MCP](/guides/agents-mcp). + +## Session start + +1. Call **`context`** — root, schema version, recipe cards, hub leaders, `index_freshness`, optional `codebase_map` / `map_id`. +2. Read **`codemap://rule`** (always-on priming: query the index for structure, don’t grep). +3. Catalog / DDL when needed: **`codemap://recipes`**, **`codemap://schema`**. + +MCP initialize also injects operational **`instructions`** (tool selection playbook). Full narrative stays on `codemap://skill` / `codemap://rule`. + +## All 21 tools + +| Tool | Role | +| ------------------- | -------------------------------------------------------------------- | +| `context` | Session bootstrap — freshness, hubs, recipe cards, optional map | +| `validate` | Per-file staleness | +| `query` | Ad-hoc SQL | +| `query_batch` | N statements / one round-trip | +| `query_recipe` | Named recipe by id | +| `show` | Exact / field-qualified symbol lookup | +| `snippet` | Same rows as `show` + disk text | +| `impact` | Blast radius (callers / dependents) | +| `trace` | Call path + snippets | +| `explore` | Multi-symbol neighborhood survey | +| `node` | One-hop symbol card | +| `affected` | Changed sources → tests | +| `audit` | Drift vs git `base` and/or baseline prefix / per-delta baselines | +| `save_baseline` | Snapshot rows (`{name, sql? \| recipe?}`) | +| `list_baselines` | Saved baselines | +| `drop_baseline` | Delete a baseline by name | +| `ingest_coverage` | Load Istanbul / LCOV / V8 coverage | +| `ingest_churn` | Load precomputed `file_churn` JSON | +| `apply` | Apply a recipe’s diff rows (`yes: true` for writes) | +| `apply_rows` | Apply pre-built rows | +| `apply_diff_input` | Apply unified diff text | + +## Goal → tool (summary) + +| Goal | Tool | Recipe twin (when applicable) | +| ---------------------------- | ---------------------------- | ------------------------------------ | +| Exact symbol | `show` / `snippet` | `find-symbol-definitions` | +| Ad-hoc SQL | `query` / `query_batch` | — | +| Named pattern | `query_recipe` | any catalog id | +| Blast radius | `impact` | `fan-in` (file hubs) | +| Call path | `trace` | `call-path` | +| Neighborhood | `explore` / `node` | `symbol-neighborhood` | +| Tests to run | `affected` | `affected-tests` | +| Drift vs baseline / base | `audit` | — | +| Save / list / drop baseline | `save_baseline` / `list_baselines` / `drop_baseline` | — | +| Freshness / bootstrap | `context` / `validate` | — | +| Coverage / churn ingest | `ingest_coverage` / `ingest_churn` | — | +| Apply recipe / rows / diff | `apply` / `apply_rows` / `apply_diff_input` | — (writes need `yes: true`) | + +Output shapes match CLI `--json` envelopes (snake_case). Array tools append a second content block prefixed `@codemap/index_freshness`; object tools merge freshness inline. + +Baselines workflow: [Audit & baselines](/guides/audit-baselines). Apply: [Apply](/guides/apply). Coverage: [Coverage & churn](/guides/coverage-churn). + +Allowlist: `CODEMAP_MCP_TOOLS` — see [Env](/reference/env). + +## Resources + +| URI | Content | +| --------------------------- | -------------------------------------------- | +| `codemap://rule` | Always-on priming rule | +| `codemap://skill` | Full skill (recipes + schema + patterns) | +| `codemap://schema` | Live DDL | +| `codemap://recipes` | Catalog | +| `codemap://recipes/{id}` | One recipe | +| `codemap://mcp-instructions`| Initialize playbook text | +| `codemap://files/{path}` | Live file card | +| `codemap://symbols/{name}` | Live symbol card | diff --git a/apps/docs/content/reference/meta.ts b/apps/docs/content/reference/meta.ts new file mode 100644 index 00000000..b50158a1 --- /dev/null +++ b/apps/docs/content/reference/meta.ts @@ -0,0 +1,8 @@ +import { defineMeta } from "blume"; + +export default defineMeta({ + title: "Reference", + icon: "code", + pages: ["cli", "env", "mcp", "formats", "api", "roadmap"], +}); + diff --git a/apps/docs/content/reference/roadmap.mdx b/apps/docs/content/reference/roadmap.mdx new file mode 100644 index 00000000..4b89cfdc --- /dev/null +++ b/apps/docs/content/reference/roadmap.mdx @@ -0,0 +1,59 @@ +--- +title: Roadmap +description: Forward-looking work — not a mirror of shipped CLI or schema. +search: + tags: ["reference", "roadmap"] +sidebar: + badge: "Planned" +--- + +Shipped behavior lives in [Guides](/guides), [Concepts](/concepts), and the +[changelog](/changelog). This page is the forward-looking list. Pull requests +welcome — open an issue first for anything below so we can agree on shape. + +## Next + +- **Community language adapters** — optional packages (e.g. Tree-sitter) with a + peer dependency on `@stainless-code/codemap` and a public registration API + beyond the built-in adapters. +- **GitHub Marketplace Action listing** — publish the in-tree Action + (`action.yml`, SARIF / annotations, CI helpers) to the Marketplace with + floating `v1` tags. +- **LSP diagnostic-push** — recipes as editor diagnostics (not rename / + go-to-definition; TypeScript already owns those). +- **Framework route extraction** — Express / React Router / NestJS-style + `http_routes` substrate for reachability recipes. +- **FTS default-on evaluation** — measure the DB size tax of defaulting + `source_fts` on; today full-text search stays opt-in (`--with-fts` / + `fts5: true`). + +## Later + +- **C.9 framework plugin layer** — declarative entry-point hints (globs + + optional AST parse of tool configs) so dead-code / unimported-export recipes + respect Vite / Next / Vitest roots — no JS eval at index time. +- **Zero-deps shell installer** — `curl | sh` / PowerShell binary fetch beside + npm for consumers without a JS toolchain. +- **MCP shared daemon per project** — one watcher + one SQLite writer shared + across concurrent agent sessions (long-running `mcp` / `serve` only; one-shot + CLI stays cold-start fast). +- **Monorepo / workspace awareness** — discover workspaces and index + per-workspace dependency graphs. + +## Out of scope + +Codemap stays a structural-index primitive. In particular: + +- **SQL (and recipes) stay the API** — no pre-baked pass/fail verdict primitive; + SARIF / audit deltas are output modes. +- **No rename / go-to-def LSP engine** — read-side `show` / `snippet` / `impact` + already cover agent lookup; diagnostic-push is the only LSP track above. +- **No LLM or embeddings in the box** — the agent host owns meaning; we supply + structure. +- **No opinionated autofix engine** — `codemap apply` executes explicit + recipe/agent diff rows with confirmation gates. +- **No telemetry upload, no remote-repo clone-and-index** — local checkout is + the source of truth. + +Maintainer detail (plans, floors, perf triggers) lives in the repo’s +[`docs/roadmap.md`](https://github.com/stainless-code/codemap/blob/main/docs/roadmap.md). diff --git a/apps/docs/package.json b/apps/docs/package.json new file mode 100644 index 00000000..2f5575f3 --- /dev/null +++ b/apps/docs/package.json @@ -0,0 +1,16 @@ +{ + "name": "@stainless-code/codemap-docs", + "private": true, + "type": "module", + "scripts": { + "audit": "blume audit --fail-on error --skip canonical_bad_target,non_canonical_in_sitemap,indexable_page_not_in_sitemap,BLUME_AUDIT_LINK_TO_BROKEN", + "build": "blume build", + "check": "blume check", + "dev": "blume dev", + "preview": "blume preview", + "validate": "blume validate" + }, + "dependencies": { + "blume": "1.1.2" + } +} diff --git a/apps/docs/pages/404.astro b/apps/docs/pages/404.astro new file mode 100644 index 00000000..71b6108e --- /dev/null +++ b/apps/docs/pages/404.astro @@ -0,0 +1,81 @@ +--- +import PageLayout from "blume/components/layout/PageLayout.astro"; +import { withBase } from "blume/components/islands/base-path.ts"; +import { contentHref } from "blume/components/content/base-href.ts"; +import data from "blume:data"; +import { CURATED_POPULAR } from "../components/curated-popular"; + +export const prerender = true; + +const { config } = data; +const site = { description: config.description, title: config.title }; + +const popular = CURATED_POPULAR.map(({ route, label }) => ({ + href: contentHref(route), + label, +})); +--- + + + + diff --git a/apps/docs/pages/_home/Batteries.astro b/apps/docs/pages/_home/Batteries.astro new file mode 100644 index 00000000..3858f626 --- /dev/null +++ b/apps/docs/pages/_home/Batteries.astro @@ -0,0 +1,56 @@ +--- +import Card from "blume/components/content/Card.astro"; +import CardGroup from "blume/components/content/CardGroup.astro"; +import { contentHref } from "blume/components/content/base-href.ts"; +--- + +
+
+

+ Batteries included. +

+

+ Recipes, MCP, CI, and agent scaffolding — same index, adopt what you need. +

+
+ +
+ + + Bundled SQL patterns for symbol lookup, impact, dead code, and CI + formats. + + + Query the index from Cursor and other MCP clients — same recipes as the + CLI. + + + Run recipes in CI with SARIF, annotations, and badge exit codes. + + + Scaffold version-matched rules and skills that stay in sync with the + package. + + +
+
diff --git a/apps/docs/pages/_home/FinalCta.astro b/apps/docs/pages/_home/FinalCta.astro new file mode 100644 index 00000000..1f918e08 --- /dev/null +++ b/apps/docs/pages/_home/FinalCta.astro @@ -0,0 +1,43 @@ +--- +import { contentHref } from "blume/components/content/base-href.ts"; +import InstallBox from "./InstallBox.astro"; + +const primaryButton = + "inline-flex items-center gap-2 rounded-full bg-foreground px-5 py-2.5 font-medium text-background text-sm transition-opacity hover:opacity-90"; +const secondaryButton = + "inline-flex items-center gap-2 rounded-full border border-border px-5 py-2.5 font-medium text-foreground text-sm transition-colors hover:border-foreground"; +--- + +
+

+ Start querying your codebase. +

+

+ Dev dependency or one-shot via bunx / npx / yarn dlx / pnx — index once, + then query with SQL or a recipe. +

+
+ +
diff --git a/apps/docs/pages/_home/Hero.astro b/apps/docs/pages/_home/Hero.astro new file mode 100644 index 00000000..005f83bc --- /dev/null +++ b/apps/docs/pages/_home/Hero.astro @@ -0,0 +1,72 @@ +--- +import CodeBlock from "blume/components/content/CodeBlock.astro"; +import { contentHref } from "blume/components/content/base-href.ts"; +import InstallBox from "./InstallBox.astro"; +import { cliSnippet } from "./source-snippets.ts"; +--- + +
+

+ Stop scanning for one symbol. + Query your codebase. +

+ +

+ Local codebase intelligence: a SQLite index of symbols, imports, and calls — + SQL and recipes for agents, not another grep pass. +

+ + {/* Blume CodeBlock fills the column — shrink-wrap like InstallBox. */} +
+ +
+ +
+ + +
diff --git a/apps/docs/pages/_home/HowItWorks.astro b/apps/docs/pages/_home/HowItWorks.astro new file mode 100644 index 00000000..d6ee38cc --- /dev/null +++ b/apps/docs/pages/_home/HowItWorks.astro @@ -0,0 +1,49 @@ +--- +import { contentHref } from "blume/components/content/base-href.ts"; + +const steps = [ + { + title: "Index", + body: "One local SQLite map of structure", + }, + { + title: "Query", + body: "SQL or bundled recipe", + }, + { + title: "Join", + body: "Compose tables in one predicate", + }, +]; +--- + +
+
+

+ How it works. +

+
+ +
+ { + steps.map((step, i) => ( +
+

+ {String(i + 1).padStart(2, "0")} +

+

{step.title}

+

{step.body}

+
+ )) + } +
+ + +
diff --git a/apps/docs/pages/_home/InstallBox.astro b/apps/docs/pages/_home/InstallBox.astro new file mode 100644 index 00000000..32557512 --- /dev/null +++ b/apps/docs/pages/_home/InstallBox.astro @@ -0,0 +1,31 @@ +--- +import CodeBlock from "blume/components/content/CodeBlock.astro"; +import Icon from "blume/components/Icon.astro"; + +const installCommand = "bunx @stainless-code/codemap"; +--- + +
+ + {/* Strip CodeBlock chrome — chip owns the frame; keep Shiki tokens. */} +
+ +
+ +
diff --git a/apps/docs/pages/_home/UseCases.astro b/apps/docs/pages/_home/UseCases.astro new file mode 100644 index 00000000..f5b42ad3 --- /dev/null +++ b/apps/docs/pages/_home/UseCases.astro @@ -0,0 +1,59 @@ +--- +import { contentHref } from "blume/components/content/base-href.ts"; + +const cases = [ + { + question: "Where is createCodemap defined?", + recipe: "find-symbol-definitions", + }, + { + question: "Which tests does this change touch?", + recipe: "affected-tests", + }, + { + question: "What depends on this file?", + recipe: "fan-in", + }, +]; +--- + +
+
+

+ Ask structure, not grep. +

+

+ Common agent questions map to one bundled recipe — CLI, MCP, or HTTP. +

+
+ +
+ { + cases.map((item) => ( + + + {item.question} + + + {item.recipe} + + → + + + + )) + } +
+ + +
diff --git a/apps/docs/pages/_home/source-snippets.ts b/apps/docs/pages/_home/source-snippets.ts new file mode 100644 index 00000000..bf690aec --- /dev/null +++ b/apps/docs/pages/_home/source-snippets.ts @@ -0,0 +1,12 @@ +export interface CliSnippet { + id: string; + lang: string; + code: string; +} + +/** Single hero CLI example — no live demo islands. */ +export const cliSnippet: CliSnippet = { + id: "find-symbol-definitions", + lang: "bash", + code: "codemap query --recipe find-symbol-definitions -p name=createCodemap", +}; diff --git a/apps/docs/pages/index.astro b/apps/docs/pages/index.astro new file mode 100644 index 00000000..e6200c37 --- /dev/null +++ b/apps/docs/pages/index.astro @@ -0,0 +1,49 @@ +--- +import PageLayout from "blume/components/layout/PageLayout.astro"; +import data from "blume:data"; +import Batteries from "./_home/Batteries.astro"; +import FinalCta from "./_home/FinalCta.astro"; +import Hero from "./_home/Hero.astro"; +import HowItWorks from "./_home/HowItWorks.astro"; +import UseCases from "./_home/UseCases.astro"; +import Footer from "../components/blume/Footer.astro"; + +const { config } = data; +const pageTitle = `${config.title} — Query your codebase.`; + +const copyScript = `(()=>{const CHECK='';document.addEventListener("click",async(e)=>{const b=e.target.closest("[data-blume-copy-install]");if(!b){return;}try{await navigator.clipboard.writeText(b.dataset.command);}catch{return;}const o=b.innerHTML;b.innerHTML=CHECK;setTimeout(()=>{b.innerHTML=o;},1500);});})();`; +--- + + +
+ + + + + +
+