Skill Consolidation Design โ
Date: 2026-03-28 Goal: Eliminate duplicate AI agent skills across .github/skills/, .gemini/skills/, and .claude/skills/ by establishing a single canonical source in tooling/skills/ with automated sync to each tool's expected location.
Problem โ
Custom skills (pr-workbench, monitor-ci) are manually duplicated across three directories:
| Directory | Used by | Format |
|---|---|---|
.github/skills/ | GitHub Copilot / VS Code | SKILL.md, YAML frontmatter, $ARGUMENTS |
.github/prompts/ | GitHub Copilot slash commands | .prompt.md, YAML frontmatter, ${input:args} |
.gemini/skills/ | Gemini CLI | skill.md, YAML frontmatter, $ARGUMENTS |
.gemini/commands/ | Gemini CLI slash commands | .toml, TOML format, |
.claude/skills/ | Claude Code skills | SKILL.md, YAML frontmatter, $ARGUMENTS |
All three skill directories currently have byte-for-byte identical content (except filename casing). Claude Code has nothing โ its commands directory doesn't exist.
Scope โ
In scope: Custom project skills only โ pr-workbench and monitor-ci (plus any future custom skills).
Out of scope: Nx plugin skills (nx-workspace, nx-generate, nx-run-tasks, nx-plugins, nx-import, link-workspace-packages). These are managed by the nrwl/nx-ai-agents-config marketplace plugin and should not be touched by the sync script.
Design โ
Canonical Source โ
tooling/skills/<skill-name>/skill.md โ the single source of truth.
Canonical format matches the existing .github/skills/ convention:
---
name: <skill-name>
description: <trigger description>
command: true # optional โ generate slash command files for this skill
---
# Skill Title
...skill content using $ARGUMENTS for user input...Supporting files (scripts, references) live alongside the skill file:
tooling/skills/
pr-workbench/
skill.md
monitor-ci/
skill.md
scripts/
ci-poll-decide.mjs
ci-state-update.mjs
references/
fix-flows.mdSync Script โ
tooling/scripts/sync-skills.js โ a Node.js script (ESM, no external deps) that reads tooling/skills/ and writes to the three target directories.
Run via: npm run sync:skills (new script in root package.json)
Sync Targets โ
For each skill in tooling/skills/:
1. .github/skills/<name>/SKILL.md
- Rename
skill.mdtoSKILL.md - Prepend auto-sync comment
- Copy supporting files (scripts/, references/) as-is with auto-sync comment where applicable
2. .gemini/skills/<name>/skill.md
- Direct copy (canonical format matches Gemini's)
- Prepend auto-sync comment
- Copy supporting files as-is
3. .claude/skills/<name>/SKILL.md
- Rename
skill.mdtoSKILL.md(Claude Code convention) - Prepend auto-sync comment
- Copy supporting files (scripts/, references/) as-is โ Claude Code supports subdirectories in skills
Command Generation โ
For skills with command: true in frontmatter:
1. .github/prompts/<name>.prompt.md
- YAML frontmatter with
descriptionandargument-hintfields - Replace
$ARGUMENTSwith${input:args}in body - Prepend auto-sync comment
2. .gemini/commands/<name>.toml
- TOML format with
descriptionstring andprompttriple-quoted string - Replace
$ARGUMENTSwithin body - Escape backslashes for TOML string embedding
3. Claude Code
- No separate command file needed โ Claude Code skills are invocable as
/skill-nameby default
Auto-Sync Comment โ
Every generated file gets this as the first line:
<!-- AUTO-SYNCED from tooling/skills/<name>/skill.md โ do not edit directly -->For TOML files:
# AUTO-SYNCED from tooling/skills/<name>/skill.md โ do not edit directlyFor JS/MJS files:
// AUTO-SYNCED from tooling/skills/<name>/scripts/<file> โ do not edit directlySafety Rules โ
- Never delete files the script didn't create. Only overwrite files that have the auto-sync comment on line 1. If a file exists without the comment, warn and skip.
- Never touch Nx plugin skills. The script only processes skills found in
tooling/skills/. Other skills in target directories are ignored. - Dry-run mode.
npm run sync:skills -- --dry-runprints what would change without writing.
Script Behavior โ
1. Scan tooling/skills/ for skill directories
2. For each skill:
a. Read skill.md and parse frontmatter
b. For each target (.github/skills, .gemini/skills, .claude/skills):
- Check if target file exists and has auto-sync comment
- If file exists WITHOUT auto-sync comment: warn and skip
- Otherwise: generate and write the transformed file
c. If command: true, generate command files for each platform
d. Copy supporting files (scripts/, references/) to .github and .gemini targets
3. Print summary: X files written, Y skipped, Z warningsnpm Script โ
Add to root package.json:
{
"scripts": {
"sync:skills": "node tooling/scripts/sync-skills.js"
}
}Validation Integration โ
Add a check to npm run validate (or as a standalone lint) that verifies synced files are up to date. Compares generated output against what's on disk โ fails if they differ. This catches forgotten sync runs.
Migration โ
One-time migration to move existing custom skills into the canonical source:
- Create
tooling/skills/pr-workbench/skill.mdโ copy from.github/skills/pr-workbench/skill.md(already lowercase) - Create
tooling/skills/monitor-ci/โ copy skill.md, scripts/, references/ from.github/skills/monitor-ci/ - Add
command: trueto monitor-ci's frontmatter - Run
npm run sync:skillsโ overwrites existing files with auto-sync comment - Verify all three target directories match
- Commit
Future: Skill Creation โ
Update the superpowers writing-skills skill to:
- Default new skill location to
tooling/skills/<name>/skill.md - Remind the author to run
npm run sync:skillsafter creating/editing a skill - This is a documentation/convention change, not a code change