verify-claims: an npm CLI that catches stale doc claims
A note in one of my repos used to say: "the tables are empty, migrate freely." True the day I wrote it. By the time I read it again, the database held real records — the note was one step from wiping them. Nothing had flagged that it had gone false. It just sat there, still trusted.
That's the whole failure mode. A doc says "Lint: 0 errors" or "Build: passes" or "the live database holds 10 transactions." It's correct when it's written. Nobody re-checks it, because re-checking means stopping and running the command by hand. So it quietly goes false and keeps being trusted anyway. It happened to me twice in the same repo before I built something to stop it.
Attach a command to the claim
verify-claims turns a doc claim into something that can be run and checked, the same way a test can. Write the command that proves the claim in an HTML comment right above it. HTML comments render as nothing on GitHub, so the doc still reads normally to anyone who's never heard of the tool:
<!-- claim: npm run lint -->
Lint: **0 errors**Then run it against your docs:
npx verify-claims "docs/**/*.md"
docs/README.md
✓ line 12 npm run lint
✗ line 20 npm run build (expected exit code 0, got exit code 1)
1 passed, 1 failedEach claim's command actually runs. A non-zero exit code means the claim is false. Wire the same call into CI and a stale claim fails the build the same way a failing test would. Otherwise it sits in a markdown file, quietly wrong, until someone trusts it at the worst possible moment.
Why not one of the existing tools
Tools like Fiberplane Drift, doc-drift-guard, and GitBook already watch for doc drift, but they all answer the same question: has the code this text points at changed? That's a parsing problem: diff the referenced file, flag the doc if it moved. None of them can answer whether "0 errors" is still true, because that isn't a diff, it's an assertion, and the only way to check an assertion is to run it. markdown-doctest is the closest match, but it hasn't shipped in over 2,000 days, and eslint-plugin-markdown is deprecated. The gap wasn't crowded; it just needed a tool willing to execute something instead of parsing it.
What it doesn't do
v1 is deliberately small: parse the claim, run the attached command, compare the exit code, report, fail CI on a false claim. It doesn't check databases, doesn't track template drift, doesn't auto-fix anything, and has no AI in it anywhere. The exclusion list is as much the design as the feature list. Adding scope later means the engine (assert a fact, run a check, compare) can carry it; a database-claim or template-drift version would be a plugin on the same core, not a rewrite.
Whether other developers want this is assumed, not measured — the evidence it's a real problem is strong for me: it happened twice, in my own repo, before I'd hand-built partial fixes. I built it, published it on npm, and MIT-licensed it, primarily to learn how to ship a package properly end to end. That goal holds regardless of who else uses it.
Try it
npm install -D @shrinivas-sn/verify-claims, then point it at a glob. Full README, the CLI reference, and the build's own worklog are on GitHub. It's one of a few things I've shipped end to end. The rest are on the projects page.