## Why
The manifest-fields tables in both skills used imprecise labels ("CC-only",
"Copilot-only") that conflated two distinct reasons a field appears in only
one manifest: platform constraint (the other tool does not support the field
at all) versus repo convention (both tools support it, but the scaffold places
it in one manifest by design). This caused agents to treat convention
boundaries as hard platform constraints, producing unnecessary errors when
updating manifests for dual-tool repos.
Provenance was also incomplete: sources.md files were missing entries for
sources that had been consulted and were already contributing to SKILL.md
and manifest-fields.md content, making the evidence chain unverifiable.
## Implementation Notes
Field classification now uses three explicit categories — shared, platform
(one tool does not support the field), and convention (both tools support it;
scaffold places it in one manifest by design). The distinction matters because
convention fields may legitimately appear in the other manifest when there is
a deliberate reason; platform fields may not.
New gotchas added to plugin-author: agent files silently ignore hooks,
mcpServers, and permissionMode frontmatter; claude plugin tag --push requires
a clean working tree; --dry-run preview before tagging; --strict flag on
validate. New gotchas in marketplace-author: metadata object as Copilot CLI
canonical location for top-level fields; strict: false for dual-tool plugins;
sha takes precedence over ref for pinning; --strict flag on validate.
tests/ removed from plugin-author because new-plugin.sh has no branching
logic warranting a bats suite at this stage.
## Impact
Skill prompt changes only — no runtime code affected. Agents using these
skills will now correctly distinguish convention from constraint when deciding
which manifest to update for a given field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9.7 KiB
name, description, allowed-tools, metadata
| name | description | allowed-tools | metadata | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| marketplace-author | Use when the user wants to add a plugin to the marketplace ("register my plugin", "add to marketplace", "list plugin X"), remove an entry ("unlist plugin X", "remove from marketplace"), or update an existing entry ("bump the marketplace version", "update the description for Y"). Always updates both .claude-plugin/marketplace.json and .github/plugin/marketplace.json in the same pass. Out of scope: plugin scaffold and configuration — use /plugin-author for that. Does not run `claude plugin marketplace add` or equivalent CLI registration commands — only manages `marketplace.json` entries. | Bash Read Write Edit |
|
Gotchas
- Both marketplace files must be identical after every operation — never update one without the other in the same edit pass.
sourcefor local plugins is a relative path from the marketplace root, not the plugin directory name alone (e.g."./plugins/kyberforge", not"kyberforge").claude plugin validate .must be run from the repo root, not from the plugin directory or the.claude-plugin/directory.- The
{ "source": "github", ... }object form is only for GitHub. For GitLab, Gitea, or any other git host, use{ "source": "git", "url": "https://..." }with a full URL. - Removing an entry from the marketplace does NOT delete the plugin files — it only removes the catalog listing.
versionin a marketplace entry is optional for git-sourced plugins; Claude Code derives version from git tags automatically. Include it when the source is npm or when the user explicitly wants a pinned version visible in the catalog.namemust be kebab-case. Reserved prefixes (anthropic-*,claude-*,agent-skills,official-claude-plugins) are rejected by the validator.- The
plugins[]array order is not semantically significant, but maintain it consistently — add new entries at the end. - For Copilot CLI, the canonical marketplace.json location is
.github/plugin/marketplace.json. Claude Code also reads.claude-plugin/marketplace.json. Both are equivalent; this repo maintains both files in sync. - Copilot CLI places top-level
descriptionandversionunder ametadataobject (metadata.description,metadata.version). Claude Code accepts them at the top level. For dual-tool repos, use themetadataform — it is valid in both tools. - Set
"strict": falseon a plugin entry to allow relaxed schema validation for that entry. This is the right choice for plugins distributed as.claude-plugin/directories that also serve Claude Code — it prevents Copilot CLI from failing on CC-specific fields that are not in the Copilot schema.
Route
Determine which operation applies before touching any file:
- Neither
.claude-plugin/marketplace.jsonnor.github/plugin/marketplace.jsonexist → follow CREATE - Only one file exists → stop and note the mirror is missing; ask the user whether to create the missing mirror from the existing file, or whether this is an error. Do not proceed until both files are present or the user has explicitly directed you to create the missing one.
- Both files exist + plugin name NOT in
plugins[]+ add/register/list intent → follow ADD - Both files exist + plugin name IS in
plugins[]+ remove/unlist/delete intent → follow REMOVE - Both files exist + plugin name IS in
plugins[]+ change/update/bump intent → follow UPDATE - User asks to validate without any add/remove/update intent → follow VALIDATE
- Ambiguous → ask: "Did you mean to add a new plugin entry, update an existing one, or remove one?"
CREATE
Run this flow only when no marketplace.json exists anywhere in the repo.
Prerequisites
Confirm you have:
- Marketplace name (kebab-case, e.g.
my-marketplace) - Owner name (and optionally email)
- Marketplace description (optional but recommended)
- At least one initial plugin entry (name, source, description)
If prerequisites are missing, ask before writing.
Step 1 — Write .claude-plugin/marketplace.json
Create the file with the following structure (fill in the values from prerequisites):
{
"name": "<marketplace-name>",
"owner": { "name": "<owner-name>", "email": "<owner-email>" },
"metadata": {
"description": "<marketplace-description>",
"version": "0.1.0"
},
"plugins": [
{
"name": "<plugin-name>",
"description": "<plugin-description>",
"source": "<source>"
}
]
}
Omit "email" if not provided. Omit "metadata.version" if the user does not want a pinned catalog version. The metadata object is the Copilot CLI canonical location for top-level description and version — Claude Code accepts both metadata-nested and top-level forms; use metadata for dual-tool repos.
Step 2 — Write .github/plugin/marketplace.json
Write identical content to .github/plugin/marketplace.json. These two files must always be identical.
Step 3 — Validate
Follow the VALIDATE flow.
ADD
Run this flow when a plugin name does not yet exist in plugins[] and the intent is to add it.
Prerequisites
Confirm you have:
- Plugin name (kebab-case)
- Plugin description
- Source type and source value (see source type branching below)
- Version (optional; omit for git-sourced plugins)
If you need details on a specific source type shape or per-entry optional fields, read references/manifest-fields.md.
Source type branching
If the user has not specified a source type, ask:
"Which source type does this plugin use?
- Local path — plugin lives in this repo (e.g.
./plugins/<name>)- GitHub — separate GitHub repo (e.g.
owner/repo)- Git URL — any git host via full URL (e.g.
https://gitlab.com/org/repo.git)- npm — distributed on npm (e.g.
@scope/package)"
Source shapes per type:
Local path:
"source": "./plugins/<name>"
GitHub:
"source": { "source": "github", "repo": "owner/repo" }
Add "ref": "<branch-or-tag>" inside the object if the user specifies a branch or tag. Add "sha": "<commit-sha>" if pinning to an exact commit — sha takes precedence over ref when both are present.
Git URL:
"source": { "source": "git", "url": "https://..." }
Add "ref": "<branch-or-tag>" inside the object if specified.
npm:
"source": { "source": "npm", "package": "@scope/pkg", "version": "1.0.0" }
version is required for npm source.
Entry shape
The full entry added to plugins[]:
{
"name": "<name>",
"description": "<description>",
"source": <source per type above>
}
Include "version": "<version>" at the entry level only when the source is npm or when the user explicitly requests a pinned version in the catalog.
Include "strict": false when the plugin is a dual Claude Code / Copilot CLI plugin — this prevents Copilot from rejecting CC-specific fields in the plugin directory.
Step 1 — Read both files
Read .claude-plugin/marketplace.json and .github/plugin/marketplace.json. Verify they are identical. If they differ, stop and report the divergence — do not proceed until the user resolves it.
Step 2 — Add the entry
Append the new entry to the plugins[] array in .claude-plugin/marketplace.json.
Step 3 — Mirror
Apply the identical addition to .github/plugin/marketplace.json in the same edit pass.
Step 4 — Validate
Follow the VALIDATE flow.
REMOVE
Run this flow when an entry exists in plugins[] and the intent is to remove it.
Step 1 — Confirm the target
Read .claude-plugin/marketplace.json. Identify the entry to remove. State the full entry as it currently appears.
Step 2 — HITL gate
State clearly before proceeding:
"I will remove the
<name>entry from both.claude-plugin/marketplace.jsonand.github/plugin/marketplace.json. This does not delete the plugin files. Confirm?"
Do not proceed until the user confirms. If the user says "yes" or equivalent, continue to Step 3.
Step 3 — Remove from both files
Remove the entry from plugins[] in .claude-plugin/marketplace.json.
Apply the identical removal to .github/plugin/marketplace.json in the same edit pass.
Step 4 — Validate
Follow the VALIDATE flow.
UPDATE
Run this flow when an entry exists in plugins[] and the intent is to change one or more fields.
If you need to verify a field name or source type shape, read references/manifest-fields.md.
Step 1 — Read the current entry
Read .claude-plugin/marketplace.json. Show the current state of the target entry so the user can confirm the fields to change.
Step 2 — Apply changes
State which fields will change and to what values, then edit .claude-plugin/marketplace.json.
Apply the identical change to .github/plugin/marketplace.json in the same edit pass.
Step 3 — Validate
Follow the VALIDATE flow.
VALIDATE
Run claude plugin validate . from the repo root:
claude plugin validate .
Add --strict to promote warnings to errors — recommended in CI.
Report the output. If validation fails, describe the specific error and what needs to be fixed. Do not attempt to auto-fix validation errors unless the fix is unambiguous (e.g. a trailing comma that violates JSON syntax); otherwise, describe the fix and ask the user to confirm.
Validation checks include: marketplace.json schema compliance, duplicate plugin names, source path traversal, and version mismatches.