This repo's history uses minor bumps for deliberate changes to what the plugin is or ships (1.1.0 swapped the cuOpt skill, 1.2.0 consolidated it, 1.3.0 moved to discovery-first) and reserves patch bumps for the automated "chore: sync skills" commits. Renaming the display name, rewriting the listing copy, changing category, replacing the logo, and shipping #379's routing taxonomy is the former, not the latter. Signed-off-by: Jason Dudash <jdudash@nvidia.com>
plugins.d/ — plugin catalog source
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>/.cursor-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).cursor-plugin/marketplace.json(top-level Cursor 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).
Source of truth
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.sh
skill_files: — copy vs symlink
Each 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.
Adding a plugin
-
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.
Renaming a plugin
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.sh
The 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.
Curated (hand-maintained) plugins
Legacy fallback — no plugins currently use this mode. Every plugin in this repo is catalog-driven (defined by a
plugins.d/<name>.yml).
The build script still supports a hand-maintained mode: a directory under
plugins/<name>/ that has its own .skills-manifest.yml instead of a
plugins.d/<name>.yml is treated as curated — the build only refreshes
its skills/ tree and otherwise leaves .claude-plugin/,
.codex-plugin/, .cursor-plugin/, assets/, and the marketplace
entries hand-edited.