| name | ai-diataxis-scaffold |
| description | Stand up the four Diátaxis mode directories, each seeded with an index page, in a project that has no documentation tree. Invoke ONLY via the /ai-diataxis-scaffold slash command. Do not activate from intent, keywords, or near-synonyms — slash incantation is required. |
| effort | high |
Agent: Scaffold a Diátaxis Documentation Tree
You stand up the four Diátaxis mode directories —
tutorial/, how-to/, reference/, explanation/ — in a project that does not
have them, and you seed every directory you create with a real index page. You
create only what is missing, you never overwrite, and you never leave a directory
empty.
Classifying individual pages is /ai-diataxis's job, not yours. You place four
index pages whose mode is known by construction; you do not run the compass over
anything.
Why this skill exists, and where it deviates
Diátaxis is explicit that creating the four empty mode directories up front is
the practice to avoid: getting started "certainly does not mean that you should
create empty structures for tutorials/howto guides/reference/explanation" —
structures "with nothing in them." Then: "Don't do that. It's horrible."
(https://diataxis.fr/how-to-use-diataxis/.)
Two things about that rule, both stated in full at
.claude/skills/ai-skills-reference/diataxis-classification.md §6. Read it
before you run.
- Its scope is projects that already have documentation. The rule sits inside
an improvement cycle whose first step is "Choose something - any piece of the
documentation," which presupposes documentation to choose from. The source is
silent on a project with none.
- Its spirit is broader than its letter, and this skill deviates from that
spirit. The source's claim is that structure should form "from the inside."
A scaffold imposes it from outside. Do not tell the user Diátaxis endorses what
you are doing. It does not; the argument for doing it anyway is that a person
cannot adopt a structure they have never seen, and that every directory here
ships with a page in it.
The same disclaimer covers the second axis. When step 2's audience question is
answered with anything but its default, this skill builds a tree partitioned by
reader as well as by mode. The one upstream page that raises that shape —
https://web.archive.org/web/20260802004758/https://diataxis.fr/complex-hierarchies/
(snapshot captured 2026-08-02, retrieved 2026-08-24; the live URL returns 404 as of
2026-08-24, so the guidance is published-but-withdrawn) — presents it only as a
question it declines to answer: "Which better? There seems to be a lot of
repetition in either cases." So claim no source support for the two-axis shape
either. State that Diátaxis does not endorse it, name that page as raising and
declining it, and say the argument for offering it is this project's own.
So: never create a directory you do not also seed. That is not a stylistic
preference. Git does not track empty directories, so four empty directories
produce zero commits and there is nothing to hand over; and an autogenerated
sidebar over an empty directory fails a Docusaurus build.
User Input
$ARGUMENTS
Treat any argument as a hint about where the docs root should be — it feeds step 2
as the user's stated preference. An empty argument is the normal case.
Step 1: Gate on project context
Read .context/README.md from the project root.
- Absent → print exactly: "No project context found at
.context/README.md.
Run /ai-init first to set up your project context." Then stop. Write
nothing. /ai-init is the sole writer of that file and every other skill in
this collection gates the same way.
- Present → parse its YAML frontmatter and carry
docs_path and
output_path into step 2. Also read Voice and Principles: the seed pages are
prose this project ships, so they follow the project's register.
Step 2: Resolve the published docs root
Resolve in this order and report which step resolved it:
docs_path in .context/README.md frontmatter. Present and a string →
use it and ask nothing. Present but not a string → WARN: "docs_path in
.context/README.md is not a string; asking where the docs root should live."
Fall through. Do not block.
- A static-site config, via
.claude/skills/ai-skills-reference/framework-detection.md — match a
generator config to its docs location.
- Conventional directories, in order:
docs/, documentation/, website/.
AskUserQuestion. Offer the detected or conventional path marked
(recommended), plus the other plausible candidates.
Expect step 4 to fire. This is the point most likely to be got wrong:
framework-detection.md matches a generator config to an existing docs location,
so it detects a site that is already there. A greenfield project — the case this
skill exists for — has no config to match and no docs directory, so steps 2 and 3
return nothing and the interview is the normal path, not the fallback. Write
the question accordingly: say that the answer becomes the root of the whole tree,
and name what you will create under it.
On confirmation, write docs_path into .context/README.md frontmatter with the
Edit tool and report that the interview will not repeat. If the user declines, use
the value for this run only.
Step 2b: Ask the audience question — once, before anything is created
Ask this in step 2 and not later. Step 5 creates directories, and the above-mode
shape cannot be adopted after that: once docs_path/how-to/ holds six pages, moving
to user-docs/how-to/ relocates every page and breaks every cross-mode index link.
The one moment the choice costs nothing is before the tree exists.
Use AskUserQuestion with three options:
- No audiences (recommended) — the four mode directories go directly under
docs_path. One readership, which is the ordinary case.
- A user tree and a developer tree — two audience roots, each holding its own
four mode directories.
- Something else — the builder names their audiences.
Write the question to the same standard step 2 already sets for the docs root: say
that the answer determines where the four mode directories go, name what will be
created under each option, and say that changing it later moves every page.
The options are examples of a shape, not a vocabulary. user and developer are
offered because they are the common pair; a project that picks "something else" names
its own labels with no suggestion from this skill. An audience has a label — the
project's own word — and an object, the thing that audience's readers act on
(the released command-line tool, this repository's source tree). The object is
never a person, and it is what the landing page seed needs. The rule in full is
reference §12 in
.claude/skills/ai-skills-reference/diataxis-classification.md.
Do not write the answer into .context/README.md. /ai-init is the sole writer
of that file's body, and ## Audiences is never interviewed for there. Instead, when
the answer is anything but the default, print the ## Audiences section for the
user to paste, one bullet per audience carrying its label and the object its readers
act on.
Step 3: Detect the static-site generator
Run the detection table in framework-detection.md again, this time for the
generator rather than the path.
- Found → report which one and where its config is.
- None found → report that no static-site generator was detected and that the
tree will not render as a site until one is added.
Generate no configuration either way. Standing up a generator is a different
job, and it is most of what got the retired ai-code-docs-setup skill deleted.
Create the tree regardless: the directories and pages are useful as files, and a
generator added later picks them up.
Step 4: Check every artifact independently, and report before writing
Check the existence of each directory and each page separately. Do not use a
single global "does a docs site exist?" gate — that is what the retired setup
skill did, and it is wrong in both directions here: a run interrupted after
creating directories but before writing pages looks complete, and a project with a
finished site in some other shape gets refused when it needs a report.
Report a table of what you found, before creating anything:
docs_path: docs/docs (from .context/README.md)
generator: Docusaurus (docs/docusaurus.config.ts)
tutorial/ exists, 2 pages — leaving untouched
how-to/ exists, 6 pages — leaving untouched
reference/ missing — will create + seed index.md
explanation/ missing — will create + seed index.md
_templates/ missing — will copy 5 templates
../CLAUDE.md exists — will print a snippet instead
Creating 2 directories, 2 index pages, 5 template files. Writing 0 existing files.
When step 2b returned audiences, report the whole shape in the same form, and
report it before writing anything — the count is the number most worth seeing
early, because it is more than double the default:
docs_path: docs/docs (from .context/README.md)
generator: Docusaurus (docs/docusaurus.config.ts)
audiences: user, developer (from the step 2b answer)
user-docs/ missing — will create + seed index.md
user-docs/tutorial/ missing — will create + seed index.md
user-docs/how-to/ missing — will create + seed index.md
user-docs/reference/ missing — will create + seed index.md
user-docs/explanation/ missing — will create + seed index.md
developer-docs/ missing — will create + seed index.md
developer-docs/tutorial/ missing — will create + seed index.md
developer-docs/how-to/ missing — will create + seed index.md
developer-docs/reference/ missing — will create + seed index.md
developer-docs/explanation/ missing — will create + seed index.md
_templates/ missing — will copy 5 templates
../CLAUDE.md missing — will write
Creating 10 directories, 10 index pages, 5 template files. Writing 0 existing files.
Against 4 directories and 4 pages for the no-audiences answer.
Never overwrite. Where a target file already exists, warn and ask whether to
overwrite or skip; default to skip. An existing page must be byte-identical after
the run.
When all four directories already exist, report that the tree is in place,
write nothing, and point the user at /ai-diataxis for classifying individual
pages. Do not seed a fifth thing to justify the run.
When a populated docs tree exists in some other shape — pages, but not these
four directories — report what is there, create the missing mode directories, and
say plainly that moving existing pages into modes is not this skill's job:
/ai-diataxis SURVEY assesses a tree page by page.
Step 5: Create the missing directories and seed each one
Branch on step 2b's answer. The two branches share every non-negotiable below.
5a. The default answer — no audiences
Create the four mode directories directly under docs_path, seed each one, and
change nothing else. This path must be byte-identical to a run of this skill
before the audience question existed: four directories, four index pages, and no
output line naming an audience, a readership, a shape, or a second axis. Not even
to say the question was asked and declined.
That is the point rather than a nicety. A builder who answered "no audiences" has one
readership, and a scaffold that then tells them about a distinction selecting nothing
has reintroduced exactly the noise the axis was designed to avoid.
5b. Any other answer — one root per audience
Create one audience root per declared audience, each holding the four seeded mode
directories, plus one landing page per root. For two audiences that is ten
directories and ten pages, reported in step 4's form before any of it is written.
Then print the registration lines and stop there:
-
Docusaurus — one sidebar entry and one navbar item per root:
// sidebars.ts — one per audience root
userDocsSidebar: [{type: 'autogenerated', dirName: 'user-docs'}],
developerDocsSidebar: [{type: 'autogenerated', dirName: 'developer-docs'}],
// docusaurus.config.ts — navbar.items, one per audience root
{ type: 'docSidebar', sidebarId: 'userDocsSidebar', position: 'left', label: 'User docs' },
{ type: 'docSidebar', sidebarId: 'developerDocsSidebar', position: 'left', label: 'Developer docs' },
-
Another generator, or none detected — name what it registers a top-level tree
with, or say that no generator was detected and the tree will not render at all.
Edit no configuration file, and say the tree is unreachable from the site's
navigation until those lines are added. This is the failure most easily produced by
being helpful: pages that exist, build, and no reader can reach. Reference §12 states
the rule — a skill never creates an audience root it cannot register, so a skill that
creates one hands over the registration.
Repeat the no-endorsement disclaimer here, in one line, naming the withdrawn
upstream page as raising the two-axis shape and declining to recommend it.
Seeding, both branches
The four mode seed shapes are in references/seeds.md — read it and use them; they
carry the frontmatter keys, the reader-facing paragraph, the fenced worked example,
and the cross-mode links. The audience landing page is the fifth shape in that
same file, used only in 5b.
Non-negotiables, all checked in step 8:
.md, never .mdx. Under format: 'detect' an .mdx file goes through
the MDX compiler, where {anything} is a JSX expression.
- No
{ in any emitted page. Write the worked examples filled in.
- Only link to modes that exist or that this run is creating. A seed's
cross-mode links must not point at a directory you skipped.
- Apply the project's Voice and Principles from step 1. These pages are prose
the project ships.
Step 6: Copy the page templates
Copy all five files from this skill's references/templates/ to
docs_path/_templates/, headers intact. Those headers carry the only MIT-0
attribution and upstream provenance there is — there is no LICENSE or NOTICE file
to fall back on, so stripping a header destroys the attribution.
Report where they landed and that they are reference material, not pages to
publish. The templates keep their {placeholders}; they are not emitted pages, so
the no-{ rule does not apply to them.
Check for a Docusaurus exclude override. Docusaurus's default exclude
skips **/_*/**, but a project that sets its own exclude array replaces that
default rather than adding to it — at which point _templates/ publishes. If the
detected config sets exclude, tell the user to add '**/_*/**' to it, and quote
the line. Do not edit their config. (This repository is its own example:
docs/docusaurus.config.ts overrides exclude and has lost that guard.)
Step 7: Write the docs-tree CLAUDE.md, print the AGENTS.md snippet
Compute the placement:
parent := dirname(docs_path)
if parent != project_root and no CLAUDE.md at parent:
write parent/CLAUDE.md # docs/docs → docs/CLAUDE.md
else:
print the content as a snippet # never clobber an existing CLAUDE.md
Never write docs_path/CLAUDE.md. Under MkDocs, every .md below the docs
directory becomes a page, so the agent-context file would publish as
documentation.
The content is in references/seeds.md, and which variant you use follows step
2b:
- Default answer (no audiences) → use the docs-tree
CLAUDE.md seed exactly as
written, byte for byte. It gains nothing about audiences, shapes, or thresholds.
- Any other answer → use the audience variant in the same file. It adds the
audience paths filled in from the interview answer, plus the two lines a two-axis
tree needs that a flat one does not: a page's home is its mode, and a mode
index gets grouped only once its list passes seven items.
Both lines are conditional for the same reason 5a is byte-identical: the default path
must not acquire prose about an axis the builder declined.
Then print the AGENTS.md snippet rather than writing it — no skill in this
collection writes that file; /ai-init prints one too.
Step 8: Self-audit
Check each item and report the result. Do not delegate any of this to the site
build: onBrokenMarkdownLinks defaults to warn, so a page carrying an unfilled
{Concept 1} builds cleanly and ships broken.
- No
{ in any page you emitted. Check every one.
- Every relative link resolves to a file or directory that exists.
- No heading text is a placeholder — no
{Title}, no "TODO", no "TBD".
- Every directory you created holds at least one page. An empty one is the
failure this skill's whole justification rests on not happening.
- Every file you did not intend to touch is unchanged.
When step 2b returned audiences, also check:
- Every audience root holds at least one landing page and four seeded mode
directories. A root with modes and no landing page has no entry point; a root with
a landing page and no modes is an empty structure by another name.
- Every cross-mode link inside a root resolves within that root.
../how-to/ from
user-docs/tutorial/index.md must reach user-docs/how-to/, never
docs_path/how-to/. A link that escapes its root sends a reader to the other
audience's tree, and the site build will not catch it because the target exists.
- No landing page contains a
{. The registration lines you printed do contain
braces; they are printed output, not an emitted page, so the rule does not reach
them — but it does reach every landing page, and that is the one seed shape written
from the interview answer rather than copied.
- No configuration file was modified.
sidebars.ts, docusaurus.config.ts, and
their equivalents must be byte-identical after the run.
Fix anything that fails before reporting completion.
Report
Close by naming what was created and what to do next:
- What was created, what was skipped because it already existed, and where.
- Whether a generator was detected, and if not, that the tree will not render
until one is added.
- The
/ai-diataxis invocation forms, so the next step is discoverable:
- "Create a page:
/ai-diataxis \"<what you need to document>\""
- "Assess a page:
/ai-diataxis <path>"
- "Survey the whole tree:
/ai-diataxis"
What This Skill Does NOT Cover
- No page content beyond the index seeds. It writes four index pages. Every
other page comes from
/ai-diataxis CREATE, one classified page at a time.
- No static-site generator. It detects one and reports its absence. It never
writes a
docusaurus.config.ts, an mkdocs.yml, or a package.json.
- No functional-quality judgement. Diátaxis "cannot address functional quality
in documentation" (https://diataxis.fr/quality/). This skill creates
structure; it does not assess whether any page is accurate, complete, or useful.
- No reorganisation of an existing tree. It never moves, renames, merges, or
rewrites a page that is already there. A populated tree in another shape gets a
report and a pointer at
/ai-diataxis SURVEY.
- No site-root router page.
docs_path/index.md is the page most likely to
already exist in a target project. The four mode index pages cross-link to each
other instead.
- No
AGENTS.md. Printed as a snippet, never written.
- No classification. The four index pages' modes are known by construction.
Nothing here runs the compass.