docs
Generate a documentation site from your ADRs and specs. Use when the user says "generate docs", "create a docs site", or wants to publish their architecture decisions.
Governing Artifacts
Usage
/sdd:docs [project name or options] [--module <name>]
Required Tools
BashReadWriteEditGlobGrepTaskAskUserQuestion
Overview
Harness portability. This skill runs on any agent harness that loads Agent Skills — Claude Code, Codex CLI, OpenCode, Crush. Tool names used below (
AskUserQuestion,Task,TeamCreate,SendMessage,TaskCreate,ToolSearch,mcp__*,$\{CLAUDE_PLUGIN_ROOT\}) denote capabilities, not hard requirements: map each to your harness's equivalent or use the documented fallback per$\{CLAUDE_PLUGIN_ROOT\}/references/harness-compat.md. References toCLAUDE.mdmean the project memory file (CLAUDE.md,AGENTS.md, orCRUSH.md) per harness-compat § "Project Memory File". A citation of the formshared-patterns.md § "Section"names one##heading in that file — load only that section (see its "How to Read This File" note), never the whole file. Invocation and arguments. Where your harness has no command layer (Crush, Codex CLI, OpenCode) this skill is reached from itsdescription, not a slash command: the/sdd:\{name\}form below is Claude Code namespacing.$ARGUMENTSmeans whatever arrived with the invocation: take the target and any--flagsfrom the request that triggered this skill, and when neither is present follow this skill's documented no-argument path instead of reporting missing arguments (harness-compat § "Invocation and Arguments").
Transform ADRs and OpenSpec specs (located via the Artifact Path Resolution pattern from $\{CLAUDE_PLUGIN_ROOT\}/references/shared-patterns.md § "Artifact Path Resolution") into a polished documentation website with:
- RFC 2119 keyword highlighting (MUST, SHALL, MAY, etc.)
- ADR cross-reference linking (📝 ADR-0001 becomes a clickable link)
- SPEC cross-reference linking (PREFIX-NNN links to spec requirement anchors)
- Status/Date/Domain badge components
- Requirement box components for spec tables
- Consequence keyword highlighting (Good/Bad/Neutral) in ADRs
- Dark mode support
- Auto-generated sidebars
Supports two modes:
- Scaffold mode: Creates a standalone
docs-site/with its own Docusaurus installation - Integration mode: Generates a build-time plugin into an existing Docusaurus site
Process
Step 0: Resolve Artifact Paths
<!-- Governing: ADR-0016 (Workspace Mode), SPEC-0014 REQ "Artifact Path Resolution" -->
Follow the Artifact Path Resolution pattern from $\{CLAUDE_PLUGIN_ROOT\}/references/shared-patterns.md § "Artifact Path Resolution" to determine the ADR, spec, and PRD directories. If $ARGUMENTS contains --module <name>, resolve paths relative to that module; otherwise, in a workspace, aggregate across all modules. The resolved ADR directory is \{adr-dir\}, spec directory is \{spec-dir\}, and PRD directory is \{prd-dir\} (default docs/prds/, per 📝 ADR-0036).
<!-- Governing: ADR-0016 (Workspace Mode), SPEC-0014 REQ "Cross-Module Aggregation" -->
Cross-module aggregation: When in aggregate mode (no --module, workspace detected), include all modules' artifacts in the docs site. Organize the sidebar navigation by module:
Architecture/
├── api/
│ ├── ADRs/
│ │ ├── ADR-0001: Choose REST over GraphQL
│ │ └── ADR-0002: Choose PostgreSQL
│ └── Specs/
│ └── SPEC-0001: Web Dashboard
├── worker/
│ ├── ADRs/
│ │ └── ADR-0001: Choose Redis for queues
│ └── Specs/
│ └── SPEC-0001: Job Processing
└── Overview (cross-module index page)
Each module's artifacts are transformed independently and placed under a module-named directory in the docs output. The index page lists all modules with artifact counts. When --module is provided, generate docs for that single module only (flat structure, no module subdirectory). When in single-module mode (no workspace), operate normally with the existing flat structure.
Step 1: Pre-flight Checks
- Check if Node.js is installed. If not, tell the user: "Node.js is required to run the docs site. Please install it from https://nodejs.org/ and re-run this command." and stop.
- Check if
\{adr-dir\}has any ADR.mdfiles - Check if
\{prd-dir\}has anyPRD-*.mdfiles. PRDs are optional (📝 ADR-0036): when the directory is absent or empty, generate no PRD section and no empty placeholder page. When PRDs exist, give them their own sidebar section ahead of ADRs, matching thePRD → ADR → speclineage, and render each PRD'sgoverns:edges as links to the ADR and spec pages it governs. - Check if
\{spec-dir\}has any spec directories (containingspec.md). Validate spec pairing per$\{CLAUDE_PLUGIN_ROOT\}/references/shared-patterns.md§ "Spec Pairing Validation". - If NEITHER has content, tell the user: "No ADRs or specs found. Create some first with
/sdd:adror/sdd:spec, then re-run/sdd:docs." and stop. - If only one has content, proceed but note which is empty (e.g., "No specs found yet -- the docs site will only include ADRs for now.")
Step 2: Detect Existing Docusaurus Site and Upgrade State
2.1: Check for upgrade manifest
Check if .sdd-docs.json exists at the project root.
If .sdd-docs.json exists:
- Read and parse the manifest
- Check if the
siteDirreferenced in the manifest still exists on disk- If siteDir exists → enter Upgrade Mode (Step 3C). Skip Steps 2.2 and 2.3.
- If siteDir is missing → warn the user: "Found
.sdd-docs.jsonbut the site directory\{siteDir\}no longer exists." UseAskUserQuestionto offer:- "Re-scaffold a new docs site" → proceed with Scaffold Mode (Step 3A)
- "Cancel" → stop
If .sdd-docs.json does NOT exist, continue to Step 2.2.
2.2: Scan for existing Docusaurus sites
Scan the project root for directories containing docusaurus.config.ts or docusaurus.config.js:
find . -maxdepth 2 -name 'docusaurus.config.*' -not -path './docs-site/*' -not -path './node_modules/*' 2>/dev/null
2.3: Choose mode
If an existing docs site directory is detected (docs-site/ exists or an integration site was found in 2.2) but no .sdd-docs.json:
- Warn: "Upgrade tracking unavailable —
.sdd-docs.jsonnot found." - Use
AskUserQuestionto offer:- "Create manifest from current state" → compute SHA-256 checksums of all managed files in the existing site, write
.sdd-docs.jsonusing the current state as baseline, then enter Upgrade Mode (Step 3C) - "Continue without upgrade tracking" → proceed to mode selection below
- "Cancel" → stop
- "Create manifest from current state" → compute SHA-256 checksums of all managed files in the existing site, write
If an existing non-scaffold Docusaurus site is found (from Step 2.2), use AskUserQuestion to let the user choose:
- Option A: "Integrate into {directory}" -- proceed with Integration Mode (Step 3B)
- Option B: "Scaffold a new docs site" -- proceed with Scaffold Mode (Step 3A)
If no existing site is found, proceed directly with Scaffold Mode (Step 3A).
Step 3A: Scaffold Mode
Read and follow the plugin's skills/docs/references/scaffold-mode.md for the full scaffold workflow. After completion, proceed to Step 4 below.
Step 3B: Integration Mode
Read and follow the plugin's skills/docs/references/integration-mode.md for the full integration workflow. After completion, proceed to Step 4 below.
Step 3C: Upgrade Mode
Read and follow the plugin's skills/docs/references/upgrade-mode.md for the full upgrade workflow. This handles manifest-based file management, conflict resolution, and new template detection.
Step 4: Create Manifest
Runs after Step 3A or 3B to establish upgrade tracking.
Determine managed files based on mode:
- Scaffold: files in
docs-site/plugins/sdd-content/,docs-site/src/components/,docs-site/src/css/,docs-site/src/theme/ - Integration: files in
\{site\}/plugins/sync-spec-docs/,\{site\}/src/components/design-docs/,\{site\}/src/css/design-docs.css,\{site\}/src/theme/MDXComponents.tsx(if created/modified)
Compute SHA-256 checksum for each file (shasum -a 256 \{file-path\}), then write .sdd-docs.json:
{
"version": "<plugin version from .claude-plugin/plugin.json>",
"mode": "scaffold" | "integration",
"siteDir": "<relative path to site dir>",
"createdAt": "<ISO 8601>",
"updatedAt": "<ISO 8601>",
"files": {
"<relative-path>": { "checksum": "sha256:<hex-digest>", "managed": true }
}
}
Tell the user: "Created .sdd-docs.json with {N} tracked files. Future runs of /sdd:docs will detect changes and offer upgrades."
Rules
- Always read templates from the plugin directory, don't recreate from memory
- Configure the Docusaurus site for the current project (title, URLs, etc.)
- The transform scripts must work with the project's actual directory structure
- Don't include OpenAPI plugin config unless the project has an OpenAPI spec
- Keep
spec-emojis.jsonandspec-mapping.jsonas generated files (populated by build-spec-mapping.js) - In integration mode, NEVER overwrite the existing site's
docusaurus.config.tswholesale -- only add the plugin entry and CSS import - In integration mode, ALWAYS namespace components under
design-docs/to avoid collisions with existing components - In integration mode, generated files go to
\{site\}/docs/architecture/-- this directory is gitignored and regenerated on every build - Always create
.sdd-docs.jsonafter a fresh scaffold or integration install (Step 4) - Never delete or skip manifest creation -- it is required for upgrade tracking
- During upgrades (Step 3C), always ask before overwriting user-modified files
- The manifest
filesobject uses project-root-relative paths as keys - Checksum format is always
sha256:<hex-digest>(lowercase hex) - When creating a manifest from an existing site (Step 2.3 "Create manifest from current state"), set all files to
managed: trueand use their current checksums as the baseline - In workspace aggregate mode, MUST organize docs navigation by module with per-module subdirectories (Governing: 📝 ADR-0016, SPEC-0014 REQ "Cross-Module Aggregation")
- In workspace aggregate mode, MUST generate a cross-module index page listing all modules with artifact counts
- In workspace aggregate mode, transform scripts run per-module with output directed to module-named subdirectories
- When
--moduleis provided, generate docs for that single module only using flat structure
Key Template Files Reference
Scaffold Mode Templates (templates/docusaurus/)
The templates directory contains production-ready versions of all files. The cp -r approach copies everything; you only need to customize docusaurus.config.ts and package.json.
Docusaurus Plugin (plugins/sdd-content/)
index.js-- Consolidated Docusaurus plugin that:- Uses
lib-artifact-transformsfor YAML frontmatter parsing (replaces ~120 lines of custom YAML) - Builds the artifact graph per SPEC-0018 edge schema with 5 ADR edge types + 4 spec edge types
- Generates MDX files from ADRs and specs with badges, RFC 2119 keyword highlighting, cross-references (Governing: 📝 ADR-0006, SPEC-0004)
- Generates index pages (landing page, ADR section, spec section) with sidebar hierarchy diagrams
- Generates the artifact graph page with stats, full Mermaid flowchart, and orphan lists
- Implements
getPathsToWatch()for native Docusaurus hot reload (replaces chokidar-cli + concurrently)
- Uses
Integration Mode Templates (templates/integration/sync-spec-docs/)
A self-contained Docusaurus plugin with adapted transform scripts.
Plugin Entry
index.js-- Docusaurus plugin that runs transforms duringloadContent()and watches source files viagetPathsToWatch()
Transform Scripts (lib/)
transform-adrs.js-- ADR transforms with parameterized pathstransform-openspecs.js-- OpenSpec transforms with parameterized pathstransform-utils.js-- Shared utilities (RFC 2119 keywords, cross-references, link fixing)mdx-escape.js-- MDX v3 safety escapingbuild-spec-mapping.js-- Spec ID mapping (returns data instead of writing files)generate-index.js-- Index page generation with parameterized paths
Shared: React Components (templates/docusaurus/src/components/)
Used by both modes. In scaffold mode, they live at docs-site/src/components/. In integration mode, they're copied to \{site\}/src/components/design-docs/.
StatusBadge.tsx-- Status with emoji (accepted, proposed, draft, etc.)DateBadge.tsx-- Date display with calendar emojiDomainBadge.tsx-- Domain/category badgePriorityBadge.tsx-- P0-P4 priority levelsSeverityBadge.tsx-- Critical/High/Medium/Low/InfoRFCLevelBadge.tsx-- Maps RFC 2119 keywords to severity colorsRequirementBox.tsx-- Bordered container for spec requirements with ID anchorsField.tsx/FieldGroup.tsx-- Metadata label-value pairs
Shared: Theme and CSS (templates/docusaurus/src/)
src/theme/MDXComponents.tsx-- Registers all custom components for use in MDXsrc/css/custom.css-- All badge, keyword, component, and dark mode styles
Reference
integration-mode.md
Generates a build-time Docusaurus plugin into an existing site. The plugin runs the same transforms as scaffold mode but writes output into the existing site's docs tree.
Let \{site\} be the path to the existing Docusaurus site directory (e.g., website/).
3B.1: Install dependencies and copy the plugin
First, install lib-artifact-transforms in the site's package.json:
cd {site} && npm install lib-artifact-transforms@github:joestump/lib-artifact-transforms#main
Then copy the integration plugin template from the plugin's templates/integration/sync-spec-docs/ directory to \{site\}/plugins/sync-spec-docs/:
cp -r {plugin-path}/templates/integration/sync-spec-docs {site}/plugins/sync-spec-docs
If \{site\}/plugins/sync-spec-docs/ already exists, ask the user before overwriting.
3B.2: Copy React components
Copy all component files from \{plugin-path\}/templates/docusaurus/src/components/ to \{site\}/src/components/design-docs/:
mkdir -p {site}/src/components/design-docs
cp {plugin-path}/templates/docusaurus/src/components/*.tsx {site}/src/components/design-docs/
3B.3: Add CSS styles
Read \{plugin-path\}/templates/docusaurus/src/css/custom.css and create \{site\}/src/css/design-docs.css containing ONLY the design-specific styles. Exclude the :root \{ ... \} and [data-theme='dark'] \{ ... \} CSS variable blocks at the top of the file (the ones that set --ifm-color-primary-* and --docusaurus-highlighted-code-line-bg). These are Docusaurus theme colors that would override the existing site's color scheme.
Include everything from the /* Badge Components */ comment onwards.
Then add the CSS import. Check how the site loads custom CSS:
- If the site's
docusaurus.config.tshas acustomCssoption, add'./src/css/design-docs.css'as an additional entry (it can be an array) - Otherwise, add
@import './design-docs.css';at the top of the site's existing custom CSS file
3B.4: Register MDX components
Check if \{site\}/src/theme/MDXComponents.tsx exists:
If it does NOT exist, create it:
import React from 'react';
import MDXComponents from '@theme-original/MDXComponents';
import DateBadge from '@site/src/components/design-docs/DateBadge';
import DomainBadge from '@site/src/components/design-docs/DomainBadge';
import PriorityBadge from '@site/src/components/design-docs/PriorityBadge';
import SeverityBadge from '@site/src/components/design-docs/SeverityBadge';
import StatusBadge from '@site/src/components/design-docs/StatusBadge';
import RFCLevelBadge from '@site/src/components/design-docs/RFCLevelBadge';
import RequirementBox from '@site/src/components/design-docs/RequirementBox';
import Field from '@site/src/components/design-docs/Field';
import FieldGroup from '@site/src/components/design-docs/FieldGroup';
export default {
...MDXComponents,
DateBadge,
DomainBadge,
PriorityBadge,
SeverityBadge,
StatusBadge,
RFCLevelBadge,
RequirementBox,
Field,
FieldGroup,
};
If it DOES exist, read the existing file and merge the design-docs imports: add import lines for each component from @site/src/components/design-docs/, add component names to the default export, and preserve all existing imports and registrations.
3B.5: Register the plugin in docusaurus.config
Read \{site\}/docusaurus.config.ts (or .js) and add the sync plugin to the plugins array. Determine the correct projectRoot by computing the relative path from \{site\} to the project root.
Example -- if the site is at website/ and the project root is ..:
plugins: [
['./plugins/sync-spec-docs', {
projectRoot: '..',
docsPath: 'docs', // adjust to match the site's existing docs path
}],
],
To find the existing docs path, look for the path option in the classic preset's docs config. If not specified, Docusaurus defaults to 'docs'.
If the config already has a plugins array, append to it. If not, add a new plugins property.
3B.6: Add .gitignore entries
Check for .gitignore at the project root. Add entries for the generated output directory:
# Design docs (generated by sync-spec-docs plugin)
{site}/docs/architecture/
3B.7: Run initial build and verify
cd {site} && npx docusaurus build 2>&1 | tail -20
If the build fails, diagnose and fix. Common problems:
- Missing dependencies: run
npm installin the site directory - MDXComponents merge conflict: check the merge was done correctly
- Plugin path error: verify the relative
projectRootis correct
3B.8: Update .claudeignore
Add entries to ignore the site's build artifacts:
{site}/node_modules/
{site}/build/
{site}/.docusaurus/
3B.9: Report results
Tell the user what was created:
- Plugin installed at
\{site\}/plugins/sync-spec-docs/ - Components installed at
\{site\}/src/components/design-docs/ - CSS added at
\{site\}/src/css/design-docs.css - Generated docs will appear at
\{site\}/docs/architecture/ - The plugin auto-syncs when ADRs or specs change during
npm run start
Then ask: "Integration complete! Want me to start the dev server? (cd \{site\} && npm run start)"
After completion, proceed to Step 4: Create Manifest (back in SKILL.md).
scaffold-mode.md
Creates a standalone Docusaurus site at docs-site/.
-
Check for existing docs-site: Look for
docs-site/in the project root. If it exists, ask the user before overwriting. -
Copy the plugin's Docusaurus templates using
cp -rfrom the plugin'stemplates/docusaurus/directory todocs-site/in the project root. -
Customize for the project by reading and modifying only these files:
docs-site/package.json-- update the project name from$ARGUMENTSor inferred from the repodocs-site/docusaurus.config.ts-- update title, baseUrl, and GitHub URL for this project- Optionally customize the
sdd-contentplugin options if your ADRs/specs are in non-standard locations:adrsDir(default:../docs/adrs)specsDir(default:../docs/openspec/specs)outputDir(default:../docs-generated)
-
Run
npm installin the docs-site directory. -
Update
.claudeignore: Check if.claudeignoreexists at the project root. If not, create it. Add entries to ignore:docs-site/node_modules/
docs-site/build/
docs-site/.docusaurus/If
.claudeignorealready exists, append any missing entries. -
Report and offer to start: Tell the user what was created, then ask: "Docs site created! Want me to start the dev server? (
cd docs-site && npm run start)"
After completion, proceed to Step 4: Create Manifest (back in SKILL.md).
upgrade-mode.md
Entered when .sdd-docs.json exists and the referenced siteDir is present on disk. Updates an existing docs installation to the latest plugin templates while preserving user customizations.
Read the manifest from .sdd-docs.json. Let \{mode\} be the manifest's mode field ("scaffold" or "integration"), and \{site\} be the resolved siteDir.
3C.1: Determine template source paths
Based on the manifest's mode:
- Scaffold: template root is
\{plugin-path\}/templates/docusaurus/ - Integration: template root is
\{plugin-path\}/templates/integration/sync-spec-docs/for plugin files, and\{plugin-path\}/templates/docusaurus/src/components/for shared components
3C.2: Process each managed file
For each entry in the manifest's files object where managed is true:
- Compute the current SHA-256 of the file on disk
- Compare against the manifest's stored
checksum:- Checksums match (file unmodified by user) → replace silently with the new template version
- Checksums differ (user has modified the file) → use
AskUserQuestion:- "Accept new version" → overwrite with the template version
- "Keep current" → leave as-is, update manifest checksum to current hash
- "Opt out of management" → set
managed: falsein manifest (skip in future upgrades)
- File missing from disk → re-create from the template
For entries where managed is false, skip entirely.
3C.2b: Pre-plugin migration detection (Scaffold mode only)
If scaffold mode AND \{site\}/scripts/ exists BUT \{site\}/plugins/ does NOT exist:
This is a pre-plugin installation (using the old 8-script approach). Offer the user:
- "Migrate to new plugin" → delete
\{site\}/scripts/,\{site\}/src/data/spec-mapping.json,\{site\}/src/data/spec-emojis.json(if present); install the newplugins/sdd-content/index.js; updatepackage.json(remove chokidar-cli, concurrently, build-content/watch-content scripts); updatedocusaurus.config.tsto register the plugin - "Keep current setup" → do not migrate; set all managed files to
managed: false
3C.3: Detect new template files
Check for files in the current plugin templates that are NOT listed in the manifest:
- For scaffold: scan
templates/docusaurus/plugins/sdd-content/,templates/docusaurus/src/components/,templates/docusaurus/src/css/,templates/docusaurus/src/theme/ - For integration: scan
templates/integration/sync-spec-docs/,templates/docusaurus/src/components/
For each new file: install it to the appropriate location and add to the manifest with managed: true and its SHA-256 checksum.
3C.4: Update the manifest
Write the updated .sdd-docs.json:
- Set
versionto the current plugin version from.claude-plugin/plugin.json - Set
updatedAtto the current ISO timestamp - Update all
checksumvalues to reflect the current on-disk state - Preserve
createdAtandmodefrom the original manifest
3C.5: Ensure .claudeignore exists
Check if .claudeignore includes ignore entries for \{site\}/node_modules/, \{site\}/build/, and \{site\}/.docusaurus/. If any are missing, append them.
3C.6: Run build and verify
- For scaffold: run
npm installin\{site\}ifpackage.jsonchanged, then offer to start the dev server - For integration: run a Docusaurus build to verify the plugin still works
3C.7: Report results
Tell the user:
- Files updated silently (checksum matched)
- Files with conflicts and what the user chose for each
- New files added
- Files skipped (managed: false)
- New plugin version recorded in the manifest
Example Invocations
generate the docs site from our ADRs and specs
/sdd:docs
scaffold a Docusaurus site that mirrors our design artifacts
rebuild the documentation site with the latest ADRs
set up a docs site so we can publish our architecture decisions