| name | skill-builder |
| description | Build a new skill for the ai-config repo the right way — FIRST check whether an existing skill should be extended instead (search skills/, scan every branch for in-flight similar work, AND check open PRs for in-progress drafts to redirect to instead of duplicating), and only then scaffold skills/<name>/SKILL.md with proper frontmatter, a discoverable trigger-rich description, a spelled-out/short alias as appropriate, cross-links, and (if it encodes a standing rule) matching preferences.md / CLAUDE.md updates — shipped via branch + PR, reviewer requested, ARDI'd to clean. Use when asked to 'build a skill', 'create a skill', 'make a new skill', 'add a skill', 'add an alias for X', 'make X an alias for Y', 'should this be an alias for Y', or 'skill-builder' — creating an alias stub routes here too, so the codex wrapper gets regenerated and the stub is self-reviewed. |
| user-invocable | true |
| allowed-tools | ["Bash","Read","Edit","Write"] |
skill-builder — author a new skill (extend-first)
Create — or, preferably, extend — an ai-config skill following the repo's
conventions. The prime directive: don't create a new skill until you've
confirmed no existing one should be extended instead, and that no other
branch is already building it.
When this fires
- "build a skill", "create a skill", "make a new skill", "add a skill",
"skill-builder"
- Creating an alias for an existing skill — "add an alias for X", "make X
an alias for Y", "should this be an alias for Y" — is a skill-builder task
too, not a raw
Write of a stub file. Hand-writing an alias SKILL.md
skips the codex-wrapper regeneration (the required step below) and trips the
validate CI check, and skips the self-review pass that catches errors in
the stub's own prose. (ai-config#569: a hand-written giardia→gia alias
stub failed validate on the missing wrapper and needed a review round to
fix a reversed phase-order description — both avoidable by routing here.)
- Any time a repeatable multi-step workflow emerges that's worth codifying —
proactively suggest capturing it as a skill.
Step 0 — Extend before you create (do this FIRST, always)
Rule out extending an existing skill before scaffolding anything:
-
Search the live skills for something that already owns (or is adjacent
to) this concern:
cd "$(git -C ~/.claude/skills/skill-builder rev-parse --show-toplevel)"
ls skills/
grep -ril "<keywords>" skills/*/SKILL.md
If a skill already covers it, extend that skill (a new alias, a new
section, an extra trigger phrase) rather than adding a near-duplicate.
-
Scan EVERY branch AND every local worktree for in-flight work — you,
another CLI session, or the @claude bot may already be adding it. A
parallel CLI session usually builds its skill in an unpushed local
worktree, so a remote-only git branch -r scan misses it entirely (this
hit PR #67 — a sibling skill was caught only by a stray system-reminder, not
the scan). Scan local refs and the worktree working trees too:
git fetch origin --prune
for b in $(git branch -a --format='%(refname:short)' | grep -v HEAD); do
git ls-tree -r --name-only "$b" | grep -iE "skills/[^/]*<keyword>" \
| sed "s|^|$b: |"
done
git worktree list --porcelain | sed -n 's/^worktree //p' | while IFS= read -r wt; do
git -C "$wt" ls-files --others --exclude-standard -- 'skills/' 2>/dev/null \
| grep -iE "skills/[^/]*<keyword>" | sed "s|^|$wt: |"
done
If a branch or worktree is already building it, continue that work (check
it out / extend its PR) instead of opening a colliding parallel branch.
-
Check open PRs too — a branch scan misses work already pushed and
opened as a PR if you never fetched it. See
check-open-prs-before-duplicating.
-
Decide explicitly: extend (preferred) or new. State which and why before
writing a line. A new alias or section almost always beats a whole new skill.
Anatomy of a skill
One directory per skill, name matching the directory:
skills/<name>/SKILL.md
---
name: <name>
description: "<what it does>. Use when asked to '<trigger>', '<trigger>', …"
user-invocable: true
allowed-tools:
- Bash
- Read
- Edit
- Write
---
description is how the skill gets discovered. Pack it with what it
does AND the natural-language triggers (Use when asked to '…'). The matcher
reads this — be generous with trigger phrasings.
- Body shape:
# <name> — <tagline>, then ## When this fires,
## Procedure, ## Relationship to other skills, ## Anti-patterns.
Concrete commands beat prose.
Conventions (match the existing family)
If the skill fans out to subagents
When a skill's procedure spawns subagents (to parallelize per-item work, e.g.
pr-status-all runs one subagent per PR), write the subagent prompt as if the
skill file doesn't exist — because for the subagent it doesn't. A spawned
subagent starts fresh: it sees only the prompt the orchestrator hands it, not
this skill's text. Any discipline the work depends on (the exact query, the
bot-login wording, how to resolve owner/repo, "read the LATEST review") has to be
restated inside the subagent prompt, not assumed inherited. Keep the cheap,
once-per-run setup in the orchestrator — enumerate the work items there, and pass
down the per-item data the orchestrator already holds so each subagent doesn't
re-fetch it. pr-status-all is the worked example.
If the same worker persona would be spawned by more than one call site, or the
fan-out step needs a harness-enforced tool boundary an inline prompt can't
guarantee (e.g. a detection pass that must never be able to write), promote it
to a persistent .claude/agents/<name>.md subagent instead of an inline
prompt — hand off to agent-builder for that. dependency-auditor,
hallucination-detector, and community-demand-scout are the worked examples.
If the skill encodes a standing rule
When the skill codifies general guidance or a preference (not just a one-off
procedure), also update memories/preferences.md, and for top-level
workflow policy add a CLAUDE.md section. Standing rule: update BOTH the
skill AND preferences — the skill encodes the behavior, preferences make it
persist and fire across all contexts even when the skill isn't invoked.
Ship it
Skills and memories all live in the ai-config repo — never leave changes
local-only. Commit via a branch + PR (not direct to main), request
d-morrison as reviewer, then ARDI to clean.
In a worktree session, the repo toplevel below is the MAIN checkout, not
your worktree. ~/.claude/skills symlinks into the main ai-config
checkout, so git -C ~/.claude/skills … rev-parse --show-toplevel returns the
main repo root — often on another session's branch. Don't cd there and don't
pass that path to Write/Edit: the skill files (and git commits) would land in
the main checkout, clobbering another session's working tree. Instead author
the files in your worktree's own skills/<name>/ dir and run git from the
worktree (it's a full checkout of the same repo). Confirm with
git branch --show-current before committing.
cd "$(git -C ~/.claude/skills/skill-builder rev-parse --show-toplevel)"
git fetch origin main && git checkout -b add-<name>-skill origin/main
python3 scripts/sync-codex-skill-wrappers.py
python3 scripts/validate-skills.py
python3 scripts/check-links.py
python3 scripts/check-vendored-drift.py
npx --yes markdownlint-cli2@0.22.1
git add skills/<name>/SKILL.md codex-skills/<name> \
skills/<alias>/SKILL.md codex-skills/<alias> \
memories/preferences.md
git commit -m "skills: add <name> — <summary>"
git push -u origin HEAD && gh pr create --fill
Regenerate the Codex wrappers — every new or renamed skill needs them.
codex-skills/ is a generated tree of thin Codex-compatible wrappers, one per
skills/<name>/, and the validate CI job fails if it's out of sync (the red
log reads Codex skill wrappers are out of sync:). After writing the skill (and
any alias dir), run
python3 scripts/sync-codex-skill-wrappers.py, then git add the new
codex-skills/<name>/ (and codex-skills/<alias>/) alongside the source.
The validate CI job runs four checks — scripts/validate-skills.py
(frontmatter + wrapper sync + manifests), scripts/check-links.py (relative
markdown links), scripts/check-vendored-drift.py (shared-fragment drift), and
markdownlint-cli2 (markdown style). Run all four before pushing to catch a
stale wrapper, broken link, drift, or lint violation without a red-CI
round-trip. Markdownlint lints every SKILL.md; the corpus disabled the
rules its legacy files already violate (see .markdownlint-cli2.jsonc), so a
new skill still has to pass the rest — e.g. unique headings (MD024) and blank
lines around tables (MD058).
Then, as their own explicit steps (don't leave them buried in a comment):
- Request the reviewer:
gh pr edit --add-reviewer d-morrison (EDIT_PR; see
request-pr-review).
- Drive to clean: run the
ardi skill on the new PR until the verdict has
zero findings.
Why git -C … rev-parse --show-toplevel over dirname "$(readlink …)":
bare readlink (no -f) resolves only a single hop and behaves
inconsistently across macOS/Linux; rev-parse --show-toplevel returns the
repo root directly regardless of how the symlink chain is set up.
Relationship to other skills
spot-skill-opportunities — the recognition step that runs before this
one: it notices, continuously and in the moment, that a pattern is
skill-shaped and hands off here to build it. ums / record-learnings
route through it too rather than judging recurrence themselves.
ums / record-learnings — when a session reveals a workflow worth
codifying, they hand off to this skill to build it.
memorize / remember — for a one-line fact or preference (not a
procedure), write a memory instead of a skill.
request-pr-review, ardi — used to ship and clean the new skill's PR.
simplify / tidy — when extending, prefer collapsing into an existing
skill over proliferating near-duplicates.
consolidate-skills — when you discover a near-duplicate that already
shipped (two real skills for one workflow), hand the cleanup there: it merges
them into one canonical skill plus alias stubs.
decompose-skill — when Step 0 finds the closest existing skill to
extend is actually two concerns wearing one name, hand the cleanup there
instead of bolting a third concern on.
heal-skill — the repair counterpart: this skill authors a skill,
heal-skill fixes one that misfired after it shipped.
agent-builder — the subagent-file counterpart: this skill authors
user-invocable workflows in skills/; agent-builder authors the
persistent, read-only fan-out worker personas a heavy skill's subagent step
can promote to .claude/agents/<name>.md.
link-skills — this skill cross-links the one skill it authors;
link-skills is the corpus-wide audit that catches cross-reference gaps a
single authoring pass missed.
config-ai — the broader router this skill is one destination for: when
a request names a capability but not a mechanism, config-ai decides
whether it's a skill (→ here), a subagent, a memory, a hook, or a gha
capability, then hands off accordingly.
Anti-patterns
- ❌ Creating a new skill when an existing one should be extended (skipping step 0).
- ❌ Not scanning other branches → colliding parallel work / duplicate skills.
- ❌ Not checking open PRs → building a second draft of a skill someone already
pushed and opened a PR for, instead of redirecting to it.
- ❌ Duplicating canonical content across alias files (aliases must only redirect).
- ❌ Hand-writing an alias
SKILL.md directly (raw Write) instead of routing
through skill-builder — skips codex-wrapper regeneration (trips validate)
and the self-review pass (giardia→gia, #569).
- ❌ A thin description with no trigger phrases — the skill never gets discovered.
- ❌ In a subagent-fanning skill, writing the subagent prompt as if it inherits
this skill's text — it doesn't; restate every needed discipline in the prompt.
- ❌
name: not matching the directory name.
- ❌ Encoding a standing rule in the skill but not in
preferences.md.
- ❌ Naming a GitHub MCP tool (or
gh/git operation) the skill uses without
registering it in tool-mappings.yml — the reviewer flags the unregistered
name as a possible hallucination (push-memory #311, resolve-pr-threads #347).
- ❌ Bumping
skills.qmd's skill count by a manual +1 instead of re-deriving it
from ls -d skills/*/ | wc -l — it drifts whenever main gains other skills
mid-review (resolve-pr-threads #347).
- ❌ Citing a
CLAUDE.md section or an "existing scale/convention" in new
skill prose without grepping to confirm it actually exists first
(check-info-quality #349).
- ❌ Leaving the new skill as a local-only uncommitted file (or pushing direct to main).
- ❌ In a worktree session, writing the skill files to the
rev-parse --show-toplevel
path — it resolves to the main checkout (via the ~/.claude/skills symlink), not
your worktree, so the files land on another session's branch. Author in the
worktree's own skills/ dir.