Builds and maintains Claude Code plugin marketplaces: converts a skills repo to spec-valid marketplace.json, adds/updates plugin entries, and migrates skills into or between suites. Use for marketplace.json, plugin distribution, one-click install, or "put these skills in a suite". Not for repo health audits (use marketplace-health-check) or cache reconciliation (use skill-governance).
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
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.
| User intent | Route |
|---|---|
| Create marketplace support for a repo that does not have it | Follow Phases 0–4 below |
| Add or update an ordinary plugin entry | Follow “Maintaining an existing marketplace,” then Phase 3 |
| Consolidate standalone skills into a suite, create a suite from existing skills, move a skill between suites, or rename a skill while moving it | Read references/suite_consolidation_workflow.md completely and follow it instead of the generic Phase 4 constraints |
| Reconcile installed caches after a merged suite migration | Invoke daymade-skill:skill-governance and use its post-migration workflow; do not mutate cache state here |
| Audit the whole repository across code, docs, security, PRs, issues, and manifest integrity | Invoke marketplace-health-check:marketplace-health-check only when the user requested a broad health check; it is not a prerequisite for a targeted suite migration |
Before editing an existing marketplace, collect evidence instead of relying on the default template:
.claude-plugin/marketplace.json.CLAUDE.md, README install section, changelog).When that history source is approved, each project's sessions live under
~/.claude/projects/<escaped-cwd>/:
<session-id>.jsonl<session-id>/subagents/agent-*.jsonlUseful 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.
# 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 translateVERSION file (if exists) — this becomes metadata.versionREADME.md — understand the project, author info, categoriesLICENSE — note the license typegit remote -v)Group skills by function. Categories are freeform strings. Good patterns:
business-diagnostics, content-creation, thinking-tools, utilitiesdeveloper-tools, productivity, documentation, securityAsk the user to confirm categories if grouping is ambiguous.
Claude Code has three separate levels:
marketplace -> plugin -> skillplugin@marketplace./plugin-name:skill-name.SKILL.md frontmatter when the skill path points to a
directory containing SKILL.md directly.Choose each plugin boundary by installation/update/cache intent:
/daymade-docs:mermaid-tools.For detailed source/cache patterns and pitfalls, read
references/cache_and_source_patterns.md before changing source or skills.
Read references/marketplace_schema.md for the complete field reference.
Key rules that are NOT obvious from the docs:
$schema field is REJECTED by claude plugin validate. Do not include it.metadata fields: description, version, pluginRoot.
metadata.homepage does NOT exist — the validator accepts it silently but it's not in the spec.metadata.version is the marketplace catalog version, NOT individual plugin versions.
It should match the repo's VERSION file (e.g., "2.3.0").version is independent. For first-time marketplace registration, use "1.0.0".strict: false is required when there's no plugin.json in the repo.
With strict: false, the marketplace entry IS the entire plugin definition.
Having BOTH strict: false AND a plugin.json with components causes a load failure.source defines the installed plugin root. For single-skill plugins, point
source directly at the skill directory (e.g., "./tunnel-doctor") and omit
skills entirely. For suite plugins, use
source: "./<suite>" with explicit skills array listing subdirectories.
Avoid source: "./" (installs full repo as cache) and skills: ["./"]
(rejected by Claude Code 2.1.x path-escape validator).claude-code-marketplace,
claude-code-plugins, claude-plugins-official, anthropic-marketplace,
anthropic-plugins, agent-skills, knowledge-work-plugins, life-sciences.tags vs keywords: Both are optional. In the current Claude Code source,
keywords is defined but never consumed in search. tags only has a UI effect
for the value "community-managed" (shows a label). Neither affects discovery.
The Discover tab searches only name + description + marketplaceName.
Include keywords for future-proofing but don't over-invest.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": "./<skill-name>",
"strict": false,
"version": "1.0.0",
"category": "<category>",
"keywords": ["<relevant>", "<keywords>"]
}
]
}The name field is what users type after @ in install commands:
claude plugin install dbs@<marketplace-name>
Choose a name that is:
metadata.description at marketplace level can be a new summaryUse this section for ordinary entry additions or metadata updates. For a suite consolidation, source relocation, suite membership transfer, or standalone-to-suite migration, use the dedicated workflow linked in the routing table; those operations have a wider breaking-change and documentation surface than an ordinary entry addition.
When adding a new plugin to an existing marketplace.json:
metadata.version — this is the marketplace catalog version.
Follow semver: new plugin = minor bump, breaking change = major bump.metadata.description — append the new skill's summary.version to "1.0.0" — it's new to the marketplace.version when its SKILL.md content changes.
Claude Code uses version to detect updates — same version = skip update.
Pair the bump with a CHANGELOG entry in the same commit; nothing checks it
for you, and the Pre-flight Checklist is the only checklist item that asks for it.version when its source or skills changes.
The installed cache path and component resolution changed even if SKILL.md did not.metadata for invalid fields — metadata.homepage is a common
mistake (not in spec, silently ignored). Remove if found.Update the following together when adding a member to an existing suite:
skills array in marketplace.json lists the new member
(./skill-name). check_marketplace.py fails when a member dir with a SKILL.md
exists on disk but is absent from the array.metadata.version strictly increases. A new member changes the suite's
layout signature (source + skills); check_version_progression.py rejects any
layout change without a metadata bump above base — rule 5 above (bump the plugin
version) is necessary but not sufficient here.README.md and README.zh-CN.md each gain a ### **skill-name** detail
section. check_doc_skill_lists.py is a required check that extracts every
### **name** heading from both READMEs and fails if a marketplace skill is
missing (and flags the reverse as GHOST)./suite:skill-name) in both READMEs.Every new file must also avoid absolute user paths (/Users/<name>/…) — the PII
guard blocks the push. Write ~/-relative and verify by re-running the real
detector, not by eye.
Follow Skill Creator's versioning contract and release readiness for release bookkeeping and review. Include the CHANGELOG entry with the bump; a passing structural check does not establish that the release is documented.
The checkers take their base differently, and a usage error is not a verdict:
| command | base argument | a usage error gives |
|---|---|---|
check_version_progression.py | --base <ref> --candidate HEAD (see below) | exit 2 — argparse, a refused --candidate-index with nothing staged, or an unreadable base/manifest |
validate_changed_skills.sh | positional <base-ref> (defaults to origin/main) | exit 1, printing base ref '<x>' is unknown here |
check_marketplace.py | none | n/a |
So the code that means "my invocation was wrong" is per-script: exit 2 for
check_version_progression.py, exit 1 for validate_changed_skills.sh. In both cases
the repo was never judged — the same state as not having run it at all. Do not read
either code as "the checker found a problem": across the pair, exit 1 is a usage error
in validate_changed_skills.sh but a real finding in check_version_progression.py
— which is exactly why the printed message, not the number, is what you read.
The post_edit_sync_check hook only catches "SKILL.md edited but plugin version not
bumped". Items 2–4 have no hook, and the CHANGELOG entry has neither a hook nor a
checker — run check_version_progression.py and
check_doc_skill_lists.py locally before pushing rather than discovering them across
CI rounds. Pass --base <base-ref> --candidate HEAD. The script also accepts
--candidate-index, which reads the manifest blob out of the git index and diffs
staged paths only; with nothing staged that blob is HEAD's copy, so it re-verifies the
commit you already have and reports "no regression" about work it never saw. The green
is real about the index and silent about your edit.
The version gate in CI re-runs only when the PR head moves, and it resolves its base to
origin/$BASE_REF at run time. A PR whose base branch has since advanced therefore
keeps the green it earned against the older base, while its version number can already
be a regression against the current one. Re-run the gate against the current
origin/main immediately before merging, not only before pushing, and rebase if it
fails.
Run the bundled validator. It runs the following checks 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 $schema fieldDuplicate plugin name → ensure all names are uniquePath contains ".." → use ./ relative paths onlyNo manifest found in directory when validating an installed cache path → validate
the marketplace manifest or plugin source, not a strict: false cache directory.# 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>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:
SKILL.md plus its own scripts/, references/,
assets/ as applicable.source is too broad.# 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>Run this checklist after every marketplace.json change. Do not skip items.
bash scripts/check_marketplace.shPass the required checks. 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.
Verify these by reading marketplace.json:
metadata.version bumped from previous versionmetadata.description mentions all skill categoriesmetadata.homepage (not in spec, silently ignored)$schema field (rejected by validator)For each plugin entry:
description matches SKILL.md frontmatter EXACTLY (not rewritten)version is "1.0.0" for new plugins, bumped for changed pluginssource points directly at the skill directory (e.g., "./skill-name")skills field (auto-discovery from source)skills paths relative to sourcestrict is false (no plugin.json in repo)name is kebab-case, unique across all entriesbash 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.
.claude-plugin/marketplace.json, optionally scripts/, optionally update READMEAdd 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>
\`\`\`Include:
claude plugin validate . passed)Use the bundled PostToolUse hooks under hooks/:
hooks/post_edit_validate.sh — runs claude plugin validate whenever a
marketplace.json file is written or edited.hooks/post_edit_sync_check.sh — warns when a SKILL.md is edited but the
matching plugin entry in marketplace.json does not bump its version.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 replace
scripts/check_marketplace.sh — always run the pre-flight check before a PR.
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.
daymade/claude-code-skills
0619a95
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.