skill-rot
ADLC phase: P7 — cache invalidation (C10)
Skills are caches. skill-rot validates that the verifiable claims inside each
SKILL.md file still hold against the current repository. Stale skills deliver
misinformation with the authority of a cached expert — worse than no skill at
all. Run weekly in CI to keep the skill corpus honest.
Usage
skill-rot [path ...] [--write] [--json]
Default search roots (searched only when they exist):
.claude/skills.agents/skillsskills
Pass one or more explicit path arguments to override the defaults.
Symlinked skill directories and symlinked SKILL.md files are followed, with cycle detection preventing infinite recursion on recursive symlink graphs. Directories named node_modules or .git below a search root are skipped. A symlink resolving into one is skipped during default discovery and is an operational error (exit 1) when you pass explicit paths; name the target path to check it.
Flags
| Flag | Description |
|---|---|
--write | When all claims in a skill are ok, upsert last-verified: <YYYY-MM-DD> into the skill's frontmatter (created if absent). Skills with stale claims or zero claims are never stamped. |
--json | Machine-readable output for orchestrators. Prints a JSON object with skills[] and summary. |
What gets verified
For each SKILL.md file found recursively (skipping node_modules and .git):
-
Commands — backtick-enclosed spans and fenced code block lines whose first token looks like a command name. Verified via:
./node_modules/.bin/<cmd>presence, ORsh -c 'command -v <cmd>'
Placeholder tokens are skipped:
<ANGLE_BRACKETS>andUPPERCASE_VARS(3+ chars, all caps/underscores/digits) are never counted as stale. -
File paths — tokens containing
/and a file extension (e.g.src/index.mjs). Checked viaexistsSyncfrom the repo root and from the skill's own directory. -
Script references —
npm run X,npx X,pnpm X,yarn Xpatterns. KeyXis looked up inscriptsof the rootpackage.json. If nopackage.jsonexists, the claim isunverifiable.
Claim statuses:
ok— verifiable and passesstale— verifiable but fails (counts toward gate failure)unverifiable— cannot determine truth (URLs, nopackage.json, ambiguous)
Unverifiable claims are never counted as stale. Skills with zero checkable claims are reported as [NO-CLAIMS] and are never stamped under --write. A skill whose claims are all unverifiable is reported as [UNVERIFIED], is not counted clean, and is never stamped.
Exit codes
| Code | Meaning |
|---|---|
0 | Gate passes — no skill has stale claims |
1 | Operational error — no SKILL.md files found, bad input, or an explicit path that cannot be fully inspected |
2 | Gate fails — at least one skill has stale claims |
Examples
# Check defaults (.claude/skills, .agents/skills, skills)
skill-rot
# Check specific directories
skill-rot .claude/skills .agents/skills
# Stamp clean skills with today's date
skill-rot --write
# JSON output for CI integrations
skill-rot --json
Relationship to sibling tools
- lesson-foundry (C9) — produces skills;
skill-rotvalidates they stay fresh - review-calibration (C8) — calibrates review quality;
skill-rotprevents outdated guidance corrupting that calibration loop - gate-manifest (C11) — can consume
skill-rotexit code as a provenance signal
Core gaps
None. This tool uses only Node 18+ built-ins and @adlc/core for CLI
utilities (parseArgs, pass, gateFail, opError, printJson).