Each <name>.yml here defines one plugin. The build script
.github/scripts/build-plugins.py
parses these files and (re)generates:
plugins/<name>/.claude-plugin/plugin.jsonplugins/<name>/.codex-plugin/plugin.jsonplugins/<name>/skills/<skill-basename>/symlinks into the canonicalskills/catalog.claude-plugin/marketplace.json(top-level Claude marketplace registry).agents/plugins/marketplace.json(top-level Codex marketplace registry)
Files whose names start with _ are treated as includes and are not
themselves built into plugins. _defaults.yml provides shared author /
license / capability defaults; per-plugin yaml fields override the defaults
(shallow merge).
The skills/ directory is the single source of truth — every SKILL.md
exists exactly once there. The plugin tree under plugins/ is reconstructed
from these YAML files on every build, so adding/removing a curated skill
only requires editing the include_skills: list and re-running:
.github/scripts/build-plugins.shEach plugin selects what kind of files end up under
plugins/<name>/skills/:
| Mode | What's on disk | Use when |
|---|---|---|
copy (default) |
real files (rsync) | publishing to Codex / Anthropic; required for codex plugin add (Codex drops symlinks during install) |
symlink |
relative symlinks → ../../../skills/<Product>/<skill> |
shipping to Claude only or to npx skills add consumers; avoids duplication |
The default lives in _defaults.yml; override per
plugin by setting skill_files: symlink (or copy) in
plugins.d/<name>.yml.
-
Create
plugins.d/<name>.ymlwith at minimum:name: <name> # lowercase kebab-case, must match the file basename description: ... # one-line summary display_name: ... short_description: ... long_description: ... category: Developer Tools include_skills: - skills/<Product>/<skill>/
-
Run
.github/scripts/build-plugins.sh. -
Commit the regenerated
plugins/<name>/tree and the updatedmarketplace.jsonfiles alongside the new yaml.
The build script doesn't know a rename happened — it just sees a new
name and builds a fresh plugins/<new-name>/ next to the old folder.
You have to delete the old one yourself, or it will sit in the repo
forever (CI won't flag it).
To rename plugins.d/old.yml → plugins.d/new.yml:
git mv plugins.d/old.yml plugins.d/new.yml
# edit the file and change `name: old` to `name: new`
git rm -r plugins/old
.github/scripts/build-plugins.shThe rebuild regenerates both marketplace.json files for you; just
git add everything that changed (the renamed yaml, the new
plugins/new/ tree, the deleted plugins/old/, and both
marketplace.json files) and commit it all together.
Heads up: the plugin name is what users type to install
(claude plugin install <name>, codex plugin add <name>). If the old
name has been published anywhere, renaming is a breaking change for
those users.
A directory under plugins/<name>/ that has its own
.skills-manifest.yml instead of a plugins.d/<name>.yml is treated as
a curated plugin: the build script only refreshes its skills/ symlinks
and otherwise leaves .claude-plugin/, .codex-plugin/, assets/, and
the marketplace entries hand-edited.