Claude-code-skills marketplace-dev
git clone https://github.com/daymade/claude-code-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/daymade/claude-code-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/suites/daymade-claude-code/marketplace-dev" ~/.claude/skills/daymade-claude-code-skills-marketplace-dev && rm -rf "$T"
suites/daymade-claude-code/marketplace-dev/SKILL.mdmarketplace-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 (
, README install section, changelog).CLAUDE.md - 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/*.jsonl
Extract 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/null
For each skill, extract from SKILL.md frontmatter:
— the skill identifiername
— the ORIGINAL text, do NOT rewrite or translatedescription
Step 2: Read the repo metadata
file (if exists) — this becomesVERSIONmetadata.version
— understand the project, author info, categoriesREADME.md
— note the license typeLICENSE- 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-toolsutilities
,developer-tools
,productivity
,documentationsecurity
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
frontmatter when the skill path points to a directory containingSKILL.md
directly.SKILL.md
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, read
references/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:
field is REJECTED by$schema
. Do not include it.claude plugin validate
only has 3 valid fields:metadata
,description
,version
. Nothing else.pluginRoot
does NOT exist — the validator accepts it silently but it's not in the spec.metadata.homepage
is the marketplace catalog version, NOT individual plugin versions. It should match the repo's VERSION file (e.g.,metadata.version
)."2.3.0"- Plugin entry
is independent. For first-time marketplace registration, useversion
."1.0.0"
is required when there's nostrict: false
in the repo. Withplugin.json
, the marketplace entry IS the entire plugin definition. Having BOTHstrict: false
AND astrict: false
with components causes a load failure.plugin.json
defines the installed plugin root. Allsource
paths are relative to that root. Useskills
only when a full repo snapshot is intended. Usesource: "./"
+source: "./path/to/skill"
for a single-skill narrow cache. Useskills: ["./"]
for suite plugins whose cache should contain only the suite members.source: "./suites/<suite>"- 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
vstags
: Both are optional. In the current Claude Code source,keywords
is defined but never consumed in search.keywords
only has a UI effect for the valuetags
(shows a label). Neither affects discovery. The Discover tab searches only"community-managed"
+name
+description
. IncludemarketplaceName
for future-proofing but don't over-invest.keywords
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
at marketplace level can be a new summarymetadata.description
Maintaining an existing marketplace
When adding a new plugin to an existing marketplace.json:
- Bump
— this is the marketplace catalog version. Follow semver: new plugin = minor bump, breaking change = major bump.metadata.version - Update
— append the new skill's summary.metadata.description - Set new plugin
toversion
— it's new to the marketplace."1.0.0" - Bump existing plugin
when its SKILL.md content changes. Claude Code uses version to detect updates — same version = skip update.version - Bump existing plugin
when itsversion
orsource
changes. The installed cache path and component resolution changed even if SKILL.md did not.skills - Audit
for invalid fields —metadata
is a common mistake (not in spec, silently ignored). Remove if found.metadata.homepage
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 repo
What it checks:
| # | Check | Failure means |
|---|---|---|
| 1 | JSON syntax of | file is not parseable JSON |
| 2 | (skipped if CLI missing) | schema-level rejection (e.g. , duplicate names) |
| 3 | + 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:
→ remove theUnrecognized key: "$schema"
field$schema
→ ensure all names are uniqueDuplicate plugin name
→ usePath contains ".."
relative paths only./
when validating an installed cache path → validate the marketplace manifest or plugin source, not aNo manifest found in directory
cache directory.strict: false
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 {} \; | sort
Expected results:
- Single-skill plugin cache:
plus its ownSKILL.md
,scripts/
,references/
as applicable.assets/ - Suite plugin cache: only the suite member skill directories and suite-scoped resources.
- If unrelated skill directories appear,
is too broad.source - 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.sh
All 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:
-
bumped from previous versionmetadata.version -
mentions all skill categoriesmetadata.description - No
(not in spec, silently ignored)metadata.homepage - No
field (rejected by validator)$schema
Per-plugin check
For each plugin entry:
-
matches SKILL.md frontmatter EXACTLY (not rewritten)description -
isversion
for new plugins, bumped for changed plugins"1.0.0" -
starts withsource
and intentionally matches the plugin cache boundary"./" - Every
path starts withskills
and resolves relative to"./"source - If
points directly at a skill root,source
isskills["./"] -
isstrict
(no plugin.json in repo)false -
is kebab-case, unique across all entriesname
Final validation
bash scripts/check_marketplace.sh
Must 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:
, optionally.claude-plugin/marketplace.json
, optionally update READMEscripts/
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 (
passed)claude plugin validate . - Test plan (install commands to verify)
Bundled hooks (optional, auto-activated)
This skill ships two PostToolUse hooks under
hooks/:
— runshooks/post_edit_validate.sh
whenever aclaude plugin validate
file is written or edited.marketplace.json
— warns when ahooks/post_edit_sync_check.sh
is edited but the matching plugin entry inSKILL.md
does not bump itsmarketplace.json
.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.
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.