name: create-docs
Analyze a codebase and create a structured, verified documentation vault for Obsidian that other agents and colleagues query through an Obsidian MCP server.
The vault and the codebase are separate:
source=<path> — the codebase. Read-only: never create, edit or delete any file in it (no AGENTS.md,
no specs/, no notes). Default: current working directory.vault=<path> — the Obsidian vault, outside the codebase. Every file this skill writes goes here.
Required: terminate if missing or if it resolves inside source.All paths below (AGENTS.md, specs/…) are relative to vault. All path:line citations and sources
entries are relative to source.
This skill needs exactly one of these modes (plus source / vault):
new — create AGENTS.md and the vault structure (inventory first, then domains).review — read and follow directions in specs-reviewer.md to review and update the docs.domain <name> — deep-dive a single domain from the inventory and write/update only its notes.continue — process the next todo domains of the inventory (resume after an interruption).Terminate if the user does not provide one of these modes.
GENERATED, or written by generators in the vault's tools folder) are never hand-edited: a regeneration
would overwrite the change. Link to them instead.specs/domains/domain-inventory.md (see Domain discovery) before writing any
domain note.verified.aliases.AGENTS.md in the vault rootEntry file for agents querying the vault. If it already exists, see Process step 1. A new one contains:
create-docs review to re-verify the affected notes"specs/ notes with a brief description of eachAGENTS.md must be short and scannable — for every line ask: "if I remove this, would the agent make mistakes?" — if no, cut it.
A domain is a functional subsystem with its own data and non-obvious business rules (e.g. billing, scheduling, training compliance, inventory). Utilities, type-only modules and thin wrappers are NOT domains.
Combine these language-agnostic signals to find domains:
| Signal | Where to look |
|---|---|
| Functional folder / module / namespace names | directory tree, project files |
| Persistent entities | tables, ORM models, migrations, SQL scripts, stored procedures |
| User-facing surfaces | menus, forms/screens, routes, API groups, reports |
| Configuration | option/setting keys, feature flags, per-tenant or per-customer switches |
| Scheduled / batch work | jobs, recalculation routines, imports/exports |
| Vocabulary | recurring domain terms in identifiers, UI labels, resource/translation files |
Write specs/domains/domain-inventory.md with one row per domain:
| Domain | Paths | Entities | Surfaces | Tier | Status | Note |
todo → draft → verified (or blocked: <reason>).For each domain, in order:
rg) the domain keywords, including localized UI labels, in code, constants,
option keys, resources and SQL.path:line (repo-relative).specs/domains/<domain>.mdMain note of the domain (hub). If it grows beyond ~300 lines, split topics into
specs/domains/<domain> - <topic>.md and link them from the hub. Link existing notes (flows, schema, UI,
imports) instead of repeating their content.
<DOMAIN>-R01, <DOMAIN>-R02, …). Each rule: one plain
sentence + steps if it is a computation + source. These are contracts the code respects, not code patterns.Option key | Constant | Effect | Default | Default per tenant/customer | Location.
Record the default where the computation reads it, and also where the UI shows it, if different.Create a domain note ONLY for domains whose rules are non-obvious from reading the code.
specs/integrations/ — external system boundariesFor every integration with an external system (HTTP, DB, IPC, filesystem, third-party import/export, message queue, AI/OCR services, etc.):
integrations.md — MOC table: name, direction (IN/OUT/BIDIRECTIONAL), protocol, implementing files, linkBoundary | Mechanism | Location. Most important section: what NOT to relax and
WHERE the guard lives.Create this folder ONLY if the project has at least one integration with a trust boundary.
specs/rules/ — patterns and recipesRecurring programming patterns go as rule notes in specs/rules/ (e.g. add-option.md, error-handling.md).
Each answers "how do I add/change X?" with numbered steps and a minimal code snippet — a recipe, not a
description.
specs/ notes (only the needed ones)file-structure.md — map of main directories and filescommands.md — extended commandsconventions-backend.md, conventions-frontend.md, conventions-database.mdapi-routes.md — interface table adapted to the real interface type (HTTP, IPC, CLI, events, forms)glossary.md — domain terms (original wording) → meaning → domain note linkmodule-index.md — Module | Path | Tier | Summary | NoteEvery note this skill creates (and every hand-written note it updates, except generated notes):
Starts with YAML frontmatter (first line of the file):
---
read_when: "<one line: when an agent or colleague should read this note>"
type: domain | integration | rule | convention | index | glossary
domain: <domain-slug>
tier: 1
status: draft | verified
aliases: ["<synonyms>", "<original UI wording>"]
tags: [domain/<slug>, type/<type>]
sources: ["path/to/file.ext", "path/to/other.ext"]
verified_date: <YYYY-MM-DD or empty>
---
Has a globally unique file name for new notes (Obsidian resolves wikilinks by name): never spec.md or
index.md repeated across folders.
Links other notes in the vault's existing style: relative Markdown links [text](../path/note.md#heading)
if the vault already uses them, otherwise wikilinks [[note name#Heading]]. Both work in Obsidian.
Rules are linked by heading or block id (^domain-r01).
Uses plain Markdown tables, no embedded images for information, no content only in callouts.
Is self-contained: the first paragraph answers "what is this" without opening other notes, because MCP clients often retrieve a single note.
MOC (map of content) notes:
specs/home.md — entry point: project summary + links to every MOCspecs/domains/domain-inventory.md — doubles as the domains MOCspecs/integrations/integrations.md, specs/rules/rules.mdAfter drafting a domain note, verify it with a separate subagent that did not write it:
path:line and confirm the code does exactly what the rule states
(conditions, boundary operators < vs <=, dates, defaults, units).status: verified, verified_date (today), and update the inventory row.Base verification only on the files present in source: no version-control commands.
Never mark a note verified without running this pass.
conventions-*.md → HOW to write code (style, naming, patterns)rules/*.md → HOW to add/change a feature (recipe with steps + snippet)domains/<domain>.md → WHAT the code guarantees (business rules, data model, configuration, states)integrations/*.md → WHERE the trust boundaries aremodule-index.md / domain-inventory.md → WHICH modules/domains exist and how critical they are