Adopting in an Existing Project
How to retrofit docs-kit onto a repository that already has (some) design docs. For a fresh repository, Project setup is faster.
The principle — do not promote everything to current
The biggest failure mode when adopting existing docs is flipping them all to current at once.
current is a claim: “reconciled with the implementation.” Marking un-reconciled documents current means docs-kit is only guaranteeing the shape, while the AI keeps trusting stale content as spec. That is worse than before you installed it.
This is why docs-kit adopt always brings documents in as status: draft. Draft means “reference material; trust the code,” so the state right after adoption honestly says: nothing is guaranteed yet.
Leaving things at draft does no harm. Promoting one valuable document at a time settles faster than rushing everything.
The path
Step 0 — take inventory
Start by listing what exists.
find . -name '*.md' -not -path './node_modules/*' -not -path './.git/*'
Sort the results into three piles.
| Pile | Criterion | Destination |
|---|---|---|
| Adopt | Describes implementation specs, structure, or past decisions | One of the four layers under docs/ |
| Leave alone | README, contribution guide, release notes, end-user documentation | Stays put. Outside docs-kit’s remit |
| Delete | Entirely outdated, describes a feature that no longer exists, abandoned draft | Delete now. Easier than moving it and deleting later |
Make the “delete” calls at this stage. Trying to tidy up after adoption means they get buried in a pile of drafts and never touched.
For which layer, follow the decision flow in Workflow. Roughly:
| Content | Layer |
|---|---|
| ”Why we chose this approach,” “what we considered and rejected” | adr/ |
| ”How it is supposed to behave now” | spec/ |
| ”Overall structure and dependency direction” | arch/ |
| A work plan for what comes next | plan/ (or move it to an issue) |
Step 1 — build the scaffolding with docs-kit init
docs-kit init
Existing files are never overwritten, so it is safe even with a docs/ already present.
created: docs.config.yaml
skipped: docs/adr/
created: docs/spec/
created: docs/arch/
created: docs/plan/
created: docs/INDEX.md
updated: CLAUDE.md
created: .github/workflows/docs-kit.yml
created: .claude/commands/docs-verify.md
created: .claude/commands/docs-catchup.md
If CLAUDE.md already exists, the <!-- docs-kit:begin v1 --> block is simply appended. Nothing else in the file is touched.
Then align docs.config.yaml with reality.
schemaVersion: 1
root: docs # document root. change it if docs live elsewhere
codeRoots: [src, app] # top-level code directories
ignore: # files whose changes should not stale a doc
- "**/*.test.ts"
- "**/__snapshots__/**"
- "**/fixtures/**"
Do not forget tests in ignore. Existing projects have a lot of them, and an empty ignore means everything is stale from day one.
If your docs are not in docs/
Change root — documentation/, design/, whatever.
root: documentation
What does not change is that the four layers adr/ spec/ arch/ plan/ must exist beneath it. Layer names are not configurable.
Step 2 — sort documents into the four layers
docs-kit adopt only looks at *.md directly inside <root>/<layer>/. Subdirectories are not scanned, so files have to be moved first.
Match the filename rules
| Layer | Filename | id |
|---|---|---|
adr/ | NNNN-<slug>.md | ADR-NNNN |
spec/ | <slug>.md | SPEC-<slug> |
arch/ | <slug>.md | ARCH-<slug> |
plan/ | <slug>.md | PLAN-<slug> |
Slugs match [a-z0-9]+(-[a-z0-9]+)* — lowercase alphanumerics and hyphens only. Spaces, uppercase, underscores, and non-ASCII filenames are all out.
git mv docs/design/EditingModel.md docs/spec/editing-model.md
git mv docs/decisions/adr-3-undo.md docs/adr/0003-undo-stack.md
Zero-pad ADR numbers to four digits (0003-undo.md, not 3-undo.md). Gaps in existing numbering are fine; only duplicates need resolving.
Rename with
git mv. Keeping the history connected leaves room for later freshness checks to treat it as a pure rename.
Put assets in a subdirectory
Keep images and the like out of the layer directories. Subdirectories are not scanned, so they can sit there untouched.
docs/
├── spec/
│ └── editing-model.md
└── assets/ ← not scanned
└── editing-model.png
Step 3 — add front matter with docs-kit adopt
docs-kit adopt
adopted: docs/adr/0003-undo-stack.md (id: ADR-0003, status: draft)
adopted: docs/spec/editing-model.md (id: SPEC-editing-model, status: draft)
adopted: docs/arch/overview.md (id: ARCH-overview, status: draft)
skipped: docs/spec/Editing Model.md (the filename does not match the naming rules; rename it or recreate it with docs-kit new)
adopt: 3 adopted, 1 skipped
(The skipped line means “filename does not match the naming rules — rename it or recreate it with docs-kit new.” The last line reads “3 stubs added, 1 skipped.”)
A stub is inserted at the top of each file.
---
id: SPEC-editing-model
title: Editing model
status: draft
---
idis derived from the filenametitlecomes from the first#heading in the body, or the filename if there is nonestatusis alwaysdraft
What adopt does not touch
| Target | Behaviour |
|---|---|
| Files that already have front matter | Skipped (if malformed, that is lint’s job) |
| Files whose name breaks the rules | Reported, not touched. It never renames on its own |
| Files whose id is already taken | Reported, not touched |
| Subdirectories of layer directories | Not scanned |
| The body | Never modified. Only a stub is prepended |
It is idempotent, so rename-and-rerun is a fine loop. Fix a skipped file, run adopt, repeat.
Step 4 — get lint green
docs-kit lint
docs/adr/0007-caching.md:E004 id "ADR-0007" and filename "0007-caching.md" do not correspond (expected ADR-0007)
docs/spec/api.md:E011 referenced id "ADR-0099" does not exist
docs/spec/legacy.md:W003 scope "vendor/**" points outside codeRoots [src] (warning)
Errors (E) must be cleared. Warnings (W) exit 0, so they can wait.
W002 (a scope that matches nothing) does not show up here: adopt leaves every document draft, and drafts are exempt. It starts applying as documents are promoted with verify.
Common right after adoption:
| Code | Cause | Fix |
|---|---|---|
| E001 | Broken front matter (hand-written front matter predating adopt, etc.) | Make it valid YAML |
| E004 | id and filename do not correspond | Align one to the other |
| E005 | Duplicate id | Change the slug and rename |
| E007 | Unknown top-level field | Prefix it with x- to keep it (owner: → x-owner:) |
| E011 | depends_on references a nonexistent id | Fix the typo or drop the reference |
E007 is the common one for existing docs. If you were writing author: or updated:, renaming them to x-author: / x-updated: preserves them verbatim (the tool holds them without interpreting).
docs-kit index && git add -A && git commit -m "docs: bring existing design docs under docs-kit (draft)"
Commit here. At this point every document is draft, so stale reports all skipped and CI passes.
Step 5 — promote to current, one at a time
This is the real work. Do not try to do all of it — go highest-value first, one document at a time.
Priority
- Specs for modules the AI touches often — the largest payoff
arch/overview.md— you want the big picture trustworthy early- ADRs that are still in force — no scope, so it is just a manual flip to
current(cheap) - Everything else
Per document
Concretely, add a scope to the front matter:
---
id: SPEC-editing-model
title: Editing model
status: draft
scope:
- src/core/editing/**
---
Then, once the body has been read against the code and corrected:
docs-kit verify SPEC-editing-model
SPEC-editing-model: verified_at → 8f3a1c2 (promoted to current)
Choosing not to promote
Not every document needs to become current.
- Too outdated to be worth fixing → delete it. git history keeps it
- A successor exists → set
status: supersededandsuperseded_by: SPEC-xxx - Still useful as background → leave it
draft. The AI will treat it as reference
Leaving it at draft is a legitimate choice. “Nothing is guaranteed here” is stated accurately, which beats a fabricated current by a wide margin.
Delegating to the AI
With Claude Code connected, /docs-catchup can grind through much of this: per document, reconcile against the implementation, verify if it matches, fix then verify if it drifted. That said, writing the scope and making the final call are better left to a human.
Step 6 — tighten CI in stages
Making all three commands mandatory on day one turns CI red with stale and everyone stops looking. Go in stages.
Stage 1 — lint only
- run: docs-kit lint
- run: docs-kit index --check
Stops structural breakage. Everything is draft, so stale always passes anyway.
Stage 2 — run stale as a warning
- run: docs-kit stale || true
Look at the result without failing on it. As the number of current documents grows, the verdict starts carrying meaning.
Stage 3 — make stale mandatory
- run: docs-kit lint
- run: docs-kit stale
- run: docs-kit index --check
Move here once the current documents are broadly in place. From then on, “change the implementation, verify the doc” is enforced.
At every stage, fetch-depth: 0 is required.
- uses: actions/checkout@v4
with:
fetch-depth: 0
Step 7 — connect Claude Code
claude mcp add docs-kit -- docs-kit mcp
In an existing project the effect is immediately visible.
docs-kit which src/core/editing/model.ts
primary:
SPEC-editing-model current 8f3a1c2 docs/spec/editing-model.md
related:
ADR-0003 current - docs/adr/0003-undo-stack.md
Even with 50 documents in docs/, the AI reads only the handful that came back.
Case by case
Monorepos
One config, at the repository root. Per-subdirectory docs.config.yaml files are not supported.
root: docs # one docs/ for the whole repository
codeRoots: [packages, apps]
Namespace per-package documents through the slug.
docs/spec/
├── web-editing-model.md → SPEC-web-editing-model
├── api-auth.md → SPEC-api-auth
└── worker-queue.md → SPEC-worker-queue
scope then points at the package path.
scope:
- packages/web/src/editing/**
Too many documents to handle
Adopting everything as draft and stopping there is fine. Even in that state:
- Reverse lookup with
whichworks (drafts are returned too) - The AI correctly treats drafts as reference material
- CI runs on
lintandindex --checkalone
Nothing gets worse than your current situation. Promote modules to current as you come to need them.
Documents that carry progress state
If checklists like “Phase 1: done ✅” are mixed in, move them out to the issue tracker. Progress state mixed into a design doc means every read requires distinguishing spec from status, and both humans and AI get it wrong.
Work plans themselves can live in plan/, but plan is disposable and expected to be deleted at merge. It is not for durable task tracking.
Existing front matter with a different schema
If static-site front matter (layout:, date:, tags:, …) is already present, adopt skips the file — it counts as already having front matter.
Add the required fields by hand and prefix anything docs-kit does not know with x-.
---
id: SPEC-editing-model # added
title: Editing model # existing title can be reused
status: draft # added
x-layout: doc # layout: → x-layout:
x-date: 2025-04-01 # date: → x-date:
x-tags: [editor] # tags: → x-tags:
---
x- fields are preserved verbatim and never interpreted. verify rewrites line by line, so they survive intact.
Docs in a GitHub Wiki or a documentation site
docs-kit can only handle Markdown inside the same repository. The freshness check depends on git history, so documents in another repository or an external service cannot be covered.
To adopt them, move the design-doc content into the repository. End-user documentation is out of scope anyway and can stay where it is.
Confirming adoption
docs-kit lint && docs-kit stale && docs-kit index --check
All three green, and at least one current document. With zero current documents you have only fixed the shape; no freshness guarantee is doing any work yet.
docs-kit stale
ADR-0003 skipped (no scope)
ARCH-overview ok (verified at 8f3a1c2)
SPEC-editing-model ok (verified at 8f3a1c2)
SPEC-legacy-api skipped (draft)
ok 2 / stale 0 / broken 0 / skipped 2
That shape means adoption is done. From here, run the loop in Workflow and whittle down the skipped count over time.
Next
- Documentation workflow — the full picture of daily operation
- Concept and design principles — why adoption starts at draft