원클릭으로
docs-ssot
Set up docs-ssot SSOT documentation structure — migrate existing docs, build, and validate
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Set up docs-ssot SSOT documentation structure — migrate existing docs, build, and validate
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Documentation update workflow. Use when modifying files in docs/ directory or any markdown files (*.md).
Maps GitHub labels to Skills and Context documents. Use when creating issues (github-issue-creation) or working on issues (fix-issue command).
How to run watch, keygen, and sign wallet CLI commands. Use when executing wallet commands or testing wallet functionality.
Git branch management, commit conventions, and PR creation workflow. Use for all tasks that require code changes, regardless of language or scope.
Solidity smart contract development workflow. Use when modifying smart contracts in apps/eth-contracts/contracts/.
TypeScript/JavaScript development workflow for apps/ directory. Use when modifying TypeScript code in xrpl-grpc-server or JavaScript in eth-contracts.
| name | docs-ssot |
| description | Set up docs-ssot SSOT documentation structure — migrate existing docs, build, and validate |
| allowed-tools | ["Read","Write","Edit","Bash(docs-ssot *)","Bash(make docs*)","Bash(git diff *)"] |
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.
docs-ssot in a new or existing repository (follow the main Workflow)SETUP.md) to an existing SSOT structure (follow Adding a new output file)docs-ssot build)| 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) |
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 check
Install 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@latest
Before running migration, check whether this repository already has a docs-ssot structure:
ls docsgen.yaml 2>/dev/null
ls template/sections/ 2>/dev/null
If 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.
List Markdown files in the repository root:
ls *.md
Common 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.
First, preview without writing files:
docs-ssot migrate --dry-run README.md CLAUDE.md
Review 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.md
This will:
template/sections/<category>/template/pages/ with @include directivesdocsgen.yaml with build targetsdocsgen.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.md
Add or remove targets to control which files are generated.
docs-ssot index
Inspect:
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 filesRun 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 check
Also 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.
All section files under template/sections/ must start at heading level 2 (##).
## My Section Title ← ✅ correct
# My Section Title ← ❌ wrong
Why: 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 -->
First validate (dry-run — checks includes without writing files):
docs-ssot validate
If validation passes, build:
docs-ssot build
# or, if a Makefile target exists:
make docs
Verify output is correct:
git diff README.md CLAUDE.md
Never edit generated outputs (README.md, CLAUDE.md, or any docsgen.yaml output) directly — they are overwritten on every build.
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.
To add a new generated file (e.g., SETUP.md) to an existing SSOT structure:
template/pages/SETUP.tpl.md, including existing sections where applicable.docsgen.yaml:
- input: template/pages/SETUP.tpl.md
output: SETUP.md
docs-ssot validate && docs-ssot build
git diff SETUP.md
If the repository has a VitePress site, detect it by checking for docs/.vitepress/:
ls docs/.vitepress/ 2>/dev/null
If 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.
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 0
Make it executable:
chmod +x .claude/hooks/prevent-generated-edit.sh
Register 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" }
]
}
]
}
}
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
fi
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 section
Open 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 build