docs-ssot
Skill128 starsChanged 6 months agoMITView on GitHub
Set up docs-ssot SSOT documentation structure — migrate existing docs, build, and validate
- Installs packages
We split this skill into the rules it gives an agent
16 rules. About 0 are common, 8 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 42
Verify required tools are installed:
- Distinctive: line 64
Before running migration, check whether this repository already has a docs-ssot structure:
- Very specific: line 71
If both exist, the repository is already (partially or fully) migrated.
- Very specific: line 73
If docsgen.yaml does not exist, or template/sections/ is empty or missing, proceed with Steps 3–6.
- Very specific: line 107
Create template files under template/pages/ with @include directives
- Very specific: line 108
Create or update docsgen.yaml with build targets
- Distinctive: line 109
Verify round-trip: build and compare output against originals
- Distinctive: line 124
Add or remove targets to control which files are generated.
- Very specific: line 155
Rule: If content for a new section already exists in a section used by another template (e.g., installation-guide.md already covers …
- Distinctive: line 163
Only create a new section file when the content is genuinely new and not covered anywhere else.
- Distinctive: line 195
If validation passes, build:
- Distinctive: line 203
Verify output is correct:
- Very specific: line 256
If the repository has a VitePress site, detect it by checking for docs/.vitepress/:
- Very specific: line 262
If present, convert each docs/ page from standalone content into a thin @include wrapper so template/sections/ becomes the single source of …
- Very specific: line 355
Add to lefthook.yml to fail a push when generated files are stale.
- Distinctive: line 375
Add a note so contributors know the documentation is managed by docs-ssot.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
docs-ssot: Documentation SSOT Setup
This skill migrates existing Markdown documentation into a modular Single Source of Truth (SSOT) structure managed by docs-ssot, then builds and validates the output.
When to use this skill
- Setting up
docs-ssotin a new or existing repository (follow the main Workflow) - Adding a new generated output file (e.g.,
SETUP.md) to an existing SSOT structure (follow Adding a new output file) - Regenerating documentation after editing source templates (run
docs-ssot build)
Quick Command Reference
| Command | Purpose |
docs-ssot migrate <files> | Decompose existing docs into SSOT section structure |
docs-ssot migrate --dry-run <files> | Preview migration without writing files |
docs-ssot validate | Dry-run: check all includes resolve (no files written) |
docs-ssot build | Generate all output files from templates |
docs-ssot check | Detect near-duplicate sections (SSOT violations) |
docs-ssot index | Show include relationships and orphan detection |
docs-ssot include <template> | Expand and print a template to stdout (debugging) |
Workflow
Step 1 — Check prerequisites
Verify required tools are installed:
docs-ssot version # docs-ssot itself
jq --version # required by the generated-file protection hook
yq --version # required by the generated-file protection hook and lefthook checkInstall docs-ssot if missing:
# Homebrew (macOS/Linux)
brew tap hiromaily/tap && brew install docs-ssot
# or Go install
go install github.com/hiromaily/docs-ssot/cmd/docs-ssot@latestStep 2 — Check if already migrated
Before running migration, check whether this repository already has a docs-ssot structure:
ls docsgen.yaml 2>/dev/null
ls template/sections/ 2>/dev/nullIf both exist, the repository is already (partially or fully) migrated. Do not run docs-ssot migrate on generated output files. Instead, skip to Step 5 to review the structure, or Step 8 to validate the current state.
If docsgen.yaml does not exist, or template/sections/ is empty or missing, proceed with Steps 3–6.
Step 3 — Identify existing documentation files
List Markdown files in the repository root:
ls *.mdCommon candidates: README.md, CLAUDE.md, AGENTS.md, SETUP.md, ARCHITECTURE.md
Do not migrate files that are already outputs in docsgen.yaml — migrating a build artifact instead of a source file will produce incorrect results.
Step 4 — Preview and run the migration
First, preview without writing files:
docs-ssot migrate --dry-run README.md CLAUDE.mdReview the output to understand how sections will be categorised and which are detected as duplicates. Then run the actual migration:
docs-ssot migrate README.md CLAUDE.md AGENTS.mdThis will:
- Split each file by H2 headings into section files under
template/sections/<category>/ - Create template files under
template/pages/with@includedirectives - Create or update
docsgen.yamlwith build targets - Verify round-trip: build and compare output against originals
docsgen.yaml reference (the file created/updated by migration):
index:
output: template/INDEX.md # optional: generates include-relationship index
targets:
- input: template/pages/README.tpl.md
output: README.md
- input: template/pages/CLAUDE.tpl.md
output: CLAUDE.mdAdd or remove targets to control which files are generated.
Step 5 — Review generated structure
docs-ssot indexInspect:
template/sections/— modular section files (edit these, not the generated outputs)template/pages/*.tpl.md— template files defining document structuredocsgen.yaml— build targets mapping templates to output files
Step 6 — Audit for duplicate content
Run this before creating any new section file. The docs-ssot migrate command deduplicates across the files it processes, but any additional content you create manually must be checked:
docs-ssot checkAlso inspect existing sections:
ls template/sections/Rule: If content for a new section already exists in a section used by another template (e.g., installation-guide.md already covers prerequisites and setup), do not create a duplicate. Instead, have the new template include the existing section:
<!-- template/pages/SETUP.tpl.md -->
<!-- @include: ../sections/development/installation-guide.md -->
<!-- @include: ../sections/development/setup-release.md -->Only create a new section file when the content is genuinely new and not covered anywhere else.
Step 7 — Heading level convention
All section files under template/sections/ must start at heading level 2 (##).
## My Section Title ← ✅ correct
# My Section Title ← ❌ wrongWhy: Section files are embedded into larger documents where # is reserved for the document title. Starting at ## means most includes need no level parameter.
Exception — when a section file is used as a standalone output (e.g., .claude/rules/*.md), use level=-1 in the template to shift ## → #:
<!-- @include: ../sections/ai/rules/docs.md level=-1 -->Step 8 — Validate and build
First validate (dry-run — checks includes without writing files):
docs-ssot validateIf validation passes, build:
docs-ssot build
# or, if a Makefile target exists:
make docsVerify output is correct:
git diff README.md CLAUDE.mdNever edit generated outputs (README.md, CLAUDE.md, or any docsgen.yaml output) directly — they are overwritten on every build.
Include directive syntax
Templates use include directives to compose sections:
<!-- @include: ../sections/project/overview.md -->
<!-- @include: ../sections/development/ -->
<!-- @include: ../sections/**/*.md level=+1 -->| Parameter | Effect |
level=+1 | ## → ### (deepen by one) |
level=-1 | ### → ## (shallow by one) |
level=0 | no change (same as omitting) |
Paths are resolved relative to the file containing the directive. Includes are expanded recursively.
Adding a new output file
To add a new generated file (e.g., SETUP.md) to an existing SSOT structure:
- Audit existing sections (see Step 6) — do not duplicate content that already exists.
- Create the template page at
template/pages/SETUP.tpl.md, including existing sections where applicable. - Register in
docsgen.yaml:- input: template/pages/SETUP.tpl.md output: SETUP.md - Validate and build (see Step 8):
docs-ssot validate && docs-ssot build git diff SETUP.md
Optional enhancements
VitePress integration
If the repository has a VitePress site, detect it by checking for docs/.vitepress/:
ls docs/.vitepress/ 2>/dev/nullIf present, convert each docs/ page from standalone content into a thin @include wrapper so template/sections/ becomes the single source of truth for both the generated root-level files and the VitePress site.
Before (docs/guide/installation.md with standalone content):
# Installation
## Prerequisites
...full content here...After (docs/guide/installation.md as a thin wrapper):
<!-- @include: ../../template/sections/development/installation-guide.md -->The canonical content lives in template/sections/ and is referenced by any template that needs it.
Generated-file protection hook (Claude Code)
Prevent AI agents from directly editing generated files. The hook reads docsgen.yaml at runtime so the block list stays in sync automatically.
Create .claude/hooks/prevent-generated-edit.sh:
#!/bin/sh
# Blocks Edit and Write tool use on auto-generated files.
# Generated files are defined as outputs in docsgen.yaml.
# Edit the source files in template/ instead, then run `make docs`.
# Requires: jq, yq
command -v jq >/dev/null 2>&1 || { echo "jq required but not found — hook inactive" >&2; exit 0; }
command -v yq >/dev/null 2>&1 || { echo "yq required but not found — hook inactive" >&2; exit 0; }
FILE=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')
if [ -z "$FILE" ]; then
exit 0
fi
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
REL_PATH="${FILE#"${REPO_ROOT}/"}"
CONFIG="docsgen.yaml"
if [ ! -f "$CONFIG" ]; then
exit 0
fi
GENERATED=$(yq -r '.targets[].output' "$CONFIG" 2>/dev/null)
if [ -z "$GENERATED" ]; then
exit 0
fi
if echo "$GENERATED" | grep -Fqx "$REL_PATH"; then
echo "BLOCKED: '$REL_PATH' is auto-generated by docs-ssot. Edit the source in template/ instead, then run 'make docs'." >&2
exit 2
fi
exit 0Make it executable:
chmod +x .claude/hooks/prevent-generated-edit.shRegister in .claude/settings.json. If the file already exists, merge into the existing hooks.PreToolUse array rather than overwriting:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{ "type": "command", "command": ".claude/hooks/prevent-generated-edit.sh" }
]
},
{
"matcher": "Write",
"hooks": [
{ "type": "command", "command": ".claude/hooks/prevent-generated-edit.sh" }
]
}
]
}
}Pre-push docs-check (lefthook)
Add to lefthook.yml to fail a push when generated files are stale. Derive the file list from docsgen.yaml so it stays in sync automatically:
pre-push:
commands:
docs-check:
glob: "{template/**/*,docsgen.yaml}"
run: |
docs-ssot build
docs-ssot index
if ! yq -r '(.targets[].output, .index.output) | select(. != null)' docsgen.yaml | xargs -I {} git diff --quiet {}; then
echo "ERROR: Generated files are out of date. Run 'make docs' and commit the changes." >&2
exit 1
fiDocument the tooling in the README
Add a note so contributors know the documentation is managed by docs-ssot.
Find the section file for the README intro:
head -5 template/pages/README.tpl.md # the first @include is the intro sectionOpen that section file and append:
> **Documentation** is managed as a Single Source of Truth using [docs-ssot](https://github.com/hiromaily/docs-ssot).
> Files such as `README.md`, `CLAUDE.md`, and `ARCHITECTURE.md` are auto-generated —
> edit the source files under `template/` and run `make docs` to regenerate.Then rebuild:
docs-ssot buildOther versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- hiromaily/claude-forge★ 153% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository62 other files it gives its agents.
- AGENTS.mdAGENTS.md
- internal/AGENTS.mdAGENTS.md
- pkg/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- internal/CLAUDE.mdCLAUDE.md
- pkg/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/agent-files.mdcCursor rule
- .cursor/rules/apps/bun.mdcCursor rule
- .cursor/rules/apps/eth-contracts.mdcCursor rule
- .cursor/rules/apps/xrp-server.mdcCursor rule
- .cursor/rules/database/atlas-hcl.mdcCursor rule
- .cursor/rules/database/sqlc.mdcCursor rule
- .cursor/rules/documentation-language.mdcCursor rule
- .cursor/rules/general.mdcCursor rule
- .cursor/rules/github-actions.mdcCursor rule
- .cursor/rules/go/conventions.mdcCursor rule
- .cursor/rules/go/di.mdcCursor rule
- .cursor/rules/go/go-path.mdcCursor rule
- .cursor/rules/go/go-test.mdcCursor rule
- .cursor/rules/internal/application-layer.mdcCursor rule
- .cursor/rules/internal/btc-shared.mdcCursor rule
- .cursor/rules/internal/clean-architecture.mdcCursor rule
- .cursor/rules/internal/cli-structure.mdcCursor rule
- .cursor/rules/internal/domain-layer.mdcCursor rule
- .cursor/rules/internal/dto.mdcCursor rule
- .cursor/rules/internal/infrastructure-layer.mdcCursor rule
- .cursor/rules/internal/interface-adapters-layer.mdcCursor rule
- .cursor/rules/internal/internal-interface.mdcCursor rule
- .cursor/rules/internal/mockery.mdcCursor rule
- .cursor/rules/internal/repository.mdcCursor rule
- .cursor/rules/internal/usecase.mdcCursor rule
- .cursor/rules/proto.mdcCursor rule
- .cursor/rules/README.mdCursor rule
- .cursor/rules/security.mdcCursor rule
- .cursor/rules/shell-script.mdcCursor rule
- .cursor/rules/ssot.mdcCursor rule
- .cursor/rules/task-context-loading.mdcCursor rule
- .cursor/rules/typescript.mdcCursor rule
- .cursor/rules/yaml.mdcCursor rule
- llms.txtllms.txt
- bch-developmentSkill
- btc-terminologySkill
- db-migrationSkill
- devopsSkill
- docs-updateSkill
- fix-pr-reviewSkill
- github-issue-creationSkill
- git-workflowSkill
- go-developmentSkill
- knowledge-gapSkill
- label-context-mappingSkill
- makefile-updateSkill
- mockerySkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-exploreSkill
- openspec-proposeSkill
- shell-scriptsSkill
- solidity-developmentSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

