nimbus-docs 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as resolveRuleForCollection, i as parseSource, n as RULES, o as validateLintOptions, s as isRuleCode, t as IMPLEMENTED_CODES } from "../rules-DDDvKkyJ.js";
2
+ import { a as resolveRuleForCollection, i as parseSource, n as RULES, o as validateLintOptions, s as isRuleCode, t as IMPLEMENTED_CODES } from "../rules-CzB-afEb.js";
3
3
  import { spawn } from "node:child_process";
4
4
  import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  import path, { dirname, join, relative, resolve } from "node:path";
@@ -49,6 +49,12 @@ const BUNDLED_INDEX = {
49
49
  "title": "Breadcrumbs",
50
50
  "description": "Page-context navigation crumbs."
51
51
  },
52
+ "button": {
53
+ "name": "button",
54
+ "type": "registry:ui",
55
+ "title": "Button",
56
+ "description": "Action trigger with variant/size/shape options. Owns the shared button/variants styling that LinkButton reuses."
57
+ },
52
58
  "callout": {
53
59
  "name": "callout",
54
60
  "type": "registry:ui",
@@ -119,7 +125,7 @@ const BUNDLED_INDEX = {
119
125
  "name": "link-button",
120
126
  "type": "registry:ui",
121
127
  "title": "LinkButton",
122
- "description": "Anchor styled as a button."
128
+ "description": "Anchor styled as a button. Shares styling with Button via button/variants."
123
129
  },
124
130
  "link-card": {
125
131
  "name": "link-card",
@@ -217,6 +223,12 @@ const BUNDLED_INDEX = {
217
223
  "title": "AI-native static surface",
218
224
  "description": "Add llms.txt, markdown variants, robots.txt, and an AgentDirective to a Nimbus docs site."
219
225
  },
226
+ "changelog": {
227
+ "name": "changelog",
228
+ "type": "registry:feature",
229
+ "title": "Changelog",
230
+ "description": "Add a reverse-chronological changelog at /changelog — a dated timeline feed that renders full entries inline, with tag filtering, year-grouped load-more pagination, per-entry permalinks, OG cards, markdown alternates, and an optional RSS feed. Generic: tags are opaque strings you define. For a feed-style changelog; for a docs-shaped tree use `nimbus-docs add new-collection`."
231
+ },
220
232
  "component-showcase": {
221
233
  "name": "component-showcase",
222
234
  "type": "registry:feature",
@@ -268,8 +280,8 @@ const BUNDLED_INDEX = {
268
280
  * Clears both locations:
269
281
  * - `node_modules/.astro/nimbus` — the default (rides Astro's cacheDir, the
270
282
  * dir hosts persist between builds).
271
- * - `.nimbus/cache` — the legacy location, still used when Astro's cacheDir
272
- * can't be resolved.
283
+ * - `.nimbus/cache` — the fallback, used when Astro's cacheDir can't be
284
+ * resolved.
273
285
  *
274
286
  * Note: if you've set a custom Astro `cacheDir`, remove `<cacheDir>/nimbus`
275
287
  * manually — the standalone CLI doesn't load your Astro config.
@@ -581,13 +593,12 @@ async function resolveComponentTree(rootSlug) {
581
593
  //#endregion
582
594
  //#region src/cli/feature.ts
583
595
  /**
584
- * Feature installer — Flue-style agent-handoff.
596
+ * Feature installer — agent-handoff.
585
597
  *
586
- * Same rule Flue uses for `flue add`: if `--print` is set OR
587
- * `determineAgent()` says the CLI is running inside a known coding agent,
588
- * the markdown is piped to stdout for the agent to consume. Otherwise we
589
- * print human-friendly instructions on stderr telling the user exactly
590
- * how to pipe the output to their agent of choice.
598
+ * If `--print` is set OR `determineAgent()` says the CLI is running inside
599
+ * a known coding agent, the markdown is piped to stdout for the agent to
600
+ * consume. Otherwise we print human-friendly instructions on stderr
601
+ * telling the user exactly how to pipe the output to their agent of choice.
591
602
  *
592
603
  * No picker, no clipboard mode — the printed pipe commands cover both.
593
604
  */
@@ -605,9 +616,8 @@ async function installFeature(slug, options) {
605
616
  * Stderr-only. We don't put this on stdout because if the user pipes our
606
617
  * output anywhere by accident, only the markdown should reach the agent.
607
618
  *
608
- * Formatting mirrors Flue's `printHumanInstructions` 1:1 agents listed
609
- * with a blank line between the "first-tier" CLIs (claude/codex/cursor-agent)
610
- * and the rest (opencode/pi).
619
+ * Agents are listed with a blank line between the "first-tier" CLIs
620
+ * (claude/codex/cursor-agent) and the rest (opencode/pi).
611
621
  */
612
622
  function printHumanInstructions(slug) {
613
623
  const cmd = `nimbus-docs add ${slug}`;
@@ -1211,9 +1221,8 @@ function loadMaterializedConfig(cwd) {
1211
1221
  * nimbus-docs add <slug> --yes → component: skip overwrite prompts
1212
1222
  * nimbus-docs add <slug> --print → feature: print markdown to stdout (skip detect)
1213
1223
  *
1214
- * Feature behavior mirrors Flue's `add` command: print markdown to stdout
1215
- * iff `--print` OR an agent is detected; otherwise print human-friendly
1216
- * pipe instructions to stderr.
1224
+ * Feature behavior: print markdown to stdout iff `--print` OR an agent is
1225
+ * detected; otherwise print human-friendly pipe instructions to stderr.
1217
1226
  *
1218
1227
  * The bundled index makes `list` (and `add` with no slug) work offline.
1219
1228
  * Per-item content is fetched from `REGISTRY_BASE_URL` only when actually
@@ -1276,7 +1285,7 @@ async function main() {
1276
1285
  return;
1277
1286
  }
1278
1287
  if (args.version) {
1279
- process.stdout.write(`0.1.10\n`);
1288
+ process.stdout.write(`0.1.12\n`);
1280
1289
  return;
1281
1290
  }
1282
1291
  const [command, slug] = args._;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["addCommand","addCommand"],"sources":["../../src/cli/_registry.generated.ts","../../src/cli/clean.ts","../../src/cli/pm.ts","../../src/cli/component.ts","../../src/cli/dotenv.ts","../../src/cli/resolver.ts","../../src/cli/feature.ts","../../src/lint/disables.ts","../../src/lint/fix.ts","../../src/lint/engine.ts","../../src/lint/discover.ts","../../src/lint/format.ts","../../src/cli/lint.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Bundled registry index — auto-generated by\n * apps/www/scripts/generate-registry.ts. Do not edit by hand.\n *\n * Re-run via: pnpm --filter @nimbus/www generate-registry\n */\n\nexport type RegistryEntryType =\n | \"registry:ui\"\n | \"registry:lib\"\n | \"registry:feature\";\n\nexport interface RegistryIndexEntry {\n name: string;\n type: RegistryEntryType;\n title: string;\n description: string;\n}\n\nexport interface BundledIndex {\n version: 1;\n items: Record<string, RegistryIndexEntry>;\n}\n\nexport const REGISTRY_BASE_URL = \"https://nimbus-docs.com/registry\";\n\nexport const BUNDLED_INDEX: BundledIndex = {\n \"version\": 1,\n \"items\": {\n \"cn\": {\n \"name\": \"cn\",\n \"type\": \"registry:lib\",\n \"title\": \"cn\",\n \"description\": \"Tailwind-aware className merger built on clsx + tailwind-merge.\"\n },\n \"accordion\": {\n \"name\": \"accordion\",\n \"type\": \"registry:ui\",\n \"title\": \"Accordion\",\n \"description\": \"Vertically stacked collapsible sections.\"\n },\n \"aside\": {\n \"name\": \"aside\",\n \"type\": \"registry:ui\",\n \"title\": \"Aside\",\n \"description\": \"Generic boxed callout. Building block for Callout, Note, Warning.\"\n },\n \"badge\": {\n \"name\": \"badge\",\n \"type\": \"registry:ui\",\n \"title\": \"Badge\",\n \"description\": \"Small status / category pill.\"\n },\n \"banner\": {\n \"name\": \"banner\",\n \"type\": \"registry:ui\",\n \"title\": \"Banner\",\n \"description\": \"Site-wide dismissible announcement bar.\"\n },\n \"breadcrumbs\": {\n \"name\": \"breadcrumbs\",\n \"type\": \"registry:ui\",\n \"title\": \"Breadcrumbs\",\n \"description\": \"Page-context navigation crumbs.\"\n },\n \"callout\": {\n \"name\": \"callout\",\n \"type\": \"registry:ui\",\n \"title\": \"Callout\",\n \"description\": \"Inline note / tip / warning / danger / info card.\"\n },\n \"card\": {\n \"name\": \"card\",\n \"type\": \"registry:ui\",\n \"title\": \"Card\",\n \"description\": \"Generic content card with optional title and footer.\"\n },\n \"card-grid\": {\n \"name\": \"card-grid\",\n \"type\": \"registry:ui\",\n \"title\": \"CardGrid\",\n \"description\": \"Responsive grid layout for cards.\"\n },\n \"code\": {\n \"name\": \"code\",\n \"type\": \"registry:ui\",\n \"title\": \"Code\",\n \"description\": \"Inline / block code wrapper. Re-exports Astro's built-in <Code> (Shiki).\"\n },\n \"code-group\": {\n \"name\": \"code-group\",\n \"type\": \"registry:ui\",\n \"title\": \"CodeGroup\",\n \"description\": \"Tabbed group of code blocks.\"\n },\n \"collapsible\": {\n \"name\": \"collapsible\",\n \"type\": \"registry:ui\",\n \"title\": \"Collapsible\",\n \"description\": \"Headless show/hide primitive — building block for Accordion and Sidebar groups.\"\n },\n \"dialog\": {\n \"name\": \"dialog\",\n \"type\": \"registry:ui\",\n \"title\": \"Dialog\",\n \"description\": \"Modal dialog with focus-trap and body-scroll lock.\"\n },\n \"embed\": {\n \"name\": \"embed\",\n \"type\": \"registry:ui\",\n \"title\": \"Embed\",\n \"description\": \"Responsive iframe / video / external content wrapper.\"\n },\n \"file-tree\": {\n \"name\": \"file-tree\",\n \"type\": \"registry:ui\",\n \"title\": \"FileTree\",\n \"description\": \"Render a directory tree as nested markup.\"\n },\n \"frame\": {\n \"name\": \"frame\",\n \"type\": \"registry:ui\",\n \"title\": \"Frame\",\n \"description\": \"Decorative outer frame for screenshots and demos.\"\n },\n \"layer-card\": {\n \"name\": \"layer-card\",\n \"type\": \"registry:ui\",\n \"title\": \"LayerCard\",\n \"description\": \"Stacked-card container with sticky header. Base for CodeGroup and PackageManagers.\"\n },\n \"link-button\": {\n \"name\": \"link-button\",\n \"type\": \"registry:ui\",\n \"title\": \"LinkButton\",\n \"description\": \"Anchor styled as a button.\"\n },\n \"link-card\": {\n \"name\": \"link-card\",\n \"type\": \"registry:ui\",\n \"title\": \"LinkCard\",\n \"description\": \"Card whose entire surface is a link.\"\n },\n \"package-managers\": {\n \"name\": \"package-managers\",\n \"type\": \"registry:ui\",\n \"title\": \"PackageManagers\",\n \"description\": \"Tabbed install command block translated across npm / pnpm / yarn / bun.\"\n },\n \"page-actions\": {\n \"name\": \"page-actions\",\n \"type\": \"registry:ui\",\n \"title\": \"PageActions\",\n \"description\": \"Inline page-header actions: copy the page as markdown, open the raw .md.\"\n },\n \"pagination\": {\n \"name\": \"pagination\",\n \"type\": \"registry:ui\",\n \"title\": \"Pagination\",\n \"description\": \"Prev / next page navigation.\"\n },\n \"popover\": {\n \"name\": \"popover\",\n \"type\": \"registry:ui\",\n \"title\": \"Popover\",\n \"description\": \"Floating panel anchored to a trigger element.\"\n },\n \"search\": {\n \"name\": \"search\",\n \"type\": \"registry:ui\",\n \"title\": \"Search\",\n \"description\": \"Command-palette search dialog with a provider seam. Defaults to Pagefind.\"\n },\n \"sidebar\": {\n \"name\": \"sidebar\",\n \"type\": \"registry:ui\",\n \"title\": \"Sidebar\",\n \"description\": \"Docs sidebar with nested groups and active-link tracking.\"\n },\n \"steps\": {\n \"name\": \"steps\",\n \"type\": \"registry:ui\",\n \"title\": \"Steps\",\n \"description\": \"Numbered ordered-list with vertical connectors.\"\n },\n \"tabs\": {\n \"name\": \"tabs\",\n \"type\": \"registry:ui\",\n \"title\": \"Tabs\",\n \"description\": \"Tabbed content panels (manual + Starlight-compatible modes).\"\n },\n \"theme-toggle\": {\n \"name\": \"theme-toggle\",\n \"type\": \"registry:ui\",\n \"title\": \"ThemeToggle\",\n \"description\": \"Light / dark theme switcher button.\"\n },\n \"toc\": {\n \"name\": \"toc\",\n \"type\": \"registry:ui\",\n \"title\": \"TOC\",\n \"description\": \"On-page table of contents with active-heading tracking.\"\n },\n \"version-switcher\": {\n \"name\": \"version-switcher\",\n \"type\": \"registry:ui\",\n \"title\": \"VersionPicker\",\n \"description\": \"Header dropdown for switching between docs versions. Reads `versions` from nimbus.config.ts, uses the build-time alternates table to land readers on the same logical page in the target version. Includes deprecation badge and hidden-version exclusion. Renders nothing when versioning is off or only one version is configured.\"\n },\n \"diagram\": {\n \"name\": \"diagram\",\n \"type\": \"registry:lib\",\n \"title\": \"Diagram UI\",\n \"description\": \"React visual components for `nimbus-docs/react`'s headless <Diagram> wrapper: ActionBar, ActionButton (ghost + primary variants), ChipGroup, Tabs (uses useTabIndicator), DiagramControls (toolbar with status slot + pre-wired Play/Pause/Reset via useDiagram), DiagramDefs (shared SVG filter/marker defs), DiagramStage (bordered dotted-grid canvas + shared keyframes), CardBadge, DiagramDebug, DiagramPauseAll. Install when authoring interactive diagrams. Lifts as React, not Astro — kept paradigm-segregated under src/components/react/diagram/.\"\n },\n \"diagram-scene\": {\n \"name\": \"diagram-scene\",\n \"type\": \"registry:lib\",\n \"title\": \"Diagram scene\",\n \"description\": \"Declarative card factory over `nimbus-docs/react`: author a diagram as data (phase steps, active-id table, edge specs) plus a CSS layout of labelled nodes. Measurement, edge routing, the SVG layer, and active-state styling are handled by the component — user-owned, restyle freely. `<Scene>` composes inside an existing <Diagram>; `createScene` wraps it into a standalone card. For pill-and-arrow diagrams; bespoke cards compose the hooks directly.\"\n },\n \"404-page\": {\n \"name\": \"404-page\",\n \"type\": \"registry:feature\",\n \"title\": \"Custom 404 page\",\n \"description\": \"Generate a brand-matched 404 page for the docs site.\"\n },\n \"ai-native\": {\n \"name\": \"ai-native\",\n \"type\": \"registry:feature\",\n \"title\": \"AI-native static surface\",\n \"description\": \"Add llms.txt, markdown variants, robots.txt, and an AgentDirective to a Nimbus docs site.\"\n },\n \"component-showcase\": {\n \"name\": \"component-showcase\",\n \"type\": \"registry:feature\",\n \"title\": \"Component showcase\",\n \"description\": \"Add a /components grid landing plus per-component showcase pages at /components/<slug>, driven by a dedicated content collection. For sites documenting their own UI library.\"\n },\n \"lint-prose-textlint\": {\n \"name\": \"lint-prose-textlint\",\n \"type\": \"registry:feature\",\n \"title\": \"Prose linting with textlint\",\n \"description\": \"Add textlint with write-good, alex, and terminology rules — npm-native prose linting that runs alongside nimbus-docs lint.\"\n },\n \"mermaid\": {\n \"name\": \"mermaid\",\n \"type\": \"registry:feature\",\n \"title\": \"Mermaid diagrams\",\n \"description\": \"Add lazy-loaded, theme-aware Mermaid.js diagram rendering with a skeleton loading state and a full-screen expand dialog.\"\n },\n \"new-collection\": {\n \"name\": \"new-collection\",\n \"type\": \"registry:feature\",\n \"title\": \"Add a new collection\",\n \"description\": \"End-to-end setup for a non-version content tree on a Nimbus docs site — blog, API reference, changelog, glossary. Creates the folder, registers the collection, scaffolds routes. For docs versions, use `nimbus-docs add new-version`.\"\n },\n \"new-version\": {\n \"name\": \"new-version\",\n \"type\": \"registry:feature\",\n \"title\": \"Add a docs version\",\n \"description\": \"End-to-end setup for adding a docs version to a Nimbus site. Creates the content directory, registers the collection, scaffolds routes, declares the manifest, installs the version-switcher picker, and wires it into your Header and DocsLayout. One command for one mental task.\"\n },\n \"pagefind-search\": {\n \"name\": \"pagefind-search\",\n \"type\": \"registry:feature\",\n \"title\": \"Pagefind search\",\n \"description\": \"Add static Pagefind indexing and the Nimbus search dialog to an existing docs site.\"\n }\n }\n};\n","/**\n * `nimbus-docs clean` — remove the incremental-build cache.\n *\n * Use when you suspect cache corruption, after a framework upgrade, or\n * when the incremental-builds documentation specifically tells you to.\n * Safe to run any time — the cache is rebuilt on the next `astro build`.\n *\n * Clears both locations:\n * - `node_modules/.astro/nimbus` — the default (rides Astro's cacheDir, the\n * dir hosts persist between builds).\n * - `.nimbus/cache` — the legacy location, still used when Astro's cacheDir\n * can't be resolved.\n *\n * Note: if you've set a custom Astro `cacheDir`, remove `<cacheDir>/nimbus`\n * manually — the standalone CLI doesn't load your Astro config.\n */\nimport { rm, stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport * as p from \"@clack/prompts\";\n\nexport async function cleanCommand(cwd: string = process.cwd()): Promise<void> {\n const candidates = [\n resolve(cwd, \"node_modules/.astro/nimbus\"),\n resolve(cwd, \".nimbus/cache\"),\n ];\n\n let removedAny = false;\n for (const dir of candidates) {\n let exists = false;\n try {\n exists = (await stat(dir)).isDirectory();\n } catch {\n // not present\n }\n if (!exists) continue;\n await rm(dir, { recursive: true, force: true });\n p.log.success(`Removed ${dir}`);\n removedAny = true;\n }\n\n if (!removedAny) p.log.info(\"No cache to clean.\");\n}\n","/**\n * Package-manager detection + install command helpers.\n *\n * Detection prefers lockfile presence in the user's cwd, then falls back\n * to the `npm_config_user_agent` env var the active package manager sets\n * when invoking the CLI. Finally falls back to `npm`.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nconst LOCKFILES: ReadonlyArray<readonly [string, PackageManager]> = [\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"bun.lockb\", \"bun\"],\n [\"bun.lock\", \"bun\"],\n [\"package-lock.json\", \"npm\"],\n];\n\nexport function detectPackageManager(cwd: string): PackageManager {\n for (const [lockfile, pm] of LOCKFILES) {\n if (existsSync(join(cwd, lockfile))) return pm;\n }\n const ua = process.env.npm_config_user_agent ?? \"\";\n if (ua.startsWith(\"pnpm\")) return \"pnpm\";\n if (ua.startsWith(\"yarn\")) return \"yarn\";\n if (ua.startsWith(\"bun\")) return \"bun\";\n return \"npm\";\n}\n\n/**\n * Command + args to install one or more new npm deps. Each PM picks the\n * verb that both adds to package.json AND installs:\n *\n * npm install <deps...>\n * pnpm add <deps...>\n * yarn add <deps...>\n * bun add <deps...>\n */\nexport function addCommand(\n pm: PackageManager,\n deps: string[],\n): { bin: string; args: string[] } {\n if (deps.length === 0) {\n throw new Error(\"addCommand called with empty deps\");\n }\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"install\", ...deps] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"add\", ...deps] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"add\", ...deps] };\n case \"bun\":\n return { bin: \"bun\", args: [\"add\", ...deps] };\n }\n}\n","/**\n * Component / utility installer.\n *\n * Walks the resolved list of items, writes each file (per-file overwrite\n * prompt on conflict), then collects all npm `dependencies` across the\n * tree and runs `<pm> add` once for the dedup'd set.\n *\n * File destination: `<cwd>/src/<path>`. The `path` field already encodes\n * the directory layout (e.g. `components/ui/dialog/Dialog.astro`).\n */\n\nimport { spawn } from \"node:child_process\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\n\nimport { addCommand, detectPackageManager } from \"./pm.js\";\nimport type { ComponentItem } from \"./resolver.js\";\n\nexport interface InstallOptions {\n /** User's project root. */\n cwd: string;\n /** Skip overwrite prompts; assume \"overwrite\" on every conflict. */\n yes: boolean;\n}\n\nexport interface InstallReport {\n /** Individual files actually written. */\n written: string[];\n /** Registry slugs skipped wholesale by the user. */\n skipped: string[];\n npmDepsInstalled: string[];\n}\n\nexport async function installComponents(\n items: ComponentItem[],\n options: InstallOptions,\n): Promise<InstallReport> {\n const report: InstallReport = {\n written: [],\n skipped: [],\n npmDepsInstalled: [],\n };\n\n // ---- 1. Write files — atomic per registry item -------------------------\n //\n // Each item (e.g. `dialog`) is treated as an indivisible unit: when any\n // of its files conflict, we prompt once for the whole slug. Letting users\n // overwrite Dialog.astro while keeping DialogContent.astro is a footgun\n // — components are cohesive and meant to evolve together.\n const srcDir = join(options.cwd, \"src\");\n\n for (const item of items) {\n const filePlans = item.files.map((file) => {\n const targetAbs = join(srcDir, file.path);\n return {\n targetAbs,\n targetRel: relative(options.cwd, targetAbs),\n content: file.content,\n exists: existsSync(targetAbs),\n };\n });\n\n const conflicts = filePlans.filter((f) => f.exists);\n\n // Utilities (registry:lib) are transitive dependencies of UI\n // components — install silently when missing, skip silently when\n // present. Never prompt or overwrite: users may have customized\n // them (e.g. cn) and being asked about `cn` every time you `add` a\n // component is noise.\n if (item.type === \"registry:lib\") {\n if (conflicts.length > 0) {\n report.skipped.push(item.name);\n continue;\n }\n } else if (conflicts.length > 0 && !options.yes) {\n const total = filePlans.length;\n const message =\n conflicts.length === total\n ? `${item.name} is already installed (${total} file${total === 1 ? \"\" : \"s\"}). Overwrite?`\n : `${item.name} is partially installed (${conflicts.length} of ${total} file${total === 1 ? \"\" : \"s\"} present). Overwrite all?`;\n\n const choice = await p.select({\n message,\n options: [\n { value: \"overwrite\", label: \"Overwrite — replace existing files\" },\n { value: \"skip\", label: \"Skip — leave files as-is\" },\n { value: \"cancel\", label: \"Cancel install\" },\n ],\n initialValue: \"overwrite\",\n });\n\n if (p.isCancel(choice) || choice === \"cancel\") {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n if (choice === \"skip\") {\n report.skipped.push(item.name);\n continue;\n }\n }\n\n // Either no conflicts, --yes, or user chose overwrite. Write every file.\n for (const plan of filePlans) {\n mkdirSync(dirname(plan.targetAbs), { recursive: true });\n writeFileSync(plan.targetAbs, plan.content);\n report.written.push(plan.targetRel);\n }\n }\n\n // ---- 2. Install missing npm deps ---------------------------------------\n const allDeps = new Set<string>();\n for (const item of items) {\n for (const dep of item.dependencies) allDeps.add(dep);\n }\n\n if (allDeps.size > 0) {\n const newDeps = filterAlreadyInstalled(options.cwd, [...allDeps]);\n if (newDeps.length > 0) {\n const pm = detectPackageManager(options.cwd);\n const { bin, args } = addCommand(pm, newDeps);\n const spinner = p.spinner();\n spinner.start(`${pm} add ${newDeps.join(\" \")}`);\n try {\n await runCommand(bin, args, options.cwd);\n spinner.stop(\n `Installed ${newDeps.length} dep${newDeps.length === 1 ? \"\" : \"s\"}.`,\n );\n report.npmDepsInstalled = newDeps;\n } catch (err) {\n spinner.stop(\"Dependency install failed.\");\n p.log.warn(\n `Could not install ${newDeps.join(\", \")}. Run \\`${bin} ${args.join(\" \")}\\` manually.`,\n );\n }\n }\n }\n\n return report;\n}\n\n/**\n * Filter out deps already present in `dependencies` or `devDependencies`\n * of the user's package.json. If package.json is missing, returns all.\n */\nfunction filterAlreadyInstalled(cwd: string, deps: string[]): string[] {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return deps;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const installed = new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ]);\n return deps.filter((d) => !installed.has(d));\n } catch {\n return deps;\n }\n}\n\nfunction runCommand(\n bin: string,\n args: string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolveP, rejectP) => {\n const child = spawn(bin, args, {\n cwd,\n stdio: [\"ignore\", \"ignore\", \"inherit\"],\n });\n child.on(\"close\", (code) =>\n code === 0\n ? resolveP()\n : rejectP(new Error(`${bin} ${args.join(\" \")} exited ${code}`)),\n );\n child.on(\"error\", rejectP);\n });\n}\n","/**\n * Tiny .env loader — no dependency.\n *\n * Reads `.env` from the user's cwd at CLI startup and sets any KEY=VALUE\n * pairs into `process.env` IF the variable isn't already set (so a shell-\n * provided env always wins over the file). Supports the basic cases:\n *\n * KEY=value\n * KEY=\"quoted value\"\n * KEY='quoted value'\n * # comments\n *\n * Used so `examples/local/.env` can carry `NIMBUS_REGISTRY_URL=...` without\n * the user having to prefix every CLI invocation.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport function loadDotenv(cwd: string): void {\n const path = join(cwd, \".env\");\n if (!existsSync(path)) return;\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return;\n }\n\n for (const rawLine of raw.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n\n const eq = line.indexOf(\"=\");\n if (eq <= 0) continue;\n\n const key = line.slice(0, eq).trim();\n if (!/^[A-Z_][A-Z0-9_]*$/i.test(key)) continue;\n\n let value = line.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n if (process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n}\n","/**\n * Registry resolver.\n *\n * Two entry points:\n *\n * - `resolveComponentTree(slug)` walks `registryDependencies` transitively\n * and returns a flat ordered list of components/utilities to install\n * (dependencies first, root last). Cycles are detected as repeated\n * visits and skipped.\n *\n * - `fetchFeatureMarkdown(slug)` returns the raw markdown for an\n * agent-handoff feature; the caller decides what to do with it.\n *\n * The base URL for hosted artifacts is read from the bundled index, with\n * an `NIMBUS_REGISTRY_URL` env override for local development.\n */\n\nimport {\n BUNDLED_INDEX,\n REGISTRY_BASE_URL,\n type RegistryIndexEntry,\n} from \"./_registry.generated.js\";\n\nexport interface RegistryFile {\n path: string;\n content: string;\n}\n\nexport interface ComponentItem {\n name: string;\n type: \"registry:ui\" | \"registry:lib\";\n title: string;\n description: string;\n dependencies: string[];\n registryDependencies: string[];\n files: RegistryFile[];\n}\n\n/**\n * Read the registry base URL on every call so `.env` files loaded after\n * module-import time (see cli/dotenv.ts) are picked up. The cost is\n * negligible — string interpolation of an env var.\n */\nfunction getBaseUrl(): string {\n return (process.env.NIMBUS_REGISTRY_URL ?? REGISTRY_BASE_URL).replace(\n /\\/$/,\n \"\",\n );\n}\n\n// ---------------------------------------------------------------------------\n// Index lookup (offline — no network)\n// ---------------------------------------------------------------------------\n\nexport function getIndexEntry(slug: string): RegistryIndexEntry | undefined {\n return BUNDLED_INDEX.items[slug];\n}\n\nexport function listEntries(filter?: {\n type?: RegistryIndexEntry[\"type\"];\n}): RegistryIndexEntry[] {\n const all = Object.values(BUNDLED_INDEX.items);\n if (!filter?.type) return all;\n return all.filter((e) => e.type === filter.type);\n}\n\n// ---------------------------------------------------------------------------\n// Network: component JSON + feature markdown\n// ---------------------------------------------------------------------------\n\nasync function httpGet(url: string): Promise<Response> {\n let res: Response;\n try {\n res = await fetch(url);\n } catch (err) {\n const cause = (err as Error).message;\n throw new Error(\n `Could not reach the registry at ${url}.\\n` +\n ` Underlying error: ${cause}\\n\\n` +\n ` Things to try:\\n` +\n ` - Is the registry server running? Start it with \\`pnpm local\\` (in the monorepo root).\\n` +\n ` - Override the URL: NIMBUS_REGISTRY_URL=https://example.com nimbus-docs add ...\\n` +\n ` - Check the value in your project's .env file.`,\n );\n }\n if (!res.ok) {\n throw new Error(\n `Registry returned ${res.status} ${res.statusText} for ${url}. ` +\n `The server is up but doesn't know about this slug — check \\`nimbus-docs list\\` for valid names.`,\n );\n }\n return res;\n}\n\nexport async function fetchComponent(slug: string): Promise<ComponentItem> {\n const res = await httpGet(`${getBaseUrl()}/components/${slug}.json`);\n return (await res.json()) as ComponentItem;\n}\n\nexport async function fetchFeatureMarkdown(slug: string): Promise<string> {\n const res = await httpGet(`${getBaseUrl()}/features/${slug}.md`);\n return await res.text();\n}\n\n// ---------------------------------------------------------------------------\n// Transitive dep resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Depth-first walk of registryDependencies. Returns items in install order\n * (deps before dependents), deduplicated by slug.\n */\nexport async function resolveComponentTree(\n rootSlug: string,\n): Promise<ComponentItem[]> {\n const visited = new Set<string>();\n const ordered: ComponentItem[] = [];\n\n async function visit(slug: string): Promise<void> {\n if (visited.has(slug)) return;\n visited.add(slug);\n\n const item = await fetchComponent(slug);\n\n // Walk deps first so they're earlier in the install order.\n for (const dep of item.registryDependencies) {\n await visit(dep);\n }\n\n ordered.push(item);\n }\n\n await visit(rootSlug);\n return ordered;\n}\n","/**\n * Feature installer — Flue-style agent-handoff.\n *\n * Same rule Flue uses for `flue add`: if `--print` is set OR\n * `determineAgent()` says the CLI is running inside a known coding agent,\n * the markdown is piped to stdout for the agent to consume. Otherwise we\n * print human-friendly instructions on stderr telling the user exactly\n * how to pipe the output to their agent of choice.\n *\n * No picker, no clipboard mode — the printed pipe commands cover both.\n */\n\nimport { determineAgent } from \"@vercel/detect-agent\";\n\nimport { fetchFeatureMarkdown } from \"./resolver.js\";\n\nexport interface FeatureInstallOptions {\n /** Force markdown to stdout regardless of agent detection. */\n print: boolean;\n}\n\nexport async function installFeature(\n slug: string,\n options: FeatureInstallOptions,\n): Promise<void> {\n const markdown = await fetchFeatureMarkdown(slug);\n\n // Same predicate as Flue: explicit --print, or detection says we're\n // running inside a known agent (which captures our stdout).\n const detected = await determineAgent().catch(() => ({\n isAgent: false as const,\n }));\n const isAgentMode = options.print || detected.isAgent === true;\n\n if (isAgentMode) {\n process.stdout.write(markdown);\n if (!markdown.endsWith(\"\\n\")) process.stdout.write(\"\\n\");\n return;\n }\n\n printHumanInstructions(slug);\n}\n\n/**\n * Stderr-only. We don't put this on stdout because if the user pipes our\n * output anywhere by accident, only the markdown should reach the agent.\n *\n * Formatting mirrors Flue's `printHumanInstructions` 1:1 — agents listed\n * with a blank line between the \"first-tier\" CLIs (claude/codex/cursor-agent)\n * and the rest (opencode/pi).\n */\nfunction printHumanInstructions(slug: string): void {\n const cmd = `nimbus-docs add ${slug}`;\n const stream = process.stderr;\n stream.write(`${cmd}\\n\\n`);\n stream.write(\"To install this feature, pipe it to your coding agent:\\n\\n\");\n stream.write(` ${cmd} --print | claude\\n`);\n stream.write(` ${cmd} --print | codex\\n`);\n stream.write(` ${cmd} --print | cursor-agent\\n\\n`);\n stream.write(` ${cmd} --print | opencode\\n`);\n stream.write(` ${cmd} --print | pi\\n`);\n stream.write(\"Or paste this prompt into any agent:\\n\\n\");\n stream.write(` Run \"${cmd} --print\" and follow the instructions.\\n`);\n}\n","/**\n * Per-file and per-line disable directives — both designed so the disable\n * itself is greppable:\n *\n * - Frontmatter `nimbusDisableRules: [\"nimbus/internal-link\"]` disables\n * the listed codes for the whole file.\n * - An inline `{/* nimbus-rule-disable-next-line nimbus/bare-url *​/}`\n * comment disables the named code on the next non-blank line.\n *\n * Both require a rule code: an empty `nimbusDisableRules` array is a\n * reported error, so the reason for a disable is always visible.\n */\n\nimport { isRuleCode } from \"./diagnostic.js\";\nimport type { RuleReport } from \"./rule.js\";\n\nexport interface DisableInfo {\n /** Rule codes disabled for the entire file. */\n fileDisabled: Set<string>;\n /** 1-based source line → rule codes disabled on that line. */\n lineDisabled: Map<number, Set<string>>;\n /** Malformed-directive findings (e.g. an empty disable array). */\n problems: RuleReport[];\n}\n\nconst INLINE_DISABLE =\n /\\{\\/\\*\\s*nimbus-rule-disable-next-line\\s+(\\S+)\\s*\\*\\/\\}/;\n\nexport function collectDisables(\n frontmatter: Record<string, unknown> | null,\n frontmatterRaw: string | null,\n frontmatterStartLine: number,\n lines: string[],\n): DisableInfo {\n const fileDisabled = new Set<string>();\n const lineDisabled = new Map<number, Set<string>>();\n const problems: RuleReport[] = [];\n\n // ----- Frontmatter file-level disables.\n if (frontmatter && \"nimbusDisableRules\" in frontmatter) {\n const raw = frontmatter.nimbusDisableRules;\n const at = locateFrontmatterKey(\n frontmatterRaw,\n \"nimbusDisableRules\",\n frontmatterStartLine,\n );\n if (!Array.isArray(raw)) {\n problems.push({\n message:\n '\"nimbusDisableRules\" must be an array of rule codes, e.g. [\"nimbus/internal-link\"].',\n line: at.line,\n column: at.column,\n });\n } else if (raw.length === 0) {\n problems.push({\n message:\n '\"nimbusDisableRules\" is empty — remove it, or name the rule code(s) you mean to disable so the reason stays greppable.',\n line: at.line,\n column: at.column,\n });\n } else {\n for (const entry of raw) {\n if (typeof entry !== \"string\") {\n problems.push({\n message: `\"nimbusDisableRules\" entry ${JSON.stringify(entry)} must be a string rule code.`,\n line: at.line,\n column: at.column,\n });\n continue;\n }\n if (!isRuleCode(entry)) {\n problems.push({\n message: `\"nimbusDisableRules\" lists \"${entry}\", which is not a known rule code — typos here silently no-op, so we surface them.`,\n line: at.line,\n column: at.column,\n });\n continue;\n }\n fileDisabled.add(entry);\n }\n }\n }\n\n // ----- Inline next-line disables.\n for (let i = 0; i < lines.length; i++) {\n const match = lines[i]!.match(INLINE_DISABLE);\n if (!match) continue;\n const code = match[1]!;\n if (!isRuleCode(code)) {\n problems.push({\n message: `inline disable references \"${code}\", which is not a known rule code — typos here silently no-op, so we surface them.`,\n line: i + 1,\n column: (match.index ?? 0) + 1,\n });\n continue;\n }\n // Target the next non-blank line (1-based).\n let target = -1;\n for (let j = i + 1; j < lines.length; j++) {\n if (lines[j]!.trim() !== \"\") {\n target = j + 1;\n break;\n }\n }\n if (target === -1) continue;\n const set = lineDisabled.get(target) ?? new Set<string>();\n set.add(code);\n lineDisabled.set(target, set);\n }\n\n return { fileDisabled, lineDisabled, problems };\n}\n\n/** Is a diagnostic for `code` on `line` suppressed by a disable directive? */\nexport function isDisabled(\n info: DisableInfo,\n code: string,\n line: number,\n): boolean {\n if (info.fileDisabled.has(code)) return true;\n return info.lineDisabled.get(line)?.has(code) ?? false;\n}\n\nfunction locateFrontmatterKey(\n frontmatterRaw: string | null,\n key: string,\n startLine: number,\n): { line: number; column: number } {\n if (frontmatterRaw) {\n const rawLines = frontmatterRaw.split(\"\\n\");\n for (let i = 0; i < rawLines.length; i++) {\n const m = rawLines[i]!.match(new RegExp(`^(\\\\s*)${key}\\\\s*:`));\n if (m) return { line: startLine + i, column: m[1]!.length + 1 };\n }\n }\n return { line: startLine, column: 1 };\n}\n","/**\n * Apply rule `fix` edits to source. Diagnostic-level atomic: each\n * diagnostic's edits are applied together or not at all, and a diagnostic\n * whose span overlaps one already applied is skipped (a second pass picks\n * it up). Edits are character offsets into the source — the same unist\n * offsets the parser reports — applied right-to-left so earlier offsets\n * stay valid.\n *\n * No \"smart\" fixes: this only applies edits a rule already declared. The\n * change is plain and reviewable in `git diff`.\n */\n\nimport type { Diagnostic } from \"./diagnostic.js\";\n\nexport interface FixResult {\n output: string;\n /** Number of diagnostics whose fix was applied. */\n fixed: number;\n /**\n * The exact diagnostic objects whose fixes were applied. The caller\n * uses this (by identity, not by index) to know which diagnostics to\n * suppress from the post-fix report — the rest stay in the output\n * because their `fix` field was advisory-only (no edits) or was\n * skipped due to an overlap with another applied fix.\n */\n applied: Set<Diagnostic>;\n}\n\nexport function applyFixes(source: string, diagnostics: Diagnostic[]): FixResult {\n const items = diagnostics\n .filter(\n (d): d is Diagnostic & { fix: NonNullable<Diagnostic[\"fix\"]> } =>\n d.fix !== undefined && d.fix.edits.length > 0,\n )\n .map((d) => {\n const edits = d.fix.edits;\n return {\n diagnostic: d,\n edits,\n start: Math.min(...edits.map((e) => e.range[0])),\n end: Math.max(...edits.map((e) => e.range[1])),\n };\n })\n // Apply from the end of the file backwards.\n .sort((a, b) => b.start - a.start);\n\n let output = source;\n let frontier = Number.POSITIVE_INFINITY;\n const applied = new Set<Diagnostic>();\n\n for (const item of items) {\n if (item.end > frontier) continue; // overlaps an already-applied span\n const ordered = [...item.edits].sort((a, b) => b.range[0] - a.range[0]);\n for (const edit of ordered) {\n output =\n output.slice(0, edit.range[0]) + edit.text + output.slice(edit.range[1]);\n }\n frontier = item.start;\n applied.add(item.diagnostic);\n }\n\n return { output, fixed: applied.size, applied };\n}\n","/**\n * The lint engine. Runs the registered rules over parsed files, resolves\n * each rule's severity from config, applies per-file and per-line disables,\n * and collects everything into the one `Diagnostic` envelope.\n *\n * Pure and synchronous: `lintFile` takes a `ParsedFile` and returns\n * `Diagnostic[]`, which is what the test harness drives directly. The\n * disk-walking entry points (`lintPaths`) sit on top.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport {\n resolveRuleForCollection,\n type CollectionsConfig,\n type RulesConfig,\n} from \"./config.js\";\nimport type { Diagnostic, RuleCode, Severity } from \"./diagnostic.js\";\nimport { collectDisables, isDisabled } from \"./disables.js\";\nimport { applyFixes } from \"./fix.js\";\nimport { parseSource, type ParsedFile } from \"./parse.js\";\nimport type { RuleReport } from \"./rule.js\";\nimport { RULES } from \"./rules/index.js\";\nimport type { AuthoringRuleCode } from \"./diagnostic.js\";\n\nexport interface LintOptions {\n /** Severity overrides. Empty/omitted = every authoring rule on at error. */\n rules?: RulesConfig;\n /**\n * Per-collection overrides. Each entry's `rules` block shallow-merges\n * over the top-level `rules` for files in that collection. Resolution\n * precedence: top-level → per-collection → per-file `nimbusDisableRules`\n * → per-line inline disables.\n */\n collections?: CollectionsConfig;\n /**\n * Restrict the run to a single rule (CLI `--rule`). Authoring-only —\n * build validators don't have a severity knob, so `--rule=mdx-syntax`\n * is rejected at the CLI before reaching the engine.\n */\n only?: AuthoringRuleCode;\n /**\n * The project's canonical site URL (from `nimbusConfig.site`), threaded\n * into each rule's `ctx.site`. Lets site-aware rules (e.g.\n * `no-self-host-url`) catch the deploy host without making the user\n * duplicate it in their lint config.\n */\n site?: string;\n /**\n * Cancellation signal — checked between files in `lintPaths`/`fixPaths`.\n * The CLI wires this to SIGINT so Ctrl-C stops the run after the\n * in-progress file finishes (its write is already atomic), instead of\n * killing the process mid-rename.\n */\n signal?: AbortSignal;\n}\n\nexport interface LintSummary {\n errors: number;\n warnings: number;\n total: number;\n files: number;\n}\n\n/** Lint one already-parsed file. */\nexport function lintFile(file: ParsedFile, opts: LintOptions = {}): Diagnostic[] {\n // `opts.only` targets one rule via `--rule=<code>`. Since authoring rules\n // default to \"off\", a bare `--rule=foo` against the framework default\n // would resolve to off and print nothing — confusing UX for a flag the\n // user explicitly asked for. Force-enable it at \"error\" *unless* the\n // user already wrote an explicit top-level setting (including \"off\" —\n // explicit top-level intent wins over a CLI shortcut). When the\n // force-enable is active we also strip per-collection overrides for that\n // same code, so a `collections.<name>.rules: { \"foo\": \"off\" }` block\n // doesn't silently re-shadow the rule for whole subtrees (the exact\n // \"silent zero coverage\" failure mode the --rule flag exists to prevent).\n const forceEnable =\n opts.only !== undefined && opts.rules?.[opts.only] === undefined;\n const rules = forceEnable\n ? { ...(opts.rules ?? {}), [opts.only!]: \"error\" as const }\n : opts.rules ?? {};\n const collections = forceEnable\n ? stripCodeFromCollections(opts.collections ?? {}, opts.only!)\n : opts.collections ?? {};\n const out: Diagnostic[] = [];\n\n // A file that didn't parse won't render — emit the build-level syntax\n // error and stop; there's no tree to run authoring rules against.\n if (file.parseError) {\n return [\n {\n code: \"nimbus/mdx-syntax\",\n severity: \"error\",\n source: \"docs-compiler\",\n file: file.path,\n message: `MDX failed to parse: ${file.parseError.message}`,\n line: file.parseError.line,\n column: file.parseError.column,\n },\n ];\n }\n\n const disables = collectDisables(\n file.frontmatter,\n file.frontmatterRaw,\n file.frontmatterStartLine,\n file.lines,\n );\n\n // Malformed disable directives are themselves frontmatter problems, and\n // always errors — a disable you can't read is worse than no disable.\n for (const problem of disables.problems) {\n out.push({\n code: \"nimbus/frontmatter-shape\",\n severity: \"error\",\n source: \"docs-compiler\",\n file: file.path,\n message: problem.message,\n line: problem.line,\n column: problem.column,\n });\n }\n\n for (const rule of RULES) {\n if (opts.only && rule.code !== opts.only) continue;\n const resolved = resolveRuleForCollection(\n rule.code,\n rules,\n collections,\n file.collection,\n );\n if (resolved.severity === \"off\") continue;\n const severity = resolved.severity as Severity;\n\n const reports: RuleReport[] = [];\n try {\n rule.run({\n file,\n options: resolved.options,\n site: opts.site,\n report: (report) => reports.push(report),\n });\n } catch (err) {\n // A rule that throws is a bug in the rule, not user content. Skip it\n // and keep linting — one bad rule shouldn't blind the user to the\n // other thirteen.\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `nimbus-docs: rule \\`${rule.code}\\` threw on ${file.path}: ${detail}\\n`,\n );\n continue;\n }\n\n for (const report of reports) {\n if (isDisabled(disables, rule.code, report.line)) continue;\n out.push({\n code: rule.code,\n severity,\n source: \"docs-compiler\",\n file: file.path,\n message: report.message,\n line: report.line,\n column: report.column,\n endLine: report.endLine,\n endColumn: report.endColumn,\n fix: report.fix,\n });\n }\n }\n\n out.sort(\n (a, b) =>\n a.line - b.line ||\n a.column - b.column ||\n a.code.localeCompare(b.code),\n );\n return out;\n}\n\n/** Lint a set of absolute file paths, reading + parsing each one. */\nexport function lintPaths(\n absPaths: string[],\n projectRoot: string,\n opts: LintOptions = {},\n): Diagnostic[] {\n const out: Diagnostic[] = [];\n for (const abs of absPaths) {\n if (opts.signal?.aborted) break;\n const rel = path.relative(projectRoot, abs);\n try {\n const source = fs.readFileSync(abs, \"utf8\");\n const parsed = parseSource(source, {\n path: rel,\n absPath: abs,\n collection: inferCollection(rel),\n });\n out.push(...lintFile(parsed, opts));\n } catch (err) {\n // I/O errors (file vanished mid-run, permission denied) shouldn't kill\n // the whole lint — skip the file with a clear message and continue.\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(`nimbus-docs: skipped ${rel}: ${detail}\\n`);\n }\n }\n return out;\n}\n\nexport interface FixRunResult {\n /** Diagnostics that remain after fixing (i.e. those with no auto-fix). */\n diagnostics: Diagnostic[];\n /** Count of diagnostics whose fix was applied. */\n fixed: number;\n /** Count of files actually rewritten. */\n filesChanged: number;\n}\n\n/**\n * Hard cap on per-file fix passes — a runaway rule that keeps emitting\n * convergence-breaking fixes won't hang the CLI. 10 is well above any\n * realistic chain (the longest in practice is 2–3: a fix unmasks a\n * second-tier finding the first pass shadowed).\n */\nconst MAX_FIX_PASSES = 10;\n\n/**\n * Lint + apply auto-fixes in place. Each file is read, linted, fixed, and\n * (when content changed) atomically rewritten via tmp-file + rename — so a\n * crash or SIGINT mid-write can't truncate the user's content. We iterate\n * each file until the output stabilizes or `MAX_FIX_PASSES` is hit; this\n * picks up diagnostics that were skipped on pass 1 due to overlap with\n * another applied fix, plus diagnostics a fix on pass 1 unmasked.\n *\n * A diagnostic stays in the report when it wasn't *actually* applied —\n * which includes the advisory-only case (a rule emits a `fix` with no\n * `edits`, like the did-you-mean hint on `internal-link`) and the\n * skipped-overlap case after the convergence cap. Both are real,\n * unresolved issues; suppressing them just because the diagnostic carries\n * a `fix` field would silently hide broken links and other\n * un-auto-fixable problems.\n *\n * Files that fail to read, parse, or write are skipped with a stderr\n * message and the run continues — one bad file shouldn't leave the rest\n * of the working tree half-fixed.\n */\nexport function fixPaths(\n absPaths: string[],\n projectRoot: string,\n opts: LintOptions = {},\n): FixRunResult {\n let fixed = 0;\n let filesChanged = 0;\n const remaining: Diagnostic[] = [];\n\n for (const abs of absPaths) {\n if (opts.signal?.aborted) break;\n const rel = path.relative(projectRoot, abs);\n try {\n const original = fs.readFileSync(abs, \"utf8\");\n let current = original;\n let lastDiagnostics: Diagnostic[] = [];\n let lastApplied = new Set<Diagnostic>();\n\n for (let pass = 0; pass < MAX_FIX_PASSES; pass++) {\n const parsed = parseSource(current, {\n path: rel,\n absPath: abs,\n collection: inferCollection(rel),\n });\n const diagnostics = lintFile(parsed, opts);\n const result = applyFixes(current, diagnostics);\n fixed += result.fixed;\n lastDiagnostics = diagnostics;\n lastApplied = result.applied;\n if (result.output === current) break;\n current = result.output;\n }\n\n if (current !== original) {\n writeFileAtomicSync(abs, current);\n filesChanged++;\n }\n for (const d of lastDiagnostics) {\n if (!lastApplied.has(d)) remaining.push(d);\n }\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(`nimbus-docs: skipped ${rel}: ${detail}\\n`);\n }\n }\n\n return { diagnostics: remaining, fixed, filesChanged };\n}\n\n/**\n * Write atomically: serialize to a sibling tmp file, fsync, rename over the\n * target. A crash mid-write leaves the original intact instead of a\n * truncated .mdx. The tmp file lives next to the target so the rename is\n * a same-filesystem atomic op.\n */\nfunction writeFileAtomicSync(abs: string, content: string): void {\n const tmp = `${abs}.nimbus-tmp-${process.pid}`;\n const fd = fs.openSync(tmp, \"w\");\n try {\n fs.writeFileSync(fd, content, \"utf8\");\n fs.fsyncSync(fd);\n } finally {\n fs.closeSync(fd);\n }\n try {\n fs.renameSync(tmp, abs);\n } catch (err) {\n try {\n fs.unlinkSync(tmp);\n } catch {\n // best-effort cleanup\n }\n throw err;\n }\n}\n\nexport function summarize(diagnostics: Diagnostic[], files: number): LintSummary {\n let errors = 0;\n let warnings = 0;\n for (const d of diagnostics) {\n if (d.severity === \"error\") errors++;\n else warnings++;\n }\n return { errors, warnings, total: diagnostics.length, files };\n}\n\n/** Infer the collection name from a `src/content/<name>/…` path. */\nfunction inferCollection(relPath: string): string | null {\n const match = relPath\n .replace(/\\\\/g, \"/\")\n .match(/(?:^|\\/)src\\/content\\/([^/]+)\\//);\n return match ? match[1]! : null;\n}\n\n/**\n * Return a new collections config with `code` removed from every per-\n * collection `rules` block. Used by `lintFile`'s `--rule` force-enable so\n * a per-collection \"off\" doesn't silently shadow the CLI flag — the\n * user explicitly asked to see this rule's findings.\n */\nfunction stripCodeFromCollections(\n collections: CollectionsConfig,\n code: AuthoringRuleCode,\n): CollectionsConfig {\n const out: CollectionsConfig = {};\n for (const [name, cfg] of Object.entries(collections)) {\n if (!cfg.rules || !(code in cfg.rules)) {\n out[name] = cfg;\n continue;\n }\n const { [code]: _stripped, ...remaining } = cfg.rules;\n out[name] = { ...cfg, rules: remaining };\n }\n return out;\n}\n","/**\n * File discovery for the CLI — walk the configured content directories for\n * `.mdx` files, skipping `node_modules` and dotfolders. Mirrors the walk\n * the MDX validator already uses, kept here so the lint CLI doesn't depend\n * on integration internals.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport function findMdxFiles(dirs: string[]): string[] {\n const out: string[] = [];\n for (const dir of dirs) walk(dir, out);\n out.sort();\n return out;\n}\n\nfunction walk(dir: string, out: string[]): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw err;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name.startsWith(\".\")) continue;\n walk(full, out);\n } else if (entry.isFile() && entry.name.endsWith(\".mdx\")) {\n out.push(full);\n }\n }\n}\n","/**\n * Diagnostic formatters: a pretty terminal form and a machine-readable\n * JSON form. The pretty form mirrors the spec —\n *\n * src/content/docs/getting-started.mdx:42:18 error nimbus/single-h1\n * more than one top-level \"#\" heading …\n *\n * The JSON form is the agent-shaped envelope, validated against the\n * committed `diagnostic.schema.json`.\n */\n\nimport type { Diagnostic } from \"./diagnostic.js\";\nimport type { LintSummary } from \"./engine.js\";\n\nconst COLORS = {\n reset: \"\u001b[0m\",\n dim: \"\u001b[2m\",\n red: \"\u001b[31m\",\n yellow: \"\u001b[33m\",\n green: \"\u001b[32m\",\n bold: \"\u001b[1m\",\n};\n\nexport interface FormatOptions {\n color: boolean;\n /** Suppress `warn`-severity diagnostics from the output. */\n quiet?: boolean;\n}\n\nexport function formatPretty(\n diagnostics: Diagnostic[],\n summary: LintSummary,\n opts: FormatOptions,\n): string {\n const paint = (code: string, text: string) =>\n opts.color ? `${code}${text}${COLORS.reset}` : text;\n\n const shown = opts.quiet\n ? diagnostics.filter((d) => d.severity === \"error\")\n : diagnostics;\n\n const lines: string[] = [];\n for (const d of shown) {\n const sev =\n d.severity === \"error\"\n ? paint(COLORS.red, \"error\")\n : paint(COLORS.yellow, \"warn\");\n const loc = paint(COLORS.dim, `${d.file}:${d.line}:${d.column}`);\n lines.push(`${loc} ${sev} ${paint(COLORS.dim, d.code)}`);\n lines.push(` ${d.message}`);\n if (d.fix && d.fix.description) {\n lines.push(` ${paint(COLORS.dim, `fix: ${d.fix.description}`)}`);\n }\n }\n\n if (summary.total === 0) {\n return paint(COLORS.green, `✓ ${summary.files} file(s) lint clean.`);\n }\n\n const tally = `${summary.errors} error(s), ${summary.warnings} warning(s) across ${summary.files} file(s)`;\n lines.push(\"\");\n lines.push(\n summary.errors > 0\n ? paint(COLORS.red, `✗ ${tally}`)\n : paint(COLORS.yellow, `${tally}`),\n );\n return lines.join(\"\\n\");\n}\n\nexport function formatJson(\n diagnostics: Diagnostic[],\n summary: LintSummary,\n): string {\n return JSON.stringify(\n {\n version: 1,\n summary: {\n errors: summary.errors,\n warnings: summary.warnings,\n total: summary.total,\n files: summary.files,\n },\n diagnostics,\n },\n null,\n 2,\n );\n}\n","/**\n * `nimbus-docs lint` — the authoring-quality verdict for MDX content.\n *\n * Walks the content directories, runs the registered rules, prints\n * diagnostics, and exits non-zero when any `error`-severity finding\n * survives. The build is never gated by this command — drafts that fail\n * lint still render under `astro dev`.\n *\n * Severity overrides live with the integration\n * (`nimbus(config, { rules })`), which materializes them to\n * `.nimbus/lint.json` at build/dev time; this command reads that file when\n * present and otherwise runs every authoring rule at its default. In-file\n * disables (`nimbusDisableRules`, inline comments) work with no config.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport {\n findMdxFiles,\n fixPaths,\n formatJson,\n formatPretty,\n IMPLEMENTED_CODES,\n isRuleCode,\n lintPaths,\n summarize,\n validateLintOptions,\n type CollectionsConfig,\n type Diagnostic,\n type RuleCode,\n type RulesConfig,\n} from \"../lint/index.js\";\n\nexport interface LintCliFlags {\n format?: string;\n quiet?: boolean;\n rule?: string;\n color?: boolean;\n fix?: boolean;\n}\n\nexport async function lintCommand(flags: LintCliFlags): Promise<void> {\n const cwd = process.cwd();\n const contentDir = path.join(cwd, \"src\", \"content\");\n\n if (flags.rule) {\n if (!isRuleCode(flags.rule)) {\n process.stderr.write(\n `Unknown rule code: \\`${flags.rule}\\`. See https://nimbus-docs.com/lint for the rule list.\\n`,\n );\n process.exit(1);\n }\n // `isRuleCode` accepts every registered code, including build validators\n // (which run inside `astro build`, not here) and planned codes that\n // don't have a rule module yet. Either case would silently exit clean\n // with zero coverage — a worse outcome than \"unknown rule\" for a\n // command users invoke specifically because they trust it to enforce\n // something.\n if (!IMPLEMENTED_CODES.has(flags.rule)) {\n process.stderr.write(\n `Rule \\`${flags.rule}\\` is not implemented by \\`nimbus-docs lint\\`. ` +\n `Build validators run inside \\`astro build\\`, not here; planned rules haven't shipped yet. ` +\n `Implemented authoring rules: ${[...IMPLEMENTED_CODES].sort().join(\", \")}.\\n`,\n );\n process.exit(1);\n }\n }\n\n const files = findMdxFiles([contentDir]);\n if (files.length === 0) {\n process.stderr.write(\n `No .mdx files found under ${path.relative(cwd, contentDir) || \".\"}. ` +\n \"Run from your project root.\\n\",\n );\n process.exit(0);\n }\n\n const { rules, collections, site } = loadMaterializedConfig(cwd);\n const opts = {\n rules,\n collections,\n site,\n // `flags.rule` already passed through validation that rejects build\n // validators; the cast here is the type-level reflection of that runtime\n // narrowing (LintOptions.only is `AuthoringRuleCode` because `--rule`\n // can't force-enable a build validator).\n only: flags.rule as import(\"../lint/diagnostic.js\").AuthoringRuleCode | undefined,\n };\n\n let diagnostics: Diagnostic[];\n let interrupted = false;\n if (flags.fix) {\n // Atomic writes already protect each file from SIGINT corruption — the\n // .tmp+rename in `fixPaths` either finishes or doesn't. The handler\n // here just stops the iteration after the in-progress file finishes\n // and gives the user a clean \"stopped after N files\" report instead\n // of a default Ctrl-C abort with partial output.\n const ac = new AbortController();\n const onSigint = () => {\n if (interrupted) {\n process.stderr.write(\"\\nnimbus-docs: forced exit.\\n\");\n process.exit(130);\n }\n interrupted = true;\n process.stderr.write(\n \"\\nnimbus-docs: interrupted — finishing current file, then stopping. Press Ctrl-C again to force.\\n\",\n );\n ac.abort();\n };\n process.on(\"SIGINT\", onSigint);\n try {\n const result = fixPaths(files, cwd, { ...opts, signal: ac.signal });\n if (result.fixed > 0) {\n process.stderr.write(\n `Fixed ${result.fixed} issue(s) across ${result.filesChanged} file(s).\\n`,\n );\n }\n if (interrupted) {\n process.stderr.write(\n `nimbus-docs: stopped early — ${result.filesChanged} file(s) changed before interrupt.\\n`,\n );\n }\n diagnostics = result.diagnostics.sort(\n (a, b) =>\n a.file.localeCompare(b.file) ||\n a.line - b.line ||\n a.column - b.column,\n );\n } finally {\n process.off(\"SIGINT\", onSigint);\n }\n } else {\n diagnostics = lintPaths(files, cwd, opts);\n }\n\n const summary = summarize(diagnostics, files.length);\n\n if (flags.format === \"json\") {\n process.stdout.write(formatJson(diagnostics, summary) + \"\\n\");\n } else {\n process.stdout.write(\n formatPretty(diagnostics, summary, {\n color: shouldUseColor(flags.color),\n quiet: flags.quiet,\n }) + \"\\n\",\n );\n }\n\n // Only `error`-severity findings fail the command. Warnings are advisory.\n // SIGINT during --fix exits 130 (standard interrupted exit code) so CI\n // can distinguish a clean run from a partial one.\n if (interrupted) process.exit(130);\n process.exit(summary.errors > 0 ? 1 : 0);\n}\n\n/**\n * Resolve whether to emit ANSI escapes, in standard CLI precedence:\n * 1. Explicit `--color` / `--no-color` flag.\n * 2. `FORCE_COLOR` env (Node ecosystem convention) — any non-empty,\n * non-zero value forces color on.\n * 3. `NO_COLOR` env (no-color.org) — any non-empty value forces color off.\n * 4. Auto-detect via `process.stdout.isTTY`.\n */\nfunction shouldUseColor(explicit: boolean | undefined): boolean {\n if (explicit !== undefined) return explicit;\n const force = process.env.FORCE_COLOR;\n if (force !== undefined && force !== \"\" && force !== \"0\") return true;\n if (process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== \"\") {\n return false;\n }\n return process.stdout.isTTY === true;\n}\n\ninterface MaterializedConfig {\n rules: RulesConfig;\n collections: CollectionsConfig;\n site?: string;\n}\n\n/**\n * Read the integration's materialized lint config from `.nimbus/lint.json`.\n * Returns empty defaults when the file is absent or unreadable (lint must\n * work before the first build).\n *\n * **Re-validates the parsed config** against `validateLintOptions`, the\n * same validator the integration ran at config-setup time. The materialized\n * file is normally machine-written, so failures here typically mean a\n * hand-edit or a stale schema. The CLI surfaces the validation error and\n * exits — silently ignoring a typo'd rule code in `lint.json` contradicts\n * the anti-silent-typo invariant the rest of the codebase enforces.\n */\nfunction loadMaterializedConfig(cwd: string): MaterializedConfig {\n const file = path.join(cwd, \".nimbus\", \"lint.json\");\n let raw: string;\n try {\n raw = fs.readFileSync(file, \"utf8\");\n } catch {\n return { rules: {}, collections: {} };\n }\n\n let parsed: { rules?: unknown; collections?: unknown; site?: unknown };\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `nimbus-docs: ${path.relative(cwd, file) || file} is not valid JSON — ${detail}. ` +\n \"Delete the file (it'll be regenerated by `astro build`) or fix the syntax.\\n\",\n );\n process.exit(1);\n }\n\n let validated;\n try {\n validated = validateLintOptions(\n { rules: parsed.rules, collections: parsed.collections },\n IMPLEMENTED_CODES,\n );\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `${detail}\\n\\n` +\n `This shape lives in ${path.relative(cwd, file) || file} — usually machine-written by the Nimbus integration at \\`astro build\\`. ` +\n \"If you've hand-edited it, fix or delete the file. Otherwise, re-run `astro build` to regenerate it.\\n\",\n );\n process.exit(1);\n }\n\n const site = typeof parsed.site === \"string\" ? parsed.site : undefined;\n return { rules: validated.rules, collections: validated.collections, site };\n}\n","#!/usr/bin/env node\n\n/**\n * `nimbus-docs` CLI entry.\n *\n * Surface:\n *\n * nimbus → list (table of installable items)\n * nimbus-docs list → list\n * nimbus-docs list --type ui|lib|feature\n * nimbus-docs add → list\n * nimbus-docs add <slug> → install (component path or feature path)\n * nimbus-docs add <slug> --yes → component: skip overwrite prompts\n * nimbus-docs add <slug> --print → feature: print markdown to stdout (skip detect)\n *\n * Feature behavior mirrors Flue's `add` command: print markdown to stdout\n * iff `--print` OR an agent is detected; otherwise print human-friendly\n * pipe instructions to stderr.\n *\n * The bundled index makes `list` (and `add` with no slug) work offline.\n * Per-item content is fetched from `REGISTRY_BASE_URL` only when actually\n * installing a slug — override via `NIMBUS_REGISTRY_URL` for local dev.\n */\n\nimport mri from \"mri\";\nimport * as p from \"@clack/prompts\";\n\nimport { BUNDLED_INDEX } from \"./_registry.generated.js\";\nimport { cleanCommand } from \"./clean.js\";\nimport { installComponents } from \"./component.js\";\nimport { loadDotenv } from \"./dotenv.js\";\nimport { installFeature } from \"./feature.js\";\nimport { lintCommand } from \"./lint.js\";\nimport {\n getIndexEntry,\n listEntries,\n resolveComponentTree,\n} from \"./resolver.js\";\n\n// Load .env from the user's cwd so per-project NIMBUS_REGISTRY_URL (and\n// any future env vars) work without shell prefixes. Shell-provided vars\n// always win (loadDotenv only sets undefined keys).\nloadDotenv(process.cwd());\n\ndeclare const __APP_VERSION__: string;\n\ninterface CliArgs {\n _: string[];\n yes: boolean;\n print: boolean;\n help: boolean;\n version: boolean;\n quiet: boolean;\n fix: boolean;\n type?: string;\n format?: string;\n rule?: string;\n color?: boolean;\n}\n\nconst HELP = `\n Usage: nimbus-docs <command> [args]\n\n Commands:\n list [--type ui|lib|feature] List available registry items\n add Same as \\`list\\`\n add <slug> Install a component or hand off a feature\n lint Lint .mdx content for authoring-quality issues\n clean Remove .nimbus/cache (incremental-builds cache)\n\n Flags:\n --yes, -y Component: overwrite conflicts without prompting\n --print Feature: print markdown to stdout (skip agent detect)\n --type <ui|lib|feature> \\`list\\`: filter by type\n --format <json> \\`lint\\`: machine-readable output\n --rule <nimbus/...> \\`lint\\`: run a single rule\n --fix \\`lint\\`: apply auto-fixes in place\n --quiet \\`lint\\`: errors only, suppress warnings\n --help, -h\n --version, -v\n\n Examples:\n nimbus-docs add dialog # component: resolve + install\n nimbus-docs add 404-page --print | claude # explicit pipe to claude\n nimbus-docs lint # pretty output, exit non-zero on error\n nimbus-docs lint --format=json # agent-readable diagnostics\n nimbus-docs lint --rule=nimbus/single-h1 # one rule\n`;\n\nasync function main(): Promise<void> {\n const args = mri(process.argv.slice(2), {\n boolean: [\"yes\", \"print\", \"help\", \"version\", \"quiet\", \"color\", \"fix\"],\n string: [\"type\", \"format\", \"rule\"],\n default: { color: undefined },\n alias: { y: \"yes\", h: \"help\", v: \"version\" },\n }) as unknown as CliArgs;\n\n if (args.help) {\n process.stdout.write(HELP);\n return;\n }\n if (args.version) {\n process.stdout.write(`${__APP_VERSION__}\\n`);\n return;\n }\n\n const [command, slug] = args._;\n\n if (command === \"lint\") {\n await lintCommand({\n format: args.format,\n quiet: args.quiet,\n rule: args.rule,\n color: args.color,\n fix: args.fix,\n });\n return;\n }\n\n if (command === \"clean\") {\n await cleanCommand();\n return;\n }\n\n if (command === \"list\" || (command === \"add\" && !slug) || !command) {\n listCommand(args.type);\n return;\n }\n\n if (command === \"add\") {\n await addCommand(slug!, {\n yes: args.yes,\n print: args.print,\n });\n return;\n }\n\n p.log.error(`Unknown command: \\`${command}\\`. Try \\`nimbus-docs --help\\`.`);\n process.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// `nimbus-docs list`\n// ---------------------------------------------------------------------------\n\nfunction listCommand(typeFilter: string | undefined): void {\n const typeMap: Record<string, \"registry:ui\" | \"registry:lib\" | \"registry:feature\"> = {\n ui: \"registry:ui\",\n lib: \"registry:lib\",\n feature: \"registry:feature\",\n };\n\n const filter =\n typeFilter && typeFilter in typeMap\n ? { type: typeMap[typeFilter] }\n : undefined;\n\n if (typeFilter && !(typeFilter in typeMap)) {\n p.log.error(\n `Unknown --type \"${typeFilter}\". Valid: ui, lib, feature.`,\n );\n process.exit(1);\n }\n\n const items = listEntries(filter);\n if (items.length === 0) {\n p.log.info(\"No items match the filter.\");\n return;\n }\n\n // Group by type for readability.\n const grouped: Record<string, typeof items> = {\n \"registry:ui\": [],\n \"registry:lib\": [],\n \"registry:feature\": [],\n };\n for (const item of items) grouped[item.type]!.push(item);\n\n const labels: Record<string, string> = {\n \"registry:ui\": \"Components\",\n \"registry:lib\": \"Utilities\",\n \"registry:feature\": \"Features\",\n };\n const widths = items.reduce(\n (m, i) => Math.max(m, i.name.length),\n 0,\n );\n\n process.stdout.write(\"\\n\");\n for (const [type, label] of Object.entries(labels)) {\n const group = grouped[type];\n if (!group || group.length === 0) continue;\n process.stdout.write(` ${label}\\n`);\n for (const item of group) {\n process.stdout.write(\n ` ${item.name.padEnd(widths + 2)}${item.description}\\n`,\n );\n }\n process.stdout.write(\"\\n\");\n }\n process.stdout.write(\n ` Install: nimbus-docs add <name> · ${items.length} item${items.length === 1 ? \"\" : \"s\"}\\n\\n`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// `nimbus-docs add <slug>`\n// ---------------------------------------------------------------------------\n\nasync function addCommand(\n slug: string,\n flags: { yes: boolean; print: boolean },\n): Promise<void> {\n const entry = getIndexEntry(slug);\n if (!entry) {\n p.log.error(\n `Unknown registry item: \\`${slug}\\`. Try \\`nimbus-docs list\\` to see what's available.`,\n );\n process.exit(1);\n }\n\n if (entry.type === \"registry:feature\") {\n await installFeature(slug, { print: flags.print });\n return;\n }\n\n // Component / utility path.\n p.intro(`nimbus-docs add ${slug}`);\n p.log.info(`${entry.title} — ${entry.description}`);\n\n const spinner = p.spinner();\n spinner.start(\"Resolving dependencies\");\n let items;\n try {\n items = await resolveComponentTree(slug);\n spinner.stop(\n `Resolved ${items.length} item${items.length === 1 ? \"\" : \"s\"}.`,\n );\n } catch (err) {\n spinner.stop(\"Failed to resolve.\");\n p.log.error((err as Error).message);\n process.exit(1);\n }\n\n if (items.length > 1) {\n p.log.message(\n \"Install order:\\n \" + items.map((i) => i.name).join(\" → \"),\n );\n }\n\n const report = await installComponents(items, {\n cwd: process.cwd(),\n yes: flags.yes,\n });\n\n const lines: string[] = [];\n if (report.written.length > 0) {\n lines.push(`✓ Wrote ${report.written.length} file${report.written.length === 1 ? \"\" : \"s\"}`);\n }\n if (report.skipped.length > 0) {\n lines.push(`↷ Skipped: ${report.skipped.join(\", \")}`);\n }\n if (report.npmDepsInstalled.length > 0) {\n lines.push(\n `+ Installed ${report.npmDepsInstalled.length} npm dep${report.npmDepsInstalled.length === 1 ? \"\" : \"s\"}: ${report.npmDepsInstalled.join(\", \")}`,\n );\n }\n\n if (lines.length === 0) {\n p.outro(\"Nothing to do.\");\n } else {\n p.outro(lines.join(\"\\n\"));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Entrypoint\n// ---------------------------------------------------------------------------\n\nmain().catch((err) => {\n p.log.error(`${(err as Error).message}`);\n process.exit(1);\n});\n\n// Tell TS BUNDLED_INDEX is used (so no `verbatimModuleSyntax` warning).\nvoid BUNDLED_INDEX;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["addCommand","addCommand"],"sources":["../../src/cli/_registry.generated.ts","../../src/cli/clean.ts","../../src/cli/pm.ts","../../src/cli/component.ts","../../src/cli/dotenv.ts","../../src/cli/resolver.ts","../../src/cli/feature.ts","../../src/lint/disables.ts","../../src/lint/fix.ts","../../src/lint/engine.ts","../../src/lint/discover.ts","../../src/lint/format.ts","../../src/cli/lint.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Bundled registry index — auto-generated by\n * apps/www/scripts/generate-registry.ts. Do not edit by hand.\n *\n * Re-run via: pnpm --filter @nimbus/www generate-registry\n */\n\nexport type RegistryEntryType =\n | \"registry:ui\"\n | \"registry:lib\"\n | \"registry:feature\";\n\nexport interface RegistryIndexEntry {\n name: string;\n type: RegistryEntryType;\n title: string;\n description: string;\n}\n\nexport interface BundledIndex {\n version: 1;\n items: Record<string, RegistryIndexEntry>;\n}\n\nexport const REGISTRY_BASE_URL = \"https://nimbus-docs.com/registry\";\n\nexport const BUNDLED_INDEX: BundledIndex = {\n \"version\": 1,\n \"items\": {\n \"cn\": {\n \"name\": \"cn\",\n \"type\": \"registry:lib\",\n \"title\": \"cn\",\n \"description\": \"Tailwind-aware className merger built on clsx + tailwind-merge.\"\n },\n \"accordion\": {\n \"name\": \"accordion\",\n \"type\": \"registry:ui\",\n \"title\": \"Accordion\",\n \"description\": \"Vertically stacked collapsible sections.\"\n },\n \"aside\": {\n \"name\": \"aside\",\n \"type\": \"registry:ui\",\n \"title\": \"Aside\",\n \"description\": \"Generic boxed callout. Building block for Callout, Note, Warning.\"\n },\n \"badge\": {\n \"name\": \"badge\",\n \"type\": \"registry:ui\",\n \"title\": \"Badge\",\n \"description\": \"Small status / category pill.\"\n },\n \"banner\": {\n \"name\": \"banner\",\n \"type\": \"registry:ui\",\n \"title\": \"Banner\",\n \"description\": \"Site-wide dismissible announcement bar.\"\n },\n \"breadcrumbs\": {\n \"name\": \"breadcrumbs\",\n \"type\": \"registry:ui\",\n \"title\": \"Breadcrumbs\",\n \"description\": \"Page-context navigation crumbs.\"\n },\n \"button\": {\n \"name\": \"button\",\n \"type\": \"registry:ui\",\n \"title\": \"Button\",\n \"description\": \"Action trigger with variant/size/shape options. Owns the shared button/variants styling that LinkButton reuses.\"\n },\n \"callout\": {\n \"name\": \"callout\",\n \"type\": \"registry:ui\",\n \"title\": \"Callout\",\n \"description\": \"Inline note / tip / warning / danger / info card.\"\n },\n \"card\": {\n \"name\": \"card\",\n \"type\": \"registry:ui\",\n \"title\": \"Card\",\n \"description\": \"Generic content card with optional title and footer.\"\n },\n \"card-grid\": {\n \"name\": \"card-grid\",\n \"type\": \"registry:ui\",\n \"title\": \"CardGrid\",\n \"description\": \"Responsive grid layout for cards.\"\n },\n \"code\": {\n \"name\": \"code\",\n \"type\": \"registry:ui\",\n \"title\": \"Code\",\n \"description\": \"Inline / block code wrapper. Re-exports Astro's built-in <Code> (Shiki).\"\n },\n \"code-group\": {\n \"name\": \"code-group\",\n \"type\": \"registry:ui\",\n \"title\": \"CodeGroup\",\n \"description\": \"Tabbed group of code blocks.\"\n },\n \"collapsible\": {\n \"name\": \"collapsible\",\n \"type\": \"registry:ui\",\n \"title\": \"Collapsible\",\n \"description\": \"Headless show/hide primitive — building block for Accordion and Sidebar groups.\"\n },\n \"dialog\": {\n \"name\": \"dialog\",\n \"type\": \"registry:ui\",\n \"title\": \"Dialog\",\n \"description\": \"Modal dialog with focus-trap and body-scroll lock.\"\n },\n \"embed\": {\n \"name\": \"embed\",\n \"type\": \"registry:ui\",\n \"title\": \"Embed\",\n \"description\": \"Responsive iframe / video / external content wrapper.\"\n },\n \"file-tree\": {\n \"name\": \"file-tree\",\n \"type\": \"registry:ui\",\n \"title\": \"FileTree\",\n \"description\": \"Render a directory tree as nested markup.\"\n },\n \"frame\": {\n \"name\": \"frame\",\n \"type\": \"registry:ui\",\n \"title\": \"Frame\",\n \"description\": \"Decorative outer frame for screenshots and demos.\"\n },\n \"layer-card\": {\n \"name\": \"layer-card\",\n \"type\": \"registry:ui\",\n \"title\": \"LayerCard\",\n \"description\": \"Stacked-card container with sticky header. Base for CodeGroup and PackageManagers.\"\n },\n \"link-button\": {\n \"name\": \"link-button\",\n \"type\": \"registry:ui\",\n \"title\": \"LinkButton\",\n \"description\": \"Anchor styled as a button. Shares styling with Button via button/variants.\"\n },\n \"link-card\": {\n \"name\": \"link-card\",\n \"type\": \"registry:ui\",\n \"title\": \"LinkCard\",\n \"description\": \"Card whose entire surface is a link.\"\n },\n \"package-managers\": {\n \"name\": \"package-managers\",\n \"type\": \"registry:ui\",\n \"title\": \"PackageManagers\",\n \"description\": \"Tabbed install command block translated across npm / pnpm / yarn / bun.\"\n },\n \"page-actions\": {\n \"name\": \"page-actions\",\n \"type\": \"registry:ui\",\n \"title\": \"PageActions\",\n \"description\": \"Inline page-header actions: copy the page as markdown, open the raw .md.\"\n },\n \"pagination\": {\n \"name\": \"pagination\",\n \"type\": \"registry:ui\",\n \"title\": \"Pagination\",\n \"description\": \"Prev / next page navigation.\"\n },\n \"popover\": {\n \"name\": \"popover\",\n \"type\": \"registry:ui\",\n \"title\": \"Popover\",\n \"description\": \"Floating panel anchored to a trigger element.\"\n },\n \"search\": {\n \"name\": \"search\",\n \"type\": \"registry:ui\",\n \"title\": \"Search\",\n \"description\": \"Command-palette search dialog with a provider seam. Defaults to Pagefind.\"\n },\n \"sidebar\": {\n \"name\": \"sidebar\",\n \"type\": \"registry:ui\",\n \"title\": \"Sidebar\",\n \"description\": \"Docs sidebar with nested groups and active-link tracking.\"\n },\n \"steps\": {\n \"name\": \"steps\",\n \"type\": \"registry:ui\",\n \"title\": \"Steps\",\n \"description\": \"Numbered ordered-list with vertical connectors.\"\n },\n \"tabs\": {\n \"name\": \"tabs\",\n \"type\": \"registry:ui\",\n \"title\": \"Tabs\",\n \"description\": \"Tabbed content panels (manual + Starlight-compatible modes).\"\n },\n \"theme-toggle\": {\n \"name\": \"theme-toggle\",\n \"type\": \"registry:ui\",\n \"title\": \"ThemeToggle\",\n \"description\": \"Light / dark theme switcher button.\"\n },\n \"toc\": {\n \"name\": \"toc\",\n \"type\": \"registry:ui\",\n \"title\": \"TOC\",\n \"description\": \"On-page table of contents with active-heading tracking.\"\n },\n \"version-switcher\": {\n \"name\": \"version-switcher\",\n \"type\": \"registry:ui\",\n \"title\": \"VersionPicker\",\n \"description\": \"Header dropdown for switching between docs versions. Reads `versions` from nimbus.config.ts, uses the build-time alternates table to land readers on the same logical page in the target version. Includes deprecation badge and hidden-version exclusion. Renders nothing when versioning is off or only one version is configured.\"\n },\n \"diagram\": {\n \"name\": \"diagram\",\n \"type\": \"registry:lib\",\n \"title\": \"Diagram UI\",\n \"description\": \"React visual components for `nimbus-docs/react`'s headless <Diagram> wrapper: ActionBar, ActionButton (ghost + primary variants), ChipGroup, Tabs (uses useTabIndicator), DiagramControls (toolbar with status slot + pre-wired Play/Pause/Reset via useDiagram), DiagramDefs (shared SVG filter/marker defs), DiagramStage (bordered dotted-grid canvas + shared keyframes), CardBadge, DiagramDebug, DiagramPauseAll. Install when authoring interactive diagrams. Lifts as React, not Astro — kept paradigm-segregated under src/components/react/diagram/.\"\n },\n \"diagram-scene\": {\n \"name\": \"diagram-scene\",\n \"type\": \"registry:lib\",\n \"title\": \"Diagram scene\",\n \"description\": \"Declarative card factory over `nimbus-docs/react`: author a diagram as data (phase steps, active-id table, edge specs) plus a CSS layout of labelled nodes. Measurement, edge routing, the SVG layer, and active-state styling are handled by the component — user-owned, restyle freely. `<Scene>` composes inside an existing <Diagram>; `createScene` wraps it into a standalone card. For pill-and-arrow diagrams; bespoke cards compose the hooks directly.\"\n },\n \"404-page\": {\n \"name\": \"404-page\",\n \"type\": \"registry:feature\",\n \"title\": \"Custom 404 page\",\n \"description\": \"Generate a brand-matched 404 page for the docs site.\"\n },\n \"ai-native\": {\n \"name\": \"ai-native\",\n \"type\": \"registry:feature\",\n \"title\": \"AI-native static surface\",\n \"description\": \"Add llms.txt, markdown variants, robots.txt, and an AgentDirective to a Nimbus docs site.\"\n },\n \"changelog\": {\n \"name\": \"changelog\",\n \"type\": \"registry:feature\",\n \"title\": \"Changelog\",\n \"description\": \"Add a reverse-chronological changelog at /changelog — a dated timeline feed that renders full entries inline, with tag filtering, year-grouped load-more pagination, per-entry permalinks, OG cards, markdown alternates, and an optional RSS feed. Generic: tags are opaque strings you define. For a feed-style changelog; for a docs-shaped tree use `nimbus-docs add new-collection`.\"\n },\n \"component-showcase\": {\n \"name\": \"component-showcase\",\n \"type\": \"registry:feature\",\n \"title\": \"Component showcase\",\n \"description\": \"Add a /components grid landing plus per-component showcase pages at /components/<slug>, driven by a dedicated content collection. For sites documenting their own UI library.\"\n },\n \"lint-prose-textlint\": {\n \"name\": \"lint-prose-textlint\",\n \"type\": \"registry:feature\",\n \"title\": \"Prose linting with textlint\",\n \"description\": \"Add textlint with write-good, alex, and terminology rules — npm-native prose linting that runs alongside nimbus-docs lint.\"\n },\n \"mermaid\": {\n \"name\": \"mermaid\",\n \"type\": \"registry:feature\",\n \"title\": \"Mermaid diagrams\",\n \"description\": \"Add lazy-loaded, theme-aware Mermaid.js diagram rendering with a skeleton loading state and a full-screen expand dialog.\"\n },\n \"new-collection\": {\n \"name\": \"new-collection\",\n \"type\": \"registry:feature\",\n \"title\": \"Add a new collection\",\n \"description\": \"End-to-end setup for a non-version content tree on a Nimbus docs site — blog, API reference, changelog, glossary. Creates the folder, registers the collection, scaffolds routes. For docs versions, use `nimbus-docs add new-version`.\"\n },\n \"new-version\": {\n \"name\": \"new-version\",\n \"type\": \"registry:feature\",\n \"title\": \"Add a docs version\",\n \"description\": \"End-to-end setup for adding a docs version to a Nimbus site. Creates the content directory, registers the collection, scaffolds routes, declares the manifest, installs the version-switcher picker, and wires it into your Header and DocsLayout. One command for one mental task.\"\n },\n \"pagefind-search\": {\n \"name\": \"pagefind-search\",\n \"type\": \"registry:feature\",\n \"title\": \"Pagefind search\",\n \"description\": \"Add static Pagefind indexing and the Nimbus search dialog to an existing docs site.\"\n }\n }\n};\n","/**\n * `nimbus-docs clean` — remove the incremental-build cache.\n *\n * Use when you suspect cache corruption, after a framework upgrade, or\n * when the incremental-builds documentation specifically tells you to.\n * Safe to run any time — the cache is rebuilt on the next `astro build`.\n *\n * Clears both locations:\n * - `node_modules/.astro/nimbus` — the default (rides Astro's cacheDir, the\n * dir hosts persist between builds).\n * - `.nimbus/cache` — the fallback, used when Astro's cacheDir can't be\n * resolved.\n *\n * Note: if you've set a custom Astro `cacheDir`, remove `<cacheDir>/nimbus`\n * manually — the standalone CLI doesn't load your Astro config.\n */\nimport { rm, stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport * as p from \"@clack/prompts\";\n\nexport async function cleanCommand(cwd: string = process.cwd()): Promise<void> {\n const candidates = [\n resolve(cwd, \"node_modules/.astro/nimbus\"),\n resolve(cwd, \".nimbus/cache\"),\n ];\n\n let removedAny = false;\n for (const dir of candidates) {\n let exists = false;\n try {\n exists = (await stat(dir)).isDirectory();\n } catch {\n // not present\n }\n if (!exists) continue;\n await rm(dir, { recursive: true, force: true });\n p.log.success(`Removed ${dir}`);\n removedAny = true;\n }\n\n if (!removedAny) p.log.info(\"No cache to clean.\");\n}\n","/**\n * Package-manager detection + install command helpers.\n *\n * Detection prefers lockfile presence in the user's cwd, then falls back\n * to the `npm_config_user_agent` env var the active package manager sets\n * when invoking the CLI. Finally falls back to `npm`.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nconst LOCKFILES: ReadonlyArray<readonly [string, PackageManager]> = [\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"bun.lockb\", \"bun\"],\n [\"bun.lock\", \"bun\"],\n [\"package-lock.json\", \"npm\"],\n];\n\nexport function detectPackageManager(cwd: string): PackageManager {\n for (const [lockfile, pm] of LOCKFILES) {\n if (existsSync(join(cwd, lockfile))) return pm;\n }\n const ua = process.env.npm_config_user_agent ?? \"\";\n if (ua.startsWith(\"pnpm\")) return \"pnpm\";\n if (ua.startsWith(\"yarn\")) return \"yarn\";\n if (ua.startsWith(\"bun\")) return \"bun\";\n return \"npm\";\n}\n\n/**\n * Command + args to install one or more new npm deps. Each PM picks the\n * verb that both adds to package.json AND installs:\n *\n * npm install <deps...>\n * pnpm add <deps...>\n * yarn add <deps...>\n * bun add <deps...>\n */\nexport function addCommand(\n pm: PackageManager,\n deps: string[],\n): { bin: string; args: string[] } {\n if (deps.length === 0) {\n throw new Error(\"addCommand called with empty deps\");\n }\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"install\", ...deps] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"add\", ...deps] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"add\", ...deps] };\n case \"bun\":\n return { bin: \"bun\", args: [\"add\", ...deps] };\n }\n}\n","/**\n * Component / utility installer.\n *\n * Walks the resolved list of items, writes each file (per-file overwrite\n * prompt on conflict), then collects all npm `dependencies` across the\n * tree and runs `<pm> add` once for the dedup'd set.\n *\n * File destination: `<cwd>/src/<path>`. The `path` field already encodes\n * the directory layout (e.g. `components/ui/dialog/Dialog.astro`).\n */\n\nimport { spawn } from \"node:child_process\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\n\nimport { addCommand, detectPackageManager } from \"./pm.js\";\nimport type { ComponentItem } from \"./resolver.js\";\n\nexport interface InstallOptions {\n /** User's project root. */\n cwd: string;\n /** Skip overwrite prompts; assume \"overwrite\" on every conflict. */\n yes: boolean;\n}\n\nexport interface InstallReport {\n /** Individual files actually written. */\n written: string[];\n /** Registry slugs skipped wholesale by the user. */\n skipped: string[];\n npmDepsInstalled: string[];\n}\n\nexport async function installComponents(\n items: ComponentItem[],\n options: InstallOptions,\n): Promise<InstallReport> {\n const report: InstallReport = {\n written: [],\n skipped: [],\n npmDepsInstalled: [],\n };\n\n // ---- 1. Write files — atomic per registry item -------------------------\n //\n // Each item (e.g. `dialog`) is treated as an indivisible unit: when any\n // of its files conflict, we prompt once for the whole slug. Letting users\n // overwrite Dialog.astro while keeping DialogContent.astro is a footgun\n // — components are cohesive and meant to evolve together.\n const srcDir = join(options.cwd, \"src\");\n\n for (const item of items) {\n const filePlans = item.files.map((file) => {\n const targetAbs = join(srcDir, file.path);\n return {\n targetAbs,\n targetRel: relative(options.cwd, targetAbs),\n content: file.content,\n exists: existsSync(targetAbs),\n };\n });\n\n const conflicts = filePlans.filter((f) => f.exists);\n\n // Utilities (registry:lib) are transitive dependencies of UI\n // components — install silently when missing, skip silently when\n // present. Never prompt or overwrite: users may have customized\n // them (e.g. cn) and being asked about `cn` every time you `add` a\n // component is noise.\n if (item.type === \"registry:lib\") {\n if (conflicts.length > 0) {\n report.skipped.push(item.name);\n continue;\n }\n } else if (conflicts.length > 0 && !options.yes) {\n const total = filePlans.length;\n const message =\n conflicts.length === total\n ? `${item.name} is already installed (${total} file${total === 1 ? \"\" : \"s\"}). Overwrite?`\n : `${item.name} is partially installed (${conflicts.length} of ${total} file${total === 1 ? \"\" : \"s\"} present). Overwrite all?`;\n\n const choice = await p.select({\n message,\n options: [\n { value: \"overwrite\", label: \"Overwrite — replace existing files\" },\n { value: \"skip\", label: \"Skip — leave files as-is\" },\n { value: \"cancel\", label: \"Cancel install\" },\n ],\n initialValue: \"overwrite\",\n });\n\n if (p.isCancel(choice) || choice === \"cancel\") {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n if (choice === \"skip\") {\n report.skipped.push(item.name);\n continue;\n }\n }\n\n // Either no conflicts, --yes, or user chose overwrite. Write every file.\n for (const plan of filePlans) {\n mkdirSync(dirname(plan.targetAbs), { recursive: true });\n writeFileSync(plan.targetAbs, plan.content);\n report.written.push(plan.targetRel);\n }\n }\n\n // ---- 2. Install missing npm deps ---------------------------------------\n const allDeps = new Set<string>();\n for (const item of items) {\n for (const dep of item.dependencies) allDeps.add(dep);\n }\n\n if (allDeps.size > 0) {\n const newDeps = filterAlreadyInstalled(options.cwd, [...allDeps]);\n if (newDeps.length > 0) {\n const pm = detectPackageManager(options.cwd);\n const { bin, args } = addCommand(pm, newDeps);\n const spinner = p.spinner();\n spinner.start(`${pm} add ${newDeps.join(\" \")}`);\n try {\n await runCommand(bin, args, options.cwd);\n spinner.stop(\n `Installed ${newDeps.length} dep${newDeps.length === 1 ? \"\" : \"s\"}.`,\n );\n report.npmDepsInstalled = newDeps;\n } catch (err) {\n spinner.stop(\"Dependency install failed.\");\n p.log.warn(\n `Could not install ${newDeps.join(\", \")}. Run \\`${bin} ${args.join(\" \")}\\` manually.`,\n );\n }\n }\n }\n\n return report;\n}\n\n/**\n * Filter out deps already present in `dependencies` or `devDependencies`\n * of the user's package.json. If package.json is missing, returns all.\n */\nfunction filterAlreadyInstalled(cwd: string, deps: string[]): string[] {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return deps;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const installed = new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ]);\n return deps.filter((d) => !installed.has(d));\n } catch {\n return deps;\n }\n}\n\nfunction runCommand(\n bin: string,\n args: string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolveP, rejectP) => {\n const child = spawn(bin, args, {\n cwd,\n stdio: [\"ignore\", \"ignore\", \"inherit\"],\n });\n child.on(\"close\", (code) =>\n code === 0\n ? resolveP()\n : rejectP(new Error(`${bin} ${args.join(\" \")} exited ${code}`)),\n );\n child.on(\"error\", rejectP);\n });\n}\n","/**\n * Tiny .env loader — no dependency.\n *\n * Reads `.env` from the user's cwd at CLI startup and sets any KEY=VALUE\n * pairs into `process.env` IF the variable isn't already set (so a shell-\n * provided env always wins over the file). Supports the basic cases:\n *\n * KEY=value\n * KEY=\"quoted value\"\n * KEY='quoted value'\n * # comments\n *\n * Used so `examples/local/.env` can carry `NIMBUS_REGISTRY_URL=...` without\n * the user having to prefix every CLI invocation.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport function loadDotenv(cwd: string): void {\n const path = join(cwd, \".env\");\n if (!existsSync(path)) return;\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return;\n }\n\n for (const rawLine of raw.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n\n const eq = line.indexOf(\"=\");\n if (eq <= 0) continue;\n\n const key = line.slice(0, eq).trim();\n if (!/^[A-Z_][A-Z0-9_]*$/i.test(key)) continue;\n\n let value = line.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n if (process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n}\n","/**\n * Registry resolver.\n *\n * Two entry points:\n *\n * - `resolveComponentTree(slug)` walks `registryDependencies` transitively\n * and returns a flat ordered list of components/utilities to install\n * (dependencies first, root last). Cycles are detected as repeated\n * visits and skipped.\n *\n * - `fetchFeatureMarkdown(slug)` returns the raw markdown for an\n * agent-handoff feature; the caller decides what to do with it.\n *\n * The base URL for hosted artifacts is read from the bundled index, with\n * an `NIMBUS_REGISTRY_URL` env override for local development.\n */\n\nimport {\n BUNDLED_INDEX,\n REGISTRY_BASE_URL,\n type RegistryIndexEntry,\n} from \"./_registry.generated.js\";\n\nexport interface RegistryFile {\n path: string;\n content: string;\n}\n\nexport interface ComponentItem {\n name: string;\n type: \"registry:ui\" | \"registry:lib\";\n title: string;\n description: string;\n dependencies: string[];\n registryDependencies: string[];\n files: RegistryFile[];\n}\n\n/**\n * Read the registry base URL on every call so `.env` files loaded after\n * module-import time (see cli/dotenv.ts) are picked up. The cost is\n * negligible — string interpolation of an env var.\n */\nfunction getBaseUrl(): string {\n return (process.env.NIMBUS_REGISTRY_URL ?? REGISTRY_BASE_URL).replace(\n /\\/$/,\n \"\",\n );\n}\n\n// ---------------------------------------------------------------------------\n// Index lookup (offline — no network)\n// ---------------------------------------------------------------------------\n\nexport function getIndexEntry(slug: string): RegistryIndexEntry | undefined {\n return BUNDLED_INDEX.items[slug];\n}\n\nexport function listEntries(filter?: {\n type?: RegistryIndexEntry[\"type\"];\n}): RegistryIndexEntry[] {\n const all = Object.values(BUNDLED_INDEX.items);\n if (!filter?.type) return all;\n return all.filter((e) => e.type === filter.type);\n}\n\n// ---------------------------------------------------------------------------\n// Network: component JSON + feature markdown\n// ---------------------------------------------------------------------------\n\nasync function httpGet(url: string): Promise<Response> {\n let res: Response;\n try {\n res = await fetch(url);\n } catch (err) {\n const cause = (err as Error).message;\n throw new Error(\n `Could not reach the registry at ${url}.\\n` +\n ` Underlying error: ${cause}\\n\\n` +\n ` Things to try:\\n` +\n ` - Is the registry server running? Start it with \\`pnpm local\\` (in the monorepo root).\\n` +\n ` - Override the URL: NIMBUS_REGISTRY_URL=https://example.com nimbus-docs add ...\\n` +\n ` - Check the value in your project's .env file.`,\n );\n }\n if (!res.ok) {\n throw new Error(\n `Registry returned ${res.status} ${res.statusText} for ${url}. ` +\n `The server is up but doesn't know about this slug — check \\`nimbus-docs list\\` for valid names.`,\n );\n }\n return res;\n}\n\nexport async function fetchComponent(slug: string): Promise<ComponentItem> {\n const res = await httpGet(`${getBaseUrl()}/components/${slug}.json`);\n return (await res.json()) as ComponentItem;\n}\n\nexport async function fetchFeatureMarkdown(slug: string): Promise<string> {\n const res = await httpGet(`${getBaseUrl()}/features/${slug}.md`);\n return await res.text();\n}\n\n// ---------------------------------------------------------------------------\n// Transitive dep resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Depth-first walk of registryDependencies. Returns items in install order\n * (deps before dependents), deduplicated by slug.\n */\nexport async function resolveComponentTree(\n rootSlug: string,\n): Promise<ComponentItem[]> {\n const visited = new Set<string>();\n const ordered: ComponentItem[] = [];\n\n async function visit(slug: string): Promise<void> {\n if (visited.has(slug)) return;\n visited.add(slug);\n\n const item = await fetchComponent(slug);\n\n // Walk deps first so they're earlier in the install order.\n for (const dep of item.registryDependencies) {\n await visit(dep);\n }\n\n ordered.push(item);\n }\n\n await visit(rootSlug);\n return ordered;\n}\n","/**\n * Feature installer — agent-handoff.\n *\n * If `--print` is set OR `determineAgent()` says the CLI is running inside\n * a known coding agent, the markdown is piped to stdout for the agent to\n * consume. Otherwise we print human-friendly instructions on stderr\n * telling the user exactly how to pipe the output to their agent of choice.\n *\n * No picker, no clipboard mode — the printed pipe commands cover both.\n */\n\nimport { determineAgent } from \"@vercel/detect-agent\";\n\nimport { fetchFeatureMarkdown } from \"./resolver.js\";\n\nexport interface FeatureInstallOptions {\n /** Force markdown to stdout regardless of agent detection. */\n print: boolean;\n}\n\nexport async function installFeature(\n slug: string,\n options: FeatureInstallOptions,\n): Promise<void> {\n const markdown = await fetchFeatureMarkdown(slug);\n\n // Predicate: explicit --print, or detection says we're running inside\n // a known agent (which captures our stdout).\n const detected = await determineAgent().catch(() => ({\n isAgent: false as const,\n }));\n const isAgentMode = options.print || detected.isAgent === true;\n\n if (isAgentMode) {\n process.stdout.write(markdown);\n if (!markdown.endsWith(\"\\n\")) process.stdout.write(\"\\n\");\n return;\n }\n\n printHumanInstructions(slug);\n}\n\n/**\n * Stderr-only. We don't put this on stdout because if the user pipes our\n * output anywhere by accident, only the markdown should reach the agent.\n *\n * Agents are listed with a blank line between the \"first-tier\" CLIs\n * (claude/codex/cursor-agent) and the rest (opencode/pi).\n */\nfunction printHumanInstructions(slug: string): void {\n const cmd = `nimbus-docs add ${slug}`;\n const stream = process.stderr;\n stream.write(`${cmd}\\n\\n`);\n stream.write(\"To install this feature, pipe it to your coding agent:\\n\\n\");\n stream.write(` ${cmd} --print | claude\\n`);\n stream.write(` ${cmd} --print | codex\\n`);\n stream.write(` ${cmd} --print | cursor-agent\\n\\n`);\n stream.write(` ${cmd} --print | opencode\\n`);\n stream.write(` ${cmd} --print | pi\\n`);\n stream.write(\"Or paste this prompt into any agent:\\n\\n\");\n stream.write(` Run \"${cmd} --print\" and follow the instructions.\\n`);\n}\n","/**\n * Per-file and per-line disable directives — both designed so the disable\n * itself is greppable:\n *\n * - Frontmatter `nimbusDisableRules: [\"nimbus/internal-link\"]` disables\n * the listed codes for the whole file.\n * - An inline `{/* nimbus-rule-disable-next-line nimbus/bare-url *​/}`\n * comment disables the named code on the next non-blank line.\n *\n * Both require a rule code: an empty `nimbusDisableRules` array is a\n * reported error, so the reason for a disable is always visible.\n */\n\nimport { isRuleCode } from \"./diagnostic.js\";\nimport type { RuleReport } from \"./rule.js\";\n\nexport interface DisableInfo {\n /** Rule codes disabled for the entire file. */\n fileDisabled: Set<string>;\n /** 1-based source line → rule codes disabled on that line. */\n lineDisabled: Map<number, Set<string>>;\n /** Malformed-directive findings (e.g. an empty disable array). */\n problems: RuleReport[];\n}\n\nconst INLINE_DISABLE =\n /\\{\\/\\*\\s*nimbus-rule-disable-next-line\\s+(\\S+)\\s*\\*\\/\\}/;\n\nexport function collectDisables(\n frontmatter: Record<string, unknown> | null,\n frontmatterRaw: string | null,\n frontmatterStartLine: number,\n lines: string[],\n): DisableInfo {\n const fileDisabled = new Set<string>();\n const lineDisabled = new Map<number, Set<string>>();\n const problems: RuleReport[] = [];\n\n // ----- Frontmatter file-level disables.\n if (frontmatter && \"nimbusDisableRules\" in frontmatter) {\n const raw = frontmatter.nimbusDisableRules;\n const at = locateFrontmatterKey(\n frontmatterRaw,\n \"nimbusDisableRules\",\n frontmatterStartLine,\n );\n if (!Array.isArray(raw)) {\n problems.push({\n message:\n '\"nimbusDisableRules\" must be an array of rule codes, e.g. [\"nimbus/internal-link\"].',\n line: at.line,\n column: at.column,\n });\n } else if (raw.length === 0) {\n problems.push({\n message:\n '\"nimbusDisableRules\" is empty — remove it, or name the rule code(s) you mean to disable so the reason stays greppable.',\n line: at.line,\n column: at.column,\n });\n } else {\n for (const entry of raw) {\n if (typeof entry !== \"string\") {\n problems.push({\n message: `\"nimbusDisableRules\" entry ${JSON.stringify(entry)} must be a string rule code.`,\n line: at.line,\n column: at.column,\n });\n continue;\n }\n if (!isRuleCode(entry)) {\n problems.push({\n message: `\"nimbusDisableRules\" lists \"${entry}\", which is not a known rule code — typos here silently no-op, so we surface them.`,\n line: at.line,\n column: at.column,\n });\n continue;\n }\n fileDisabled.add(entry);\n }\n }\n }\n\n // ----- Inline next-line disables.\n for (let i = 0; i < lines.length; i++) {\n const match = lines[i]!.match(INLINE_DISABLE);\n if (!match) continue;\n const code = match[1]!;\n if (!isRuleCode(code)) {\n problems.push({\n message: `inline disable references \"${code}\", which is not a known rule code — typos here silently no-op, so we surface them.`,\n line: i + 1,\n column: (match.index ?? 0) + 1,\n });\n continue;\n }\n // Target the next non-blank line (1-based).\n let target = -1;\n for (let j = i + 1; j < lines.length; j++) {\n if (lines[j]!.trim() !== \"\") {\n target = j + 1;\n break;\n }\n }\n if (target === -1) continue;\n const set = lineDisabled.get(target) ?? new Set<string>();\n set.add(code);\n lineDisabled.set(target, set);\n }\n\n return { fileDisabled, lineDisabled, problems };\n}\n\n/** Is a diagnostic for `code` on `line` suppressed by a disable directive? */\nexport function isDisabled(\n info: DisableInfo,\n code: string,\n line: number,\n): boolean {\n if (info.fileDisabled.has(code)) return true;\n return info.lineDisabled.get(line)?.has(code) ?? false;\n}\n\nfunction locateFrontmatterKey(\n frontmatterRaw: string | null,\n key: string,\n startLine: number,\n): { line: number; column: number } {\n if (frontmatterRaw) {\n const rawLines = frontmatterRaw.split(\"\\n\");\n for (let i = 0; i < rawLines.length; i++) {\n const m = rawLines[i]!.match(new RegExp(`^(\\\\s*)${key}\\\\s*:`));\n if (m) return { line: startLine + i, column: m[1]!.length + 1 };\n }\n }\n return { line: startLine, column: 1 };\n}\n","/**\n * Apply rule `fix` edits to source. Diagnostic-level atomic: each\n * diagnostic's edits are applied together or not at all, and a diagnostic\n * whose span overlaps one already applied is skipped (a second pass picks\n * it up). Edits are character offsets into the source — the same unist\n * offsets the parser reports — applied right-to-left so earlier offsets\n * stay valid.\n *\n * No \"smart\" fixes: this only applies edits a rule already declared. The\n * change is plain and reviewable in `git diff`.\n */\n\nimport type { Diagnostic } from \"./diagnostic.js\";\n\nexport interface FixResult {\n output: string;\n /** Number of diagnostics whose fix was applied. */\n fixed: number;\n /**\n * The exact diagnostic objects whose fixes were applied. The caller\n * uses this (by identity, not by index) to know which diagnostics to\n * suppress from the post-fix report — the rest stay in the output\n * because their `fix` field was advisory-only (no edits) or was\n * skipped due to an overlap with another applied fix.\n */\n applied: Set<Diagnostic>;\n}\n\nexport function applyFixes(source: string, diagnostics: Diagnostic[]): FixResult {\n const items = diagnostics\n .filter(\n (d): d is Diagnostic & { fix: NonNullable<Diagnostic[\"fix\"]> } =>\n d.fix !== undefined && d.fix.edits.length > 0,\n )\n .map((d) => {\n const edits = d.fix.edits;\n return {\n diagnostic: d,\n edits,\n start: Math.min(...edits.map((e) => e.range[0])),\n end: Math.max(...edits.map((e) => e.range[1])),\n };\n })\n // Apply from the end of the file backwards.\n .sort((a, b) => b.start - a.start);\n\n let output = source;\n let frontier = Number.POSITIVE_INFINITY;\n const applied = new Set<Diagnostic>();\n\n for (const item of items) {\n if (item.end > frontier) continue; // overlaps an already-applied span\n const ordered = [...item.edits].sort((a, b) => b.range[0] - a.range[0]);\n for (const edit of ordered) {\n output =\n output.slice(0, edit.range[0]) + edit.text + output.slice(edit.range[1]);\n }\n frontier = item.start;\n applied.add(item.diagnostic);\n }\n\n return { output, fixed: applied.size, applied };\n}\n","/**\n * The lint engine. Runs the registered rules over parsed files, resolves\n * each rule's severity from config, applies per-file and per-line disables,\n * and collects everything into the one `Diagnostic` envelope.\n *\n * Pure and synchronous: `lintFile` takes a `ParsedFile` and returns\n * `Diagnostic[]`, which is what the test harness drives directly. The\n * disk-walking entry points (`lintPaths`) sit on top.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport {\n resolveRuleForCollection,\n type CollectionsConfig,\n type RulesConfig,\n} from \"./config.js\";\nimport type { Diagnostic, RuleCode, Severity } from \"./diagnostic.js\";\nimport { collectDisables, isDisabled } from \"./disables.js\";\nimport { applyFixes } from \"./fix.js\";\nimport { parseSource, type ParsedFile } from \"./parse.js\";\nimport type { RuleReport } from \"./rule.js\";\nimport { RULES } from \"./rules/index.js\";\nimport type { AuthoringRuleCode } from \"./diagnostic.js\";\n\nexport interface LintOptions {\n /** Per-rule severity. Authoring rules are off by default; omitted/empty means no authoring rules run. */\n rules?: RulesConfig;\n /**\n * Per-collection overrides. Each entry's `rules` block shallow-merges\n * over the top-level `rules` for files in that collection. Resolution\n * precedence: top-level → per-collection → per-file `nimbusDisableRules`\n * → per-line inline disables.\n */\n collections?: CollectionsConfig;\n /**\n * Restrict the run to a single rule (CLI `--rule`). Authoring-only —\n * build validators don't have a severity knob, so `--rule=mdx-syntax`\n * is rejected at the CLI before reaching the engine.\n */\n only?: AuthoringRuleCode;\n /**\n * The project's canonical site URL (from `nimbusConfig.site`), threaded\n * into each rule's `ctx.site`. Lets site-aware rules (e.g.\n * `no-self-host-url`) catch the deploy host without making the user\n * duplicate it in their lint config.\n */\n site?: string;\n /**\n * Cancellation signal — checked between files in `lintPaths`/`fixPaths`.\n * The CLI wires this to SIGINT so Ctrl-C stops the run after the\n * in-progress file finishes (its write is already atomic), instead of\n * killing the process mid-rename.\n */\n signal?: AbortSignal;\n}\n\nexport interface LintSummary {\n errors: number;\n warnings: number;\n total: number;\n files: number;\n}\n\n/** Lint one already-parsed file. */\nexport function lintFile(file: ParsedFile, opts: LintOptions = {}): Diagnostic[] {\n // `opts.only` targets one rule via `--rule=<code>`. Since authoring rules\n // default to \"off\", a bare `--rule=foo` against the framework default\n // would resolve to off and print nothing — confusing UX for a flag the\n // user explicitly asked for. Force-enable it at \"error\" *unless* the\n // user already wrote an explicit top-level setting (including \"off\" —\n // explicit top-level intent wins over a CLI shortcut). When the\n // force-enable is active we also strip per-collection overrides for that\n // same code, so a `collections.<name>.rules: { \"foo\": \"off\" }` block\n // doesn't silently re-shadow the rule for whole subtrees (the exact\n // \"silent zero coverage\" failure mode the --rule flag exists to prevent).\n const forceEnable =\n opts.only !== undefined && opts.rules?.[opts.only] === undefined;\n const rules = forceEnable\n ? { ...(opts.rules ?? {}), [opts.only!]: \"error\" as const }\n : opts.rules ?? {};\n const collections = forceEnable\n ? stripCodeFromCollections(opts.collections ?? {}, opts.only!)\n : opts.collections ?? {};\n const out: Diagnostic[] = [];\n\n // A file that didn't parse won't render — emit the build-level syntax\n // error and stop; there's no tree to run authoring rules against.\n if (file.parseError) {\n return [\n {\n code: \"nimbus/mdx-syntax\",\n severity: \"error\",\n source: \"docs-compiler\",\n file: file.path,\n message: `MDX failed to parse: ${file.parseError.message}`,\n line: file.parseError.line,\n column: file.parseError.column,\n },\n ];\n }\n\n const disables = collectDisables(\n file.frontmatter,\n file.frontmatterRaw,\n file.frontmatterStartLine,\n file.lines,\n );\n\n // Malformed disable directives are themselves frontmatter problems, and\n // always errors — a disable you can't read is worse than no disable.\n for (const problem of disables.problems) {\n out.push({\n code: \"nimbus/frontmatter-shape\",\n severity: \"error\",\n source: \"docs-compiler\",\n file: file.path,\n message: problem.message,\n line: problem.line,\n column: problem.column,\n });\n }\n\n for (const rule of RULES) {\n if (opts.only && rule.code !== opts.only) continue;\n const resolved = resolveRuleForCollection(\n rule.code,\n rules,\n collections,\n file.collection,\n );\n if (resolved.severity === \"off\") continue;\n const severity = resolved.severity as Severity;\n\n const reports: RuleReport[] = [];\n try {\n rule.run({\n file,\n options: resolved.options,\n site: opts.site,\n report: (report) => reports.push(report),\n });\n } catch (err) {\n // A rule that throws is a bug in the rule, not user content. Skip it\n // and keep linting — one bad rule shouldn't blind the user to the\n // other thirteen.\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `nimbus-docs: rule \\`${rule.code}\\` threw on ${file.path}: ${detail}\\n`,\n );\n continue;\n }\n\n for (const report of reports) {\n if (isDisabled(disables, rule.code, report.line)) continue;\n out.push({\n code: rule.code,\n severity,\n source: \"docs-compiler\",\n file: file.path,\n message: report.message,\n line: report.line,\n column: report.column,\n endLine: report.endLine,\n endColumn: report.endColumn,\n fix: report.fix,\n });\n }\n }\n\n out.sort(\n (a, b) =>\n a.line - b.line ||\n a.column - b.column ||\n a.code.localeCompare(b.code),\n );\n return out;\n}\n\n/** Lint a set of absolute file paths, reading + parsing each one. */\nexport function lintPaths(\n absPaths: string[],\n projectRoot: string,\n opts: LintOptions = {},\n): Diagnostic[] {\n const out: Diagnostic[] = [];\n for (const abs of absPaths) {\n if (opts.signal?.aborted) break;\n const rel = path.relative(projectRoot, abs);\n try {\n const source = fs.readFileSync(abs, \"utf8\");\n const parsed = parseSource(source, {\n path: rel,\n absPath: abs,\n collection: inferCollection(rel),\n });\n out.push(...lintFile(parsed, opts));\n } catch (err) {\n // I/O errors (file vanished mid-run, permission denied) shouldn't kill\n // the whole lint — skip the file with a clear message and continue.\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(`nimbus-docs: skipped ${rel}: ${detail}\\n`);\n }\n }\n return out;\n}\n\nexport interface FixRunResult {\n /** Diagnostics that remain after fixing (i.e. those with no auto-fix). */\n diagnostics: Diagnostic[];\n /** Count of diagnostics whose fix was applied. */\n fixed: number;\n /** Count of files actually rewritten. */\n filesChanged: number;\n}\n\n/**\n * Hard cap on per-file fix passes — a runaway rule that keeps emitting\n * convergence-breaking fixes won't hang the CLI. 10 is well above any\n * realistic chain (the longest in practice is 2–3: a fix unmasks a\n * second-tier finding the first pass shadowed).\n */\nconst MAX_FIX_PASSES = 10;\n\n/**\n * Lint + apply auto-fixes in place. Each file is read, linted, fixed, and\n * (when content changed) atomically rewritten via tmp-file + rename — so a\n * crash or SIGINT mid-write can't truncate the user's content. We iterate\n * each file until the output stabilizes or `MAX_FIX_PASSES` is hit; this\n * picks up diagnostics that were skipped on pass 1 due to overlap with\n * another applied fix, plus diagnostics a fix on pass 1 unmasked.\n *\n * A diagnostic stays in the report when it wasn't *actually* applied —\n * which includes the advisory-only case (a rule emits a `fix` with no\n * `edits`, like the did-you-mean hint on `internal-link`) and the\n * skipped-overlap case after the convergence cap. Both are real,\n * unresolved issues; suppressing them just because the diagnostic carries\n * a `fix` field would silently hide broken links and other\n * un-auto-fixable problems.\n *\n * Files that fail to read, parse, or write are skipped with a stderr\n * message and the run continues — one bad file shouldn't leave the rest\n * of the working tree half-fixed.\n */\nexport function fixPaths(\n absPaths: string[],\n projectRoot: string,\n opts: LintOptions = {},\n): FixRunResult {\n let fixed = 0;\n let filesChanged = 0;\n const remaining: Diagnostic[] = [];\n\n for (const abs of absPaths) {\n if (opts.signal?.aborted) break;\n const rel = path.relative(projectRoot, abs);\n try {\n const original = fs.readFileSync(abs, \"utf8\");\n let current = original;\n let lastDiagnostics: Diagnostic[] = [];\n let lastApplied = new Set<Diagnostic>();\n\n for (let pass = 0; pass < MAX_FIX_PASSES; pass++) {\n const parsed = parseSource(current, {\n path: rel,\n absPath: abs,\n collection: inferCollection(rel),\n });\n const diagnostics = lintFile(parsed, opts);\n const result = applyFixes(current, diagnostics);\n fixed += result.fixed;\n lastDiagnostics = diagnostics;\n lastApplied = result.applied;\n if (result.output === current) break;\n current = result.output;\n }\n\n if (current !== original) {\n writeFileAtomicSync(abs, current);\n filesChanged++;\n }\n for (const d of lastDiagnostics) {\n if (!lastApplied.has(d)) remaining.push(d);\n }\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(`nimbus-docs: skipped ${rel}: ${detail}\\n`);\n }\n }\n\n return { diagnostics: remaining, fixed, filesChanged };\n}\n\n/**\n * Write atomically: serialize to a sibling tmp file, fsync, rename over the\n * target. A crash mid-write leaves the original intact instead of a\n * truncated .mdx. The tmp file lives next to the target so the rename is\n * a same-filesystem atomic op.\n */\nfunction writeFileAtomicSync(abs: string, content: string): void {\n const tmp = `${abs}.nimbus-tmp-${process.pid}`;\n const fd = fs.openSync(tmp, \"w\");\n try {\n fs.writeFileSync(fd, content, \"utf8\");\n fs.fsyncSync(fd);\n } finally {\n fs.closeSync(fd);\n }\n try {\n fs.renameSync(tmp, abs);\n } catch (err) {\n try {\n fs.unlinkSync(tmp);\n } catch {\n // best-effort cleanup\n }\n throw err;\n }\n}\n\nexport function summarize(diagnostics: Diagnostic[], files: number): LintSummary {\n let errors = 0;\n let warnings = 0;\n for (const d of diagnostics) {\n if (d.severity === \"error\") errors++;\n else warnings++;\n }\n return { errors, warnings, total: diagnostics.length, files };\n}\n\n/** Infer the collection name from a `src/content/<name>/…` path. */\nfunction inferCollection(relPath: string): string | null {\n const match = relPath\n .replace(/\\\\/g, \"/\")\n .match(/(?:^|\\/)src\\/content\\/([^/]+)\\//);\n return match ? match[1]! : null;\n}\n\n/**\n * Return a new collections config with `code` removed from every per-\n * collection `rules` block. Used by `lintFile`'s `--rule` force-enable so\n * a per-collection \"off\" doesn't silently shadow the CLI flag — the\n * user explicitly asked to see this rule's findings.\n */\nfunction stripCodeFromCollections(\n collections: CollectionsConfig,\n code: AuthoringRuleCode,\n): CollectionsConfig {\n const out: CollectionsConfig = {};\n for (const [name, cfg] of Object.entries(collections)) {\n if (!cfg.rules || !(code in cfg.rules)) {\n out[name] = cfg;\n continue;\n }\n const { [code]: _stripped, ...remaining } = cfg.rules;\n out[name] = { ...cfg, rules: remaining };\n }\n return out;\n}\n","/**\n * File discovery for the CLI — walk the configured content directories for\n * `.mdx` files, skipping `node_modules` and dotfolders. Mirrors the walk\n * the MDX validator already uses, kept here so the lint CLI doesn't depend\n * on integration internals.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport function findMdxFiles(dirs: string[]): string[] {\n const out: string[] = [];\n for (const dir of dirs) walk(dir, out);\n out.sort();\n return out;\n}\n\nfunction walk(dir: string, out: string[]): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw err;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name.startsWith(\".\")) continue;\n walk(full, out);\n } else if (entry.isFile() && entry.name.endsWith(\".mdx\")) {\n out.push(full);\n }\n }\n}\n","/**\n * Diagnostic formatters: a pretty terminal form and a machine-readable\n * JSON form. The pretty form reads as —\n *\n * src/content/docs/getting-started.mdx:42:18 error nimbus/single-h1\n * more than one top-level \"#\" heading …\n *\n * The JSON form is the agent-shaped envelope, validated against the\n * committed `diagnostic.schema.json`.\n */\n\nimport type { Diagnostic } from \"./diagnostic.js\";\nimport type { LintSummary } from \"./engine.js\";\n\nconst COLORS = {\n reset: \"\u001b[0m\",\n dim: \"\u001b[2m\",\n red: \"\u001b[31m\",\n yellow: \"\u001b[33m\",\n green: \"\u001b[32m\",\n bold: \"\u001b[1m\",\n};\n\nexport interface FormatOptions {\n color: boolean;\n /** Suppress `warn`-severity diagnostics from the output. */\n quiet?: boolean;\n}\n\nexport function formatPretty(\n diagnostics: Diagnostic[],\n summary: LintSummary,\n opts: FormatOptions,\n): string {\n const paint = (code: string, text: string) =>\n opts.color ? `${code}${text}${COLORS.reset}` : text;\n\n const shown = opts.quiet\n ? diagnostics.filter((d) => d.severity === \"error\")\n : diagnostics;\n\n const lines: string[] = [];\n for (const d of shown) {\n const sev =\n d.severity === \"error\"\n ? paint(COLORS.red, \"error\")\n : paint(COLORS.yellow, \"warn\");\n const loc = paint(COLORS.dim, `${d.file}:${d.line}:${d.column}`);\n lines.push(`${loc} ${sev} ${paint(COLORS.dim, d.code)}`);\n lines.push(` ${d.message}`);\n if (d.fix && d.fix.description) {\n lines.push(` ${paint(COLORS.dim, `fix: ${d.fix.description}`)}`);\n }\n }\n\n if (summary.total === 0) {\n return paint(COLORS.green, `✓ ${summary.files} file(s) lint clean.`);\n }\n\n const tally = `${summary.errors} error(s), ${summary.warnings} warning(s) across ${summary.files} file(s)`;\n lines.push(\"\");\n lines.push(\n summary.errors > 0\n ? paint(COLORS.red, `✗ ${tally}`)\n : paint(COLORS.yellow, `${tally}`),\n );\n return lines.join(\"\\n\");\n}\n\nexport function formatJson(\n diagnostics: Diagnostic[],\n summary: LintSummary,\n): string {\n return JSON.stringify(\n {\n version: 1,\n summary: {\n errors: summary.errors,\n warnings: summary.warnings,\n total: summary.total,\n files: summary.files,\n },\n diagnostics,\n },\n null,\n 2,\n );\n}\n","/**\n * `nimbus-docs lint` — the authoring-quality verdict for MDX content.\n *\n * Walks the content directories, runs the registered rules, prints\n * diagnostics, and exits non-zero when any `error`-severity finding\n * survives. The build is never gated by this command — drafts that fail\n * lint still render under `astro dev`.\n *\n * Severity overrides live with the integration\n * (`nimbus(config, { rules })`), which materializes them to\n * `.nimbus/lint.json` at build/dev time; this command reads that file when\n * present and otherwise runs every authoring rule at its default. In-file\n * disables (`nimbusDisableRules`, inline comments) work with no config.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport {\n findMdxFiles,\n fixPaths,\n formatJson,\n formatPretty,\n IMPLEMENTED_CODES,\n isRuleCode,\n lintPaths,\n summarize,\n validateLintOptions,\n type CollectionsConfig,\n type Diagnostic,\n type RuleCode,\n type RulesConfig,\n} from \"../lint/index.js\";\n\nexport interface LintCliFlags {\n format?: string;\n quiet?: boolean;\n rule?: string;\n color?: boolean;\n fix?: boolean;\n}\n\nexport async function lintCommand(flags: LintCliFlags): Promise<void> {\n const cwd = process.cwd();\n const contentDir = path.join(cwd, \"src\", \"content\");\n\n if (flags.rule) {\n if (!isRuleCode(flags.rule)) {\n process.stderr.write(\n `Unknown rule code: \\`${flags.rule}\\`. See https://nimbus-docs.com/lint for the rule list.\\n`,\n );\n process.exit(1);\n }\n // `isRuleCode` accepts every registered code, including build validators\n // (which run inside `astro build`, not here) and planned codes that\n // don't have a rule module yet. Either case would silently exit clean\n // with zero coverage — a worse outcome than \"unknown rule\" for a\n // command users invoke specifically because they trust it to enforce\n // something.\n if (!IMPLEMENTED_CODES.has(flags.rule)) {\n process.stderr.write(\n `Rule \\`${flags.rule}\\` is not implemented by \\`nimbus-docs lint\\`. ` +\n `Build validators run inside \\`astro build\\`, not here; planned rules haven't shipped yet. ` +\n `Implemented authoring rules: ${[...IMPLEMENTED_CODES].sort().join(\", \")}.\\n`,\n );\n process.exit(1);\n }\n }\n\n const files = findMdxFiles([contentDir]);\n if (files.length === 0) {\n process.stderr.write(\n `No .mdx files found under ${path.relative(cwd, contentDir) || \".\"}. ` +\n \"Run from your project root.\\n\",\n );\n process.exit(0);\n }\n\n const { rules, collections, site } = loadMaterializedConfig(cwd);\n const opts = {\n rules,\n collections,\n site,\n // `flags.rule` already passed through validation that rejects build\n // validators; the cast here is the type-level reflection of that runtime\n // narrowing (LintOptions.only is `AuthoringRuleCode` because `--rule`\n // can't force-enable a build validator).\n only: flags.rule as import(\"../lint/diagnostic.js\").AuthoringRuleCode | undefined,\n };\n\n let diagnostics: Diagnostic[];\n let interrupted = false;\n if (flags.fix) {\n // Atomic writes already protect each file from SIGINT corruption — the\n // .tmp+rename in `fixPaths` either finishes or doesn't. The handler\n // here just stops the iteration after the in-progress file finishes\n // and gives the user a clean \"stopped after N files\" report instead\n // of a default Ctrl-C abort with partial output.\n const ac = new AbortController();\n const onSigint = () => {\n if (interrupted) {\n process.stderr.write(\"\\nnimbus-docs: forced exit.\\n\");\n process.exit(130);\n }\n interrupted = true;\n process.stderr.write(\n \"\\nnimbus-docs: interrupted — finishing current file, then stopping. Press Ctrl-C again to force.\\n\",\n );\n ac.abort();\n };\n process.on(\"SIGINT\", onSigint);\n try {\n const result = fixPaths(files, cwd, { ...opts, signal: ac.signal });\n if (result.fixed > 0) {\n process.stderr.write(\n `Fixed ${result.fixed} issue(s) across ${result.filesChanged} file(s).\\n`,\n );\n }\n if (interrupted) {\n process.stderr.write(\n `nimbus-docs: stopped early — ${result.filesChanged} file(s) changed before interrupt.\\n`,\n );\n }\n diagnostics = result.diagnostics.sort(\n (a, b) =>\n a.file.localeCompare(b.file) ||\n a.line - b.line ||\n a.column - b.column,\n );\n } finally {\n process.off(\"SIGINT\", onSigint);\n }\n } else {\n diagnostics = lintPaths(files, cwd, opts);\n }\n\n const summary = summarize(diagnostics, files.length);\n\n if (flags.format === \"json\") {\n process.stdout.write(formatJson(diagnostics, summary) + \"\\n\");\n } else {\n process.stdout.write(\n formatPretty(diagnostics, summary, {\n color: shouldUseColor(flags.color),\n quiet: flags.quiet,\n }) + \"\\n\",\n );\n }\n\n // Only `error`-severity findings fail the command. Warnings are advisory.\n // SIGINT during --fix exits 130 (standard interrupted exit code) so CI\n // can distinguish a clean run from a partial one.\n if (interrupted) process.exit(130);\n process.exit(summary.errors > 0 ? 1 : 0);\n}\n\n/**\n * Resolve whether to emit ANSI escapes, in standard CLI precedence:\n * 1. Explicit `--color` / `--no-color` flag.\n * 2. `FORCE_COLOR` env (Node ecosystem convention) — any non-empty,\n * non-zero value forces color on.\n * 3. `NO_COLOR` env (no-color.org) — any non-empty value forces color off.\n * 4. Auto-detect via `process.stdout.isTTY`.\n */\nfunction shouldUseColor(explicit: boolean | undefined): boolean {\n if (explicit !== undefined) return explicit;\n const force = process.env.FORCE_COLOR;\n if (force !== undefined && force !== \"\" && force !== \"0\") return true;\n if (process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== \"\") {\n return false;\n }\n return process.stdout.isTTY === true;\n}\n\ninterface MaterializedConfig {\n rules: RulesConfig;\n collections: CollectionsConfig;\n site?: string;\n}\n\n/**\n * Read the integration's materialized lint config from `.nimbus/lint.json`.\n * Returns empty defaults when the file is absent or unreadable (lint must\n * work before the first build).\n *\n * **Re-validates the parsed config** against `validateLintOptions`, the\n * same validator the integration ran at config-setup time. The materialized\n * file is normally machine-written, so failures here typically mean a\n * hand-edit or a stale schema. The CLI surfaces the validation error and\n * exits — silently ignoring a typo'd rule code in `lint.json` contradicts\n * the anti-silent-typo invariant the rest of the codebase enforces.\n */\nfunction loadMaterializedConfig(cwd: string): MaterializedConfig {\n const file = path.join(cwd, \".nimbus\", \"lint.json\");\n let raw: string;\n try {\n raw = fs.readFileSync(file, \"utf8\");\n } catch {\n return { rules: {}, collections: {} };\n }\n\n let parsed: { rules?: unknown; collections?: unknown; site?: unknown };\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `nimbus-docs: ${path.relative(cwd, file) || file} is not valid JSON — ${detail}. ` +\n \"Delete the file (it'll be regenerated by `astro build`) or fix the syntax.\\n\",\n );\n process.exit(1);\n }\n\n let validated;\n try {\n validated = validateLintOptions(\n { rules: parsed.rules, collections: parsed.collections },\n IMPLEMENTED_CODES,\n );\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `${detail}\\n\\n` +\n `This shape lives in ${path.relative(cwd, file) || file} — usually machine-written by the Nimbus integration at \\`astro build\\`. ` +\n \"If you've hand-edited it, fix or delete the file. Otherwise, re-run `astro build` to regenerate it.\\n\",\n );\n process.exit(1);\n }\n\n const site = typeof parsed.site === \"string\" ? parsed.site : undefined;\n return { rules: validated.rules, collections: validated.collections, site };\n}\n","#!/usr/bin/env node\n\n/**\n * `nimbus-docs` CLI entry.\n *\n * Surface:\n *\n * nimbus → list (table of installable items)\n * nimbus-docs list → list\n * nimbus-docs list --type ui|lib|feature\n * nimbus-docs add → list\n * nimbus-docs add <slug> → install (component path or feature path)\n * nimbus-docs add <slug> --yes → component: skip overwrite prompts\n * nimbus-docs add <slug> --print → feature: print markdown to stdout (skip detect)\n *\n * Feature behavior: print markdown to stdout iff `--print` OR an agent is\n * detected; otherwise print human-friendly pipe instructions to stderr.\n *\n * The bundled index makes `list` (and `add` with no slug) work offline.\n * Per-item content is fetched from `REGISTRY_BASE_URL` only when actually\n * installing a slug — override via `NIMBUS_REGISTRY_URL` for local dev.\n */\n\nimport mri from \"mri\";\nimport * as p from \"@clack/prompts\";\n\nimport { BUNDLED_INDEX } from \"./_registry.generated.js\";\nimport { cleanCommand } from \"./clean.js\";\nimport { installComponents } from \"./component.js\";\nimport { loadDotenv } from \"./dotenv.js\";\nimport { installFeature } from \"./feature.js\";\nimport { lintCommand } from \"./lint.js\";\nimport {\n getIndexEntry,\n listEntries,\n resolveComponentTree,\n} from \"./resolver.js\";\n\n// Load .env from the user's cwd so per-project NIMBUS_REGISTRY_URL (and\n// any future env vars) work without shell prefixes. Shell-provided vars\n// always win (loadDotenv only sets undefined keys).\nloadDotenv(process.cwd());\n\ndeclare const __APP_VERSION__: string;\n\ninterface CliArgs {\n _: string[];\n yes: boolean;\n print: boolean;\n help: boolean;\n version: boolean;\n quiet: boolean;\n fix: boolean;\n type?: string;\n format?: string;\n rule?: string;\n color?: boolean;\n}\n\nconst HELP = `\n Usage: nimbus-docs <command> [args]\n\n Commands:\n list [--type ui|lib|feature] List available registry items\n add Same as \\`list\\`\n add <slug> Install a component or hand off a feature\n lint Lint .mdx content for authoring-quality issues\n clean Remove .nimbus/cache (incremental-builds cache)\n\n Flags:\n --yes, -y Component: overwrite conflicts without prompting\n --print Feature: print markdown to stdout (skip agent detect)\n --type <ui|lib|feature> \\`list\\`: filter by type\n --format <json> \\`lint\\`: machine-readable output\n --rule <nimbus/...> \\`lint\\`: run a single rule\n --fix \\`lint\\`: apply auto-fixes in place\n --quiet \\`lint\\`: errors only, suppress warnings\n --help, -h\n --version, -v\n\n Examples:\n nimbus-docs add dialog # component: resolve + install\n nimbus-docs add 404-page --print | claude # explicit pipe to claude\n nimbus-docs lint # pretty output, exit non-zero on error\n nimbus-docs lint --format=json # agent-readable diagnostics\n nimbus-docs lint --rule=nimbus/single-h1 # one rule\n`;\n\nasync function main(): Promise<void> {\n const args = mri(process.argv.slice(2), {\n boolean: [\"yes\", \"print\", \"help\", \"version\", \"quiet\", \"color\", \"fix\"],\n string: [\"type\", \"format\", \"rule\"],\n default: { color: undefined },\n alias: { y: \"yes\", h: \"help\", v: \"version\" },\n }) as unknown as CliArgs;\n\n if (args.help) {\n process.stdout.write(HELP);\n return;\n }\n if (args.version) {\n process.stdout.write(`${__APP_VERSION__}\\n`);\n return;\n }\n\n const [command, slug] = args._;\n\n if (command === \"lint\") {\n await lintCommand({\n format: args.format,\n quiet: args.quiet,\n rule: args.rule,\n color: args.color,\n fix: args.fix,\n });\n return;\n }\n\n if (command === \"clean\") {\n await cleanCommand();\n return;\n }\n\n if (command === \"list\" || (command === \"add\" && !slug) || !command) {\n listCommand(args.type);\n return;\n }\n\n if (command === \"add\") {\n await addCommand(slug!, {\n yes: args.yes,\n print: args.print,\n });\n return;\n }\n\n p.log.error(`Unknown command: \\`${command}\\`. Try \\`nimbus-docs --help\\`.`);\n process.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// `nimbus-docs list`\n// ---------------------------------------------------------------------------\n\nfunction listCommand(typeFilter: string | undefined): void {\n const typeMap: Record<string, \"registry:ui\" | \"registry:lib\" | \"registry:feature\"> = {\n ui: \"registry:ui\",\n lib: \"registry:lib\",\n feature: \"registry:feature\",\n };\n\n const filter =\n typeFilter && typeFilter in typeMap\n ? { type: typeMap[typeFilter] }\n : undefined;\n\n if (typeFilter && !(typeFilter in typeMap)) {\n p.log.error(\n `Unknown --type \"${typeFilter}\". Valid: ui, lib, feature.`,\n );\n process.exit(1);\n }\n\n const items = listEntries(filter);\n if (items.length === 0) {\n p.log.info(\"No items match the filter.\");\n return;\n }\n\n // Group by type for readability.\n const grouped: Record<string, typeof items> = {\n \"registry:ui\": [],\n \"registry:lib\": [],\n \"registry:feature\": [],\n };\n for (const item of items) grouped[item.type]!.push(item);\n\n const labels: Record<string, string> = {\n \"registry:ui\": \"Components\",\n \"registry:lib\": \"Utilities\",\n \"registry:feature\": \"Features\",\n };\n const widths = items.reduce(\n (m, i) => Math.max(m, i.name.length),\n 0,\n );\n\n process.stdout.write(\"\\n\");\n for (const [type, label] of Object.entries(labels)) {\n const group = grouped[type];\n if (!group || group.length === 0) continue;\n process.stdout.write(` ${label}\\n`);\n for (const item of group) {\n process.stdout.write(\n ` ${item.name.padEnd(widths + 2)}${item.description}\\n`,\n );\n }\n process.stdout.write(\"\\n\");\n }\n process.stdout.write(\n ` Install: nimbus-docs add <name> · ${items.length} item${items.length === 1 ? \"\" : \"s\"}\\n\\n`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// `nimbus-docs add <slug>`\n// ---------------------------------------------------------------------------\n\nasync function addCommand(\n slug: string,\n flags: { yes: boolean; print: boolean },\n): Promise<void> {\n const entry = getIndexEntry(slug);\n if (!entry) {\n p.log.error(\n `Unknown registry item: \\`${slug}\\`. Try \\`nimbus-docs list\\` to see what's available.`,\n );\n process.exit(1);\n }\n\n if (entry.type === \"registry:feature\") {\n await installFeature(slug, { print: flags.print });\n return;\n }\n\n // Component / utility path.\n p.intro(`nimbus-docs add ${slug}`);\n p.log.info(`${entry.title} — ${entry.description}`);\n\n const spinner = p.spinner();\n spinner.start(\"Resolving dependencies\");\n let items;\n try {\n items = await resolveComponentTree(slug);\n spinner.stop(\n `Resolved ${items.length} item${items.length === 1 ? \"\" : \"s\"}.`,\n );\n } catch (err) {\n spinner.stop(\"Failed to resolve.\");\n p.log.error((err as Error).message);\n process.exit(1);\n }\n\n if (items.length > 1) {\n p.log.message(\n \"Install order:\\n \" + items.map((i) => i.name).join(\" → \"),\n );\n }\n\n const report = await installComponents(items, {\n cwd: process.cwd(),\n yes: flags.yes,\n });\n\n const lines: string[] = [];\n if (report.written.length > 0) {\n lines.push(`✓ Wrote ${report.written.length} file${report.written.length === 1 ? \"\" : \"s\"}`);\n }\n if (report.skipped.length > 0) {\n lines.push(`↷ Skipped: ${report.skipped.join(\", \")}`);\n }\n if (report.npmDepsInstalled.length > 0) {\n lines.push(\n `+ Installed ${report.npmDepsInstalled.length} npm dep${report.npmDepsInstalled.length === 1 ? \"\" : \"s\"}: ${report.npmDepsInstalled.join(\", \")}`,\n );\n }\n\n if (lines.length === 0) {\n p.outro(\"Nothing to do.\");\n } else {\n p.outro(lines.join(\"\\n\"));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Entrypoint\n// ---------------------------------------------------------------------------\n\nmain().catch((err) => {\n p.log.error(`${(err as Error).message}`);\n process.exit(1);\n});\n\n// Tell TS BUNDLED_INDEX is used (so no `verbatimModuleSyntax` warning).\nvoid BUNDLED_INDEX;\n"],"mappings":"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"}