Converts any Claude Code skills repository into an official plugin marketplace. Analyzes existing skills, generates .claude-plugin/marketplace.json conforming to the Anthropic spec, validates with `claude plugin validate`, tests real installation, and creates a PR to the upstream repo. Encodes hard-won anti-patterns from real marketplace development (schema traps, version semantics, description pitfalls). Use when the user mentions: marketplace, plugin support, one-click install, marketplace.json, plugin distribution, auto-update, or wants a skills repo installable via `claude plugin install`. Also trigger when the user has a skills repo and asks about packaging, distribution, or making it installable.
Resources
4Install
npx skillscat add daymade/claude-code-skills/marketplace-dev Install via the SkillsCat registry.
marketplace-dev
Convert a Claude Code skills repository into an official plugin marketplace so users
can install skills via claude plugin marketplace add and get auto-updates.
Input: a repo with skills/ directories containing SKILL.md files.
Output: .claude-plugin/marketplace.json + validated + installation-tested + PR-ready.
Phase 0: Evidence Intake
Before editing an existing marketplace, collect evidence instead of relying on the
default template:
- Read the current
.claude-plugin/marketplace.json. - Read this repo's marketplace rules (
CLAUDE.md, README install section, changelog). - Read official docs for marketplace/plugin path semantics.
- If refining from prior failures, mine local Claude Code session history.
Each project's sessions live under ~/.claude/projects/<escaped-cwd>/:
- Top-level files:
<session-id>.jsonl - Subagent transcripts:
<session-id>/subagents/agent-*.jsonl
Useful search patterns (adjust keywords to the failure you are debugging):
grep -lc "marketplace.json\|claude plugin validate\|claude plugin install" \
~/.claude/projects/<escaped-cwd>/*.jsonl
grep -lc "Unrecognized key\|Plugin not found\|No manifest found\|Duplicate plugin" \
~/.claude/projects/<escaped-cwd>/*.jsonl \
~/.claude/projects/<escaped-cwd>/*/subagents/*.jsonlExtract lessons as evidence-backed rules: command attempted, observed output, root
cause, final working command/config. Do not encode guesses from memory.
Phase 1: Analyze the Target Repo
Step 1: Discover all skills
# Find every SKILL.md
find <repo-path>/skills -name "SKILL.md" -type f 2>/dev/nullFor each skill, extract from SKILL.md frontmatter:
name— the skill identifierdescription— the ORIGINAL text, do NOT rewrite or translate
Step 2: Read the repo metadata
VERSIONfile (if exists) — this becomesmetadata.versionREADME.md— understand the project, author info, categoriesLICENSE— note the license type- Git remotes — identify upstream vs fork (
git remote -v)
Step 3: Determine categories
Group skills by function. Categories are freeform strings. Good patterns:
business-diagnostics,content-creation,thinking-tools,utilitiesdeveloper-tools,productivity,documentation,security
Ask the user to confirm categories if grouping is ambiguous.
Step 4: Choose plugin boundaries
Claude Code has three separate levels:
marketplace -> plugin -> skill- Marketplace name is used for install identity:
plugin@marketplace. - Plugin name is the slash namespace:
/plugin-name:skill-name. - Skill name comes from
SKILL.mdfrontmatter when the skill path points to a
directory containingSKILL.mddirectly.
Choose each plugin boundary by installation/update/cache intent:
- Single-skill plugin: use when the skill should install, update, and roll back
independently with a narrow cache. - Suite plugin: use when related skills should share one namespace and one
install command, for example/daymade-docs:mermaid-tools.
For detailed source/cache patterns and pitfalls, readreferences/cache_and_source_patterns.md before changing source or skills.
Phase 2: Create marketplace.json
The official schema (memorize this)
Read references/marketplace_schema.md for the complete field reference.
Key rules that are NOT obvious from the docs:
$schemafield is REJECTED byclaude plugin validate. Do not include it.metadataonly has 3 valid fields:description,version,pluginRoot. Nothing else.metadata.homepagedoes NOT exist — the validator accepts it silently but it's not in the spec.metadata.versionis the marketplace catalog version, NOT individual plugin versions.
It should match the repo's VERSION file (e.g.,"2.3.0").- Plugin entry
versionis independent. For first-time marketplace registration, use"1.0.0". strict: falseis required when there's noplugin.jsonin the repo.
Withstrict: false, the marketplace entry IS the entire plugin definition.
Having BOTHstrict: falseAND aplugin.jsonwith components causes a load failure.sourcedefines the installed plugin root. Allskillspaths are relative
to that root. Usesource: "./"only when a full repo snapshot is intended.
Usesource: "./path/to/skill"+skills: ["./"]for a single-skill narrow
cache. Usesource: "./<suite>"for suite plugins whose cache should
contain only the suite members.- Reserved marketplace names that CANNOT be used:
claude-code-marketplace,claude-code-plugins,claude-plugins-official,anthropic-marketplace,anthropic-plugins,agent-skills,knowledge-work-plugins,life-sciences. tagsvskeywords: Both are optional. In the current Claude Code source,keywordsis defined but never consumed in search.tagsonly has a UI effect
for the value"community-managed"(shows a label). Neither affects discovery.
The Discover tab searches onlyname+description+marketplaceName.
Includekeywordsfor future-proofing but don't over-invest.
Generate the marketplace.json
Use this template, filling in from the analysis:
{
"name": "<marketplace-name>",
"owner": {
"name": "<github-org-or-username>"
},
"metadata": {
"description": "<one-line description of the marketplace>",
"version": "<from-VERSION-file-or-1.0.0>"
},
"plugins": [
{
"name": "<skill-name>",
"description": "<EXACT text from SKILL.md frontmatter, do NOT rewrite>",
"source": "./",
"strict": false,
"version": "1.0.0",
"category": "<category>",
"keywords": ["<relevant>", "<keywords>"],
"skills": ["./skills/<skill-name>"]
}
]
}Naming the marketplace
The name field is what users type after @ in install commands:claude plugin install dbs@<marketplace-name>
Choose a name that is:
- Short and memorable
- kebab-case (lowercase, hyphens only)
- Related to the project identity, not generic
Description rules
- Use the ORIGINAL description from each SKILL.md frontmatter
- Do NOT translate, embellish, or "improve" descriptions
- If the repo's audience is Chinese, keep descriptions in Chinese
- If bilingual, use the first language in the SKILL.md description field
- The
metadata.descriptionat marketplace level can be a new summary
Maintaining an existing marketplace
When adding a new plugin to an existing marketplace.json:
- Bump
metadata.version— this is the marketplace catalog version.
Follow semver: new plugin = minor bump, breaking change = major bump. - Update
metadata.description— append the new skill's summary. - Set new plugin
versionto"1.0.0"— it's new to the marketplace. - Bump existing plugin
versionwhen its SKILL.md content changes.
Claude Code uses version to detect updates — same version = skip update. - Bump existing plugin
versionwhen itssourceorskillschanges.
The installed cache path and component resolution changed even if SKILL.md did not. - Audit
metadatafor invalid fields —metadata.homepageis a common
mistake (not in spec, silently ignored). Remove if found.
Phase 3: Validate
Step 1: One-shot pre-flight check
Run the bundled validator. It runs four checks in sequence and exits non-zero on
any required failure:
bash scripts/check_marketplace.sh # validates current repo
bash scripts/check_marketplace.sh /path # validates a target repoWhat it checks:
| # | Check | Failure means |
|---|---|---|
| 1 | JSON syntax of .claude-plugin/marketplace.json |
file is not parseable JSON |
| 2 | claude plugin validate . (skipped if claude CLI missing) |
schema-level rejection (e.g. Unrecognized key: "$schema", duplicate names) |
| 3 | source + skills resolution for every plugin entry |
a plugin entry points to a SKILL.md that does not exist on disk |
| 4 | Reverse sync (disk → manifest) | WARN-only: a SKILL.md on disk is not registered in any plugin entry |
Common schema failures and fixes:
Unrecognized key: "$schema"→ remove the$schemafieldDuplicate plugin name→ ensure all names are uniquePath contains ".."→ use./relative paths onlyNo manifest found in directorywhen validating an installed cache path → validate
the marketplace manifest or plugin source, not astrict: falsecache directory.
Step 2: Installation test
# Add as local marketplace
claude plugin marketplace add .
# Install a plugin
claude plugin install <plugin-name>@<marketplace-name>
# Verify it appears
claude plugin list | grep <plugin-name>
# Check for updates (should say "already at latest")
claude plugin update <plugin-name>@<marketplace-name>
# Clean up
claude plugin uninstall <plugin-name>@<marketplace-name>
claude plugin marketplace remove <marketplace-name>Step 3: Cache footprint test
After installation or update, inspect the actual cache. This is the only way to
confirm source produced the intended snapshot:
PLUGIN=<plugin-name>
MARKET=<marketplace-name>
CACHE=$(jq -r --arg id "$PLUGIN@$MARKET" '.plugins[$id][0].installPath' ~/.claude/plugins/installed_plugins.json)
find "$CACHE" -maxdepth 1 -mindepth 1 -exec basename {} \; | sortExpected results:
- Single-skill plugin cache:
SKILL.mdplus its ownscripts/,references/,assets/as applicable. - Suite plugin cache: only the suite member skill directories and suite-scoped
resources. - If unrelated skill directories appear,
sourceis too broad. - If cache entries are symlinks, the plugin is not self-contained; use canonical
source directories instead of symlink farms.
Step 4: GitHub installation test (if pushed)
# Test from GitHub (requires the branch to be pushed)
claude plugin marketplace add <github-user>/<repo>
claude plugin install <plugin-name>@<marketplace-name>
# Verify
claude plugin list | grep <plugin-name>
# Clean up
claude plugin uninstall <plugin-name>@<marketplace-name>
claude plugin marketplace remove <marketplace-name>Pre-flight Checklist (MUST pass before proceeding to PR)
Run this checklist after every marketplace.json change. Do not skip items.
Automated checks
bash scripts/check_marketplace.shAll four checks must pass. Treat the reverse-sync WARN as a real signal: an
unregistered SKILL.md on disk is almost always either an accidentally-dropped
skill you forgot to register, or dead code that should be removed.
Metadata check
Verify these by reading marketplace.json:
-
metadata.versionbumped from previous version -
metadata.descriptionmentions all skill categories - No
metadata.homepage(not in spec, silently ignored) - No
$schemafield (rejected by validator)
Per-plugin check
For each plugin entry:
-
descriptionmatches SKILL.md frontmatter EXACTLY (not rewritten) -
versionis"1.0.0"for new plugins, bumped for changed plugins -
sourcestarts with"./"and intentionally matches the plugin cache boundary - Every
skillspath starts with"./"and resolves relative tosource - If
sourcepoints directly at a skill root,skillsis["./"] -
strictisfalse(no plugin.json in repo) -
nameis kebab-case, unique across all entries
Final validation
bash scripts/check_marketplace.shMust print RESULT: PASSED before creating a PR. A WARN [4/4] is acceptable
only when you have consciously decided to leave a SKILL.md unregistered.
Phase 4: Create PR
Principles
- Pure incremental: do NOT modify any existing files (skills, README, etc.)
- Squash commits: avoid binary bloat in git history from iterative changes
- Only add:
.claude-plugin/marketplace.json, optionallyscripts/, optionally update README
README update (if appropriate)
Add the marketplace install method above existing install instructions:
## Install
 <!-- only if demo exists -->
**Claude Code plugin marketplace (one-click install, auto-update):**
\`\`\`bash
claude plugin marketplace add <owner>/<repo>
claude plugin install <skill>@<marketplace-name>
\`\`\`PR description template
Include:
- What was added (marketplace.json with N skills, M categories)
- Install commands users will use after merge
- Design decisions (pure incremental, original descriptions, etc.)
- Validation evidence (
claude plugin validate .passed) - Test plan (install commands to verify)
Bundled hooks (optional, auto-activated)
This skill ships two PostToolUse hooks under hooks/:
hooks/post_edit_validate.sh— runsclaude plugin validatewhenever amarketplace.jsonfile is written or edited.hooks/post_edit_sync_check.sh— warns when aSKILL.mdis edited but the
matching plugin entry inmarketplace.jsondoes not bump itsversion.
Both hooks are declared in this plugin's own manifest entry (plugins[].hooks),
so they activate automatically when the plugin is enabled in a Claude Code
session. No manual settings.json edit is required. To disable them, remove
the hooks block from this plugin entry in the user's installed copy or use/plugin disable marketplace-dev (they take effect only when the plugin is
enabled).
These hooks are editor-time guardrails. They do NOT replacescripts/check_marketplace.sh — always run the pre-flight check before a PR.
Anti-Patterns (things that went wrong and how to fix them)
Read references/anti_patterns.md for the full list of pitfalls discovered during
real marketplace development. These are NOT theoretical — every one was encountered
and debugged in production.