skill-maintenance
Installation
SKILL.md
Skill maintenance
Makes every change to an agent skill land finished: built to the skill standard, self-contained, routed by a sharp description, and proven by its own checkers and their planted-bug self-test. The usual reader of a skill is an agent working with no human review, so a skill is correct only when the checks here say so.
Rules that must hold
- A skill is done only when its checks pass.
validate-skill.mjs, the skill's ownscripts/selftest.mjsandcheck-skill.mjsall printRESULT: PASS; nobody reads skill files closely, so nothing else counts as review. - Copy knowledge in; never point at it. No repo docs, design files, research notes, other skills' files, maintainer tooling paths, absolute, scratch or
../paths, and no runtime variable that only some agents set (${CLAUDE_SKILL_DIR}in markdown is the one allowed); a skill is installed alone (a plugin cache,.agents/skills/,.claude/skills/) and every pointer dangles there. - The description decides whether the skill is ever used. At most 300 characters (aim for 250), a third-person verb first, "Use when" with the words tasks contain, and "Not for ()"; the agent sees only names and descriptions before it loads a skill, and that listing is budgeted.
- Rules and the definition of done sit at the top, in the six-section order, and SKILL.md stays at 300 lines or fewer. After context compaction only the first 5,000 tokens of a skill survive, so whatever sits lower is lost in long sessions.
- Frontmatter is
nameanddescription, plus the few allowed keys.disable-model-invocation: truebelongs only on a side-effectingrun-*runbook whose workflow stops and asks;allowed-toolsandhooksmake the agent's own invocation need approval (denied in headless runs), andpathsoruser-invocablehide the skill. - Every checker proves itself against planted bugs. A good case and one
bad-*case per rule listed in its--help, each EXPECT naming the rule id, written as overlay cases (amutation.jsonon a shared base); a check that has only ever passed proves nothing, and an EXPECT that says only "FAIL" passes on a crash. - Checkers keep the output contract and never pass on nothing. Positional repo root,
--help, exit 0/1/2, aRESULT:last line; a missing target exits 2; SKIP only throughnotYetCreated()for a file another skill creates, NOT APPLICABLE only for a repo fact, and ship gates never skip; a silent pass turns a gate green on a typo. - Checkers read the app through its layout and contracts, never through hard-coded paths.
resolveLayout()for folders,walkRepo()for scans (it prunes installed skills, whose fixtures plant bugs on purpose), app facts in a repo-ownedcontracts/<name>.jsonwhose template the skill ships, and every device named (maestro --device, a simctl UDID,adb -s, an AVD name); otherwise the checker works in one repo only or reaches another session's simulator. - Templates are real files that name their repo path on line 1 and pass a real app's gates.
tsc, ESLint and Jest in a reference app; a template that does not compile teaches the bug it was meant to prevent. - Edit the canonical copy, never a synced or generated file. Shared files change in the library's shared folder and arrive through its sync; generated files change through their generator; the next sync or render erases a hand edit, and the validator fails on drift first.
- Every version-sensitive fact carries a "verified on" date and a re-verify command. Expo, React Native and agent tooling move faster than memory; a dated fact with its command is refreshed in minutes, an undated one rots silently.
- Touch only the skill you were asked to change. Other people and agents work on other skills in parallel, writes under
.claude/need the developer, and shared or generated files have owners; put every other needed change in the report.