Compare commits

...

2 Commits

Author SHA1 Message Date
Daisy Hollman
8e43c34db9 ci: fail validate when a plugin name is removed without a renames entry
Adds a step to the validate job that diffs plugins[].name against the
PR base and fails if any name disappeared without a corresponding key
in the top-level "renames" map. Prevents the next airwallex-style
plugin-not-found regression.

Part of CC-2871. Depends on the renames map (PR A).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 17:35:10 +00:00
Daisy Hollman
7e287ffe95 feat: add renames map for auto-migration of renamed plugins
Adds a top-level "renames" map to marketplace.json with the four
historical renames (adlc, airwallex, convex-backend, vals) so that
users who installed under the old slug auto-migrate to the new one
once the loader-side support in cci#43997 ships.

Also documents in README.md that plugin `name` is an immutable slug:
use `displayName` for label changes, and if a rename is unavoidable,
add a `renames` entry.

Part of CC-2871.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 17:34:37 +00:00
3 changed files with 40 additions and 0 deletions

View File

@@ -6,6 +6,12 @@
"name": "Anthropic",
"email": "support@anthropic.com"
},
"renames": {
"adlc": "agentforce-adlc",
"airwallex": "airwallex-agentos",
"convex-backend": "convex",
"vals": "valtown"
},
"plugins": [
{
"name": "42crunch-api-security-testing",

View File

@@ -38,6 +38,25 @@ jobs:
with:
fetch-depth: 0
- name: Check for renamed plugins without renames entry
run: |
set -euo pipefail
base="${{ github.event.pull_request.base.sha || 'origin/main' }}"
# Names removed from plugins[] in this diff
removed=$(comm -23 \
<(git show "$base:.claude-plugin/marketplace.json" | jq -r '.plugins[].name' | sort) \
<(jq -r '.plugins[].name' .claude-plugin/marketplace.json | sort))
[ -z "$removed" ] && { echo "No plugin names removed."; exit 0; }
# Renames keys present in HEAD
rename_keys=$(jq -r '.renames // {} | keys[]' .claude-plugin/marketplace.json | sort)
missing=$(comm -23 <(echo "$removed" | sort) <(echo "$rename_keys"))
if [ -n "$missing" ]; then
echo "::error::Plugin name(s) removed without a renames entry: $missing"
echo "Add to .claude-plugin/marketplace.json top-level \"renames\": {\"<old>\": \"<new>\"} (or null if intentionally removed)."
exit 1
fi
echo "All removed names have renames entries."
- uses: anthropics/claude-plugins-community/.github/actions/validate-plugins@426e469f322952061102b286b378c0c9733a0934
with:
marketplace-path: .claude-plugin/marketplace.json

View File

@@ -42,6 +42,21 @@ plugin-name/
└── README.md # Documentation
```
## Plugin names are immutable
The `name` field in a marketplace entry is an **immutable slug**. Once a plugin has been published, its `name` must not change — users have it installed under that slug, and renaming it breaks their install with a `plugin-not-found` error.
- To change how a plugin is labeled in the UI, set or update `displayName` instead.
- If a rename is genuinely unavoidable, add an entry to the top-level `renames` map in `.claude-plugin/marketplace.json` so existing installs auto-migrate:
```json
"renames": {
"old-name": "new-name"
}
```
The Claude Code plugin loader reads this map and transparently rewrites the old slug to the new one on the user's next sync.
## Skill-bundle plugins
When a plugin's source repository ships skills (`SKILL.md` files) without a `.claude-plugin/plugin.json` manifest, the marketplace entry can declare the skills directly using `strict: false` and an explicit `skills` array.