docs-cleaner
Consolidates redundant documentation while preserving all valuable content; keeps a doc set truthful after things change. Modes: (1) POST-CHANGE GOVERNANCE — when code, scripts, config, env vars, ports, paths, deployment, auth, tests, or a documented procedure changed; also "which docs are now wrong
By daymade · 885 installs
npx skills add daymade/claude-code-skills --skill docs-cleaner
Source repository · Upstream listing
Docs Cleaner
Documentation goes wrong in recurring ways, and they need different work.
It rots. Something changed — a port, a path, a procedure, a decision — and the docs
still describe the old world. The field's name for this is documentation rot or version
drift : artifacts fall out of sync one at a time until people stop trusting the set.
It sprawls. The same topic accumulates three files, each partly right, none
authoritative.
They trace to one root cause: a fact was written down in more places than it was
defined. Everything below follows from fixing that.
Core principle (governs both modes)
Critical evaluation before deletion. Never blindly delete. Analyze each section's
unique value before proposing removal. The goal is reduction without information loss.
This governs every deletion shaped action in this skill, not just consolidation: archiving
a document, dropping a derived value, and removing a cross reference are all deletions and
all owe the same analysis first. "It looked redundant" is not that analysis.
Which mode are you in?
The user said / the situation Mode
"I changed X" / a diff exists / a procedure was updated 1 — Post change governance
"which docs are now wrong", "check for stale commands/paths" 1 — Post change governance
"clean up the docs", "too many files on this", "merge these" 2 — Consolidation
A topic is spread over several files with no clear owner 2 — Consolidation
They share the Drift Test below. When both apply, run Mode 1 first: consolidating docs
that are also factually stale just produces one confidently wrong document.
A note on CLAUDE.md / AGENTS.md : both modes apply to them like any other document
— govern them after a change, consolidate them when they duplicate each other. The one job
that belongs elsewhere is restructuring a single oversized one — pushing low frequency
detail down into references while keeping the top level lean. That is what
daymade claude code's claude md progressive disclosurer skill is built for; prefer it
when the problem is size and layering rather than truth or duplication. If it is not
available, Mode 2 still handles the file — you just do the value analysis by hand.
The Drift Test (the core of both modes)
Before writing any value into a document — and when deciding whether an existing one
earns its place — ask these questions in order, and stop at the first hit :
1. Can this be computed from details already recorded here or in the authoritative
source?
→ It is a derived value . Do not write it. Compute it when someone asks.
Examples: a count ("6 sections", "N groups covered"), a total, a status summarizing rows
in a table below it, "last updated on" when the log underneath already says.
When you remove one, repair the sentence rather than leaving a hole: "the four checks
below" becomes "the checks below". Deleting the number and leaving dangling grammar is a
different defect, not a fix.
Exception — generated navigation. A table of contents restating the headings is a
derived value by this test, and hand maintained ones should indeed go. But leave it alone
when it is produced by the docs toolchain at build time, or when the platform requires the
marker to render navigation: those are computed on demand, which is what question 1 asks
for. Check for a generator before deleting one.
2. Not computable, but the same fact is authoritatively defined somewhere else?
→ It is a copy . Link to that definition. Do not restate the value.
3. Neither derivable nor copied — it independently records what was true at a
particular moment?
→ It may remain as an atomic historical observation : a dated change, original
measurement, price observation or decision. Never replace its past value with a
current value or a current config link.
Apply the ordered test to each claim, including claims inside changelogs,
postmortems and dated notes. A date does not exempt a locally derivable total,
ratio or copied summary from questions 1 and 2. Remove that derived or copied
restatement while preserving the independent event, measurement and causal context.
For example, a dated upload limit change records the change at that time; today's
config is a different fact. A region addition event survives removal of a total
computable from its recorded historical region details. Do not recompute that old
total using today's regions.
A unique historical atom that passes questions 1 and 2 is not a drift repair.
Its content value still receives Mode 2's analysis under the existing authorization.
When the evidence does not establish whether a claim is derivable, copied or
independently observed, retain it as unresolved and report the gap; do not guess a
basis for deletion. New approval is needed only when the intended action exceeds
the authorization already given.
Linking only solves case 2. Pointing a link at a derived value is a category error:
there is no single authoritative cell to point at, so the link becomes scaffolding that
goes stale on its own and creates a false impression that the two places are aligned.
Why this ordering matters: the mature answer to drift in API documentation is
"generate it from the source, don't hand copy it" (OpenAPI/Swagger exist for exactly this
reason). Question 1 is that same instinct applied to prose — the surest way to keep a
number correct is for it not to be written down twice.
Position gives no exemption
A fact is a fact wherever it sits. All of these are body text for the purposes of the test
above, and all of them are where stale values actually survive audits:
frontmatter · YAML/JSON metadata · parenthetical asides · a description column in an index
table · checkbox state · introductory framing before the real content · cross document
footnotes · an extra column added to a table · commit message shaped notes left in prose
What counts as a fact
Anything that changes over time and has an authoritative definition somewhere: numbers,
status, ownership, relationships, classifications, rules, decision sources, dates, counts.
Business rules count too — "all quotes route through the finance lead" is defined once and
referenced, never restated in each downstream doc.
Mode 1 — Post change governance
Run these in order. The order is the point: fixing derived docs before establishing what
is authoritative just multiplies the work.
1. Scope it from the change, not from the repo.
Enumerate the facts this change altered — this port, this path, this procedure name,
this default. That list is what bounds the work. The list is bounded; the search for
each item on it is not — a fact's quiet copies live precisely in files the change never
touched, so each fact gets searched repo wide in step 5. What is forbidden is the other
thing: opening files to look for unrelated problems. An unbounded sweep is how a doc task
turns into an unreviewable refactor.
2. Identify the authoritative source (SSOT) for each affected fact.
Which file defines this port / path / procedure — as opposed to mentioning it? Update
that first. Everything downstream either points at it or is derived from it.
When a procedure moves from a Skill entry into a reference, include its consuming
CLAUDE.md / AGENTS.md pointer in this scope. Use the
[delivery entry replay](references/delivery entry replay.md) to check the old and repaired
navigation against the actual destination; reachability alone does not establish that
the destination still defines the required procedure.
The practical test for "defines" is where a change has to be made for reality to
change : the file the deployment actually reads, the schema the code loads, the runbook a
human follows step by step. A file that recites the value while explaining something else
is mentioning it. When two files both look declarative, prefer, in order: the one a machine
consumes over one only humans read; the one nearest the thing it describes; the one other
docs already cite. Then say in your report which you picked and on which of those grounds —
an arbitrary pick becomes permanent once step 2 points everything else at it, so it should
be a stated decision rather than an accident of which file you opened first.
3. Resolve implementation disagreements from established intent and authorization.
Treat code, scripts, config, and observed runs as evidence of current behavior, not as
automatic authority over intended behavior. When a requirement, authoritative source, or
test establishes the intended behavior and the user has already authorized the scoped
implementation fix, repair and verify the implementation first, then update the docs to
match. Keep that repair within the facts and files already authorized by the task.
When intended behavior is ambiguous or the implementation change is not already authorized,
report the disagreement and obtain the missing decision or authority before editing code.
Do not make the documentation describe wished for behavior, and do not silently turn a
documentation pass into an implementation project.
4. Decide each affected doc's disposition before editing it.
The document is… Do
Still actionable; only specific facts drifted Update
Built on a premise that no longer holds Archive / retire
Do not patch a document whose premise is gone — you get something internally consistent
and globally wrong, which is harder to spot than an obviously outdated file.
A "this section is superseded" note left inline is not a third option. Maintainer
bookkeeping does not belong in a reader's path; readers lack the context that makes it
meaningful and only get confused. Move it out.
"Archive" means: out of the reader's path, still in history. Concretely: look for a
convention the project already has ( archive/ , archive/ , deprecated/ , or whatever it
uses) and follow it; if there is none, create archive/ at the same level as the file.
Either way move it with git mv so history follows, then repoint or remove every inbound
reference. Do not delete it outright, and do not settle for adding status: deprecated
frontmatter while leaving the file where readers still find it — a retired document still
in the reader's path is still being read.
Ask before archiving anything you did not create, for the same reason step 3 of Phase 4
needs agreement. Running unattended and cannot ask: leave the document untouched and
report it as needing retirement. Do not patch it instead — a document whose premise died
gets more misleading, not less, when you update its facts.
5. Find every copy of each changed fact — before you change it.
This is the step that gets skipped, and it is where the classic failure lives: the obvious
occurrence gets updated and three quiet ones do not. See Verifying below for the exact
commands.
The highest risk shape is renumbering or inserting an item into a sequence , because
you are not changing one fact but a whole family of mutually referencing ones: body text
saying "see step 7", cross references in sibling files, and — the nastiest — prose that
baked the count into a sentence ("the four checks below"). That last one contains none of
the numbers you are searching for, so a search by step number will never surface it.
There is no mechanical sweep for this, and you should not pretend otherwise. Two obvious
scopings were measured and both fail:
Search count words repo wide → 224,330 lines / ~550 MB on a real documentation repo
(17.7 MB scoped to a single project directory). Nobody runs that, and an instruction that
guarantees its own bypass is worse than no instruction.
Search count words only in files that mention the subject → bounded, but wrong in the
direction that matters . Prose that bakes a count into a sentence is exactly the prose
that refers to the subject by alias, translation, pronoun, or bare link — "the four checks
below", 「预检有四个检查」 — and never by its title