/skill
The package manager for Claude Code skills — npm/brew for the skill registry
at blamechris/skill-templates.
Install, list, and update skills on demand, tailored to the current repo by
the agent running this command. No central fan-out, no per-repo deploy PRs.
This replaces the old push-based deploy: instead of a CI job pre-customizing every skill into every repo, a repo pulls a skill the moment it needs one and the invoking agent customizes it inline using the repo's own context.
Arguments
$ARGUMENTS— a subcommand and optional skill name:add <name>— install a skill into this repo (resolve → customize → write → lock).list— show available skills (from the registry index) vs what's installed here.outdated— show installed skills whose template has moved on in the registry.update [name]— re-install stale skills (all outdated, or just<name>).remove <name>— delete an installed skill and its lock entry.- With no argument, default to
list.
Concepts
- Registry —
blamechris/skill-templates. Holds pure generic templates ingeneric/<name>.md(with{{CUSTOMIZE: …}}markers) and an indexregistry.json. - Index —
registry.jsonat the registry root: one entry per skill with its current template githashand a one-line description. The cheap source of truth forlist/outdated. Regenerated byscripts/build-index.sh. - Installed skill —
.claude/commands/<name>.mdin this repo: the template with every{{CUSTOMIZE}}marker filled for this repo, ending with a version stamp. - Version stamp — the last line of an installed skill:
<!-- skill-templates: <name> <hash> <date> -->. The<hash>is the registry template commit the install was built from. This is the per-skill version pin. - Profile —
.claude/skill-profile.mdin this repo: the repo's identity and per-skill tailoring notes. The agent reads it (plusCLAUDE.mdand the code) to fill{{CUSTOMIZE}}markers. If absent, the agent infers fromCLAUDE.md+ repo layout and notes in its report that a profile would sharpen future installs. - Lockfile —
.claude/skills.lock(JSON): the manifest of what's installed and at which template hash. Letsoutdated/updatework from repo-local state. - Targets — the coding agents a skill is compiled for.
.claude/commands/<name>.md(the customized install) is the provider-NEUTRAL source;scripts/compile-skill-targets.mjsemits each agent's NATIVE custom-command format:claude→.claude/skills/<name>/SKILL.md,gemini→.gemini/commands/<name>.toml,codex→~/.codex/prompts/<name>.md. The active list comes from thetargets:line in.claude/skill-profile.md(prompt the user if absent; the compiler falls back toclaude). This is what makes a skill model-agnostic — author once, run under any model. The neutral arg token is$ARGUMENTS; the compiler maps it per agent (e.g. Gemini{{args}}). The compiler ships in the registry atassets/compile-skill-targets.mjs.
Resolving the registry
Find the registry once, in this order; use the first that works:
$SKILL_REGISTRY_DIRif set — a local clone path.~/Projects/skill-templatesif it exists — the conventional local clone (fast, works offline for reads).- Otherwise fetch over the network with
gh:- Index:
gh api repos/blamechris/skill-templates/contents/registry.json --jq '.content' | base64 -d - Template:
gh api repos/blamechris/skill-templates/contents/generic/<name>.md --jq '.content' | base64 -d - Hash of a template:
gh api 'repos/blamechris/skill-templates/commits?path=generic/<name>.md&per_page=1' --jq '.[0].sha[0:7]'
- Index:
When using a local clone, refresh it only when online and tolerantly:
git -C "$REG" pull --ff-only --quiet 2>/dev/null || true. A failed fetch (offline) or
a non-fast-forward leaves the existing clone usable — fall back to its current state and
note in the report that hashes may be stale. Record which source you used.
Instructions
skill list
- Resolve the registry and read
registry.json. - Read this repo's
.claude/skills.lock(treat missing as empty) and list.claude/commands/*.md(treat a missing directory as no skills installed — a bare repo being bootstrapped). - Print a table: skill, registry hash, installed hash (from the stamp/lock), and
status —
installed/outdated/not installed. Group installed first.
skill add <name>
- Resolve & fetch. Read
registry.json; confirm<name>exists (if not, suggest near matches from the index and stop). Fetchgeneric/<name>.mdand capture its current templatehash. - Gather repo context. Read
CLAUDE.md,.claude/skill-profile.md(if present), and enough of the repo (layout, test/build commands, labels, conventions) to fill the template's{{CUSTOMIZE: …}}markers. The marker text describes what each spot needs. - Customize inline. Produce the final skill markdown by following the registry's
customization rules exactly:
- Replace every
{{CUSTOMIZE: …}}marker with content derived from the repo context. The marker text says what kind of content is needed. - If the repo context has nothing relevant for a marker, remove the marker line entirely — never leave a blank or placeholder marker.
- Preserve all non-customizable text exactly — do not rephrase, reorder, or "improve" anything that isn't a marker. Preserve all code blocks and formatting.
- Remove the entire trailing
## Customization Pointssection (it's meta-docs for template maintainers, not part of a deployed skill). - Never invent specifics. If a marker asks for examples the repo context does
not provide (file:line citations, label names, agent rosters, commands), use
placeholder shapes (
path/to/file:<line>,scope) rather than fabricating. - No attribution anywhere — no "Generated with", no "Co-Authored-By", no AI mentions (this is a hard registry rule).
- Replace every
- Self-validate before writing (the agent IS the validator here — these cover the
registry's
validate_outputchecks, including its skeleton-preservation pass):- No residual markers: no
{{CUSTOMIZEremains (outside backticked mentions). - No attribution footer: none of the last ~15 lines start with "Generated with Claude" / "Co-Authored-By: Claude".
- Headings preserved (exact): every real markdown heading from the template
(minus the removed
## Customization Points) appears verbatim in the output. - Body preserved: non-heading, non-marker template lines survive in the output —
only the spots where a
{{CUSTOMIZE}}marker was filled or removed may differ. Do not silently drop or reword the template's prose, code blocks, or examples. - Length sane: output is roughly 50–200% of the template length (catches truncation or runaway expansion).
- No forged stamp: the customized body contains no
<!-- skill-templates: … -->line of its own. Strip any before step 5 appends the single authoritative stamp, sooutdatedcan't be fooled by a planted version. - Guards intact: if this skill has a
guardsarray inregistry.json, every guard must still be satisfied — for each guard, at least one of itsanyOfregexes matches the customized output. A guard miss means customization stripped a load-bearing section; restore it. (These are the content checks ported fromsync.sh.) - If any check fails, fix and re-check before writing. Never write defective output.
- No residual markers: no
- Write + stamp. Create
.claude/commands/if absent, strip any pre-existing<!-- skill-templates: … -->lines from the body, then write to.claude/commands/<name>.mdending with exactly:<!-- skill-templates: <name> <hash> <date> -->(today's date,YYYY-MM-DD). - Lint (deterministic gate). Run the registry's mechanical linter on the file just
written — it re-checks markers, attribution, the stamp, and guards independently of
the agent's judgment:
"$REG/scripts/skill-lint.sh" <name> .claude/commands/<name>.md(where$REGis the resolved registry clone). If it exits non-zero, fix the reported issues and re-lint before recording the lockfile — do not lock a skill that fails lint. Consumers can run the same linter as a pre-commit hook or in CI. - Compile to native targets. Ensure the compiler exists in this repo (create
scripts/if absent). Ifscripts/compile-skill-targets.mjsis missing — or you're runningupdate, so it stays current with the registry — (re)fetch it: from a local clone,cp "$REG/assets/compile-skill-targets.mjs" scripts/; on the network-only path (no local clone), fetch it like the templates —gh api repos/blamechris/skill-templates/contents/assets/compile-skill-targets.mjs --jq '.content' | base64 -d > scripts/compile-skill-targets.mjs. Write it toscripts/and track it in VCS so it travels with the repo. Read thetargets:line from.claude/skill-profile.md; if there is none, ask the user which agents to compile for (claude / gemini / codex) and offer to record the choice in the profile (the compiler falls back toclaudeif unset). Then runnode scripts/compile-skill-targets.mjs --name <name>(it reads the profile targets), or--targets <list>to override. It writes the native artifact per target and exits non-zero on any emit failure — treat that as a hard gate: fix and re-run before locking. Codex emits to the user-global~/.codex/prompts/(not version-controlled, deprecated upstream) — only whencodexis explicitly a target. Keep the list oftargetsyou compiled with for the next step. - Record in the lockfile. Only after a successful compile, create
.claude/skills.lock(schema below) if absent and upsert<name>atomically with: the templatehash; theprofileHashwhen a.claude/skill-profile.mdexists (soupdatecan tell when the profile changed, not just the template); and thetargetsyou just compiled with (soremovecleans exactly the right native artifacts andoutdatedcan detect target drift). Writing the entry only after compile succeeds means a failed compile never leaves a half-written ortargets-less entry. - Report. State the skill, the hash installed, the registry source used, the targets compiled (with output paths), and any markers dropped for lack of repo context.
skill outdated
- Resolve the registry and read
registry.json. - For each entry in
.claude/skills.lock(or each stamped.claude/commands/*.md), flag it stale if any of:- version drift — installed
hash≠ the registry's current hash; - profile drift — the lockfile's
profileHash≠ the current.claude/skill-profile.mdhash (the skill was tailored against an older profile); - corruption drift — the installed file fails a registry
guard(some guard'sanyOfregexes no longer match — a load-bearing section was lost). - target drift — only when the lock entry has a
targetsarray (a pre-targetsinstall with no such field is treated as "unknown" — fall back to disk inspection, never flagged just for the field's absence): the profile'stargets:list has an agent not in the lock entry'stargets(added to the profile but never compiled), or a recorded target's native artifact is missing on disk — excluding targets the compiler intentionally skips (e.g. Gemini for a body containing{{…}}/!{…}/@{…}, which is never emitted and so isn't real drift). A plain recompile fixes genuine target drift — no registry fetch needed.
- version drift — installed
- Print the drifted skills with the reason, e.g.
name abc1234 → def5678 (version)orname (guard miss: idempotency)orname (target drift: gemini not compiled). If none, say so. (This is the consumer-side port of the registry'ssync.shdrift check — version stamp and content guards.)
skill update [name]
- Run
outdated. If<name>is given, narrow to it. - For each stale skill, re-run
add(which re-fetches, re-customizes against current repo context, and re-stamps). Skip skills already current. - Report what was updated
old → newand what was already current.
skill remove <name>
Read the skill's targets from its .claude/skills.lock entry, then delete
.claude/commands/<name>.md, its lock entry, and exactly the native artifacts for those targets:
claude → .claude/skills/<name>/ (dir), gemini → .gemini/commands/<name>.toml,
codex → ~/.codex/prompts/<name>.md. If the lock entry has no targets (an older install),
fall back to removing whichever of those three exist. Report what was removed.
Lockfile schema (.claude/skills.lock)
{
"registry": "blamechris/skill-templates",
"skills": {
"full-review": { "hash": "cc062bc", "installed": "2026-06-04", "profileHash": "3f1a9c2", "targets": ["claude", "gemini"] },
"check-pr": { "hash": "a10ef75", "installed": "2026-06-04", "targets": ["claude"] }
}
}
hash— the registry template commit this install was built from (matches the version stamp).outdateddiffs this againstregistry.json.installed— date the install/update ran (YYYY-MM-DD).profileHash(optional) — short hash of.claude/skill-profile.mdat install time. Present only when a profile existed.outdatedflags profile drift when it no longer matches the current profile, so a changed profile triggers a re-tailor onupdate.targets(optional) — the agents this skill was compiled for at install time (e.g.["claude", "gemini"]). Written by theaddcompile step;removeuses it to delete exactly the right native artifacts, andoutdateduses it to detect target drift. Absent on pre-targets installs — treat a missingtargetsas "unknown" and fall back to disk inspection.- The lockfile is the authoritative manifest; the per-file stamp is a convenient inline mirror. Keep them in agreement.
Notes
- The agent is the customizer. No Haiku/API key — the agent running
/skilltailors the template with full repo context, which is richer than a context-blind batch job. The self-validation step replaces the registry's automatedvalidate_output. - Auto-install on miss. A repo or global
CLAUDE.mdrule should say: asked to run/X? Check the neutral source.claude/commands/X.md. Missing → not installed →skill add X. Present but the native artifact (.claude/skills/X/SKILL.md) is missing → just not compiled → recompile withnode scripts/compile-skill-targets.mjs --name X(no registry fetch). Then invoke. That makes "use /full-review in a repo that lacks it" just work without re-fetching when a recompile suffices. - Compile is deterministic. The generic→native transform lives in
scripts/compile-skill-targets.mjs, not in agent judgment, so the native artifacts are reproducible. Edited a skill's generic source (.claude/commands/<name>.md) by hand? Recompile withnode scripts/compile-skill-targets.mjs --name <name>(--dry-runpreviews). - Idempotent. Re-running
addfor a current skill is a no-op re-render; re-running for a moved template updates it. Safe to run anytime. - Self-contained on first use.
/skillneeds no customization to work — it ships with sane registry defaults so it can bootstrap a repo that has nothing else installed.
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.