marketplace-dev — Claude Code skill: build a plugin marketplace
Turns a skills repo into a Claude plugin marketplace: generates marketplace.json, adds plugin entries, and moves skills between suites.
npx skills add daymade/claude-code-skills --skill marketplace-dev -a claude-codeWhat marketplace-dev does
The skill walks a repository, finds every SKILL.md under skills/, reads the project metadata, and writes .claude-plugin/marketplace.json. The output is validated with claude plugin validate and installation-tested, so it is ready to open as a PR. Users then install skills with claude plugin marketplace add and get auto-updates.
The workflow runs in phases. Evidence intake first: the current marketplace.json, the repo's own rules, official docs, and — only with explicit approval — past sessions under ~/.claude/projects/<escaped-cwd>/. Then repo analysis, plugin boundary decisions, and manifest generation. Suite consolidation, moving a skill between suites, and renaming while moving have their own path through references/suite_consolidation_workflow.md.
Some schema rules are easy to miss. $schema is rejected by the validator. metadata.homepage is not in the spec even though the validator accepts it silently. strict: false is required when the repo has no plugin.json, and combining it with a plugin.json breaks loading. source: "./" installs the whole repo as the cache, while skills: ["./"] is rejected by the Claude 2.1.x path-escape validator. This is not the tool for a full repo audit or for reconciling caches after a migration.
What it helps with
- generate a spec-valid marketplace.json from a skills repo
- add or update a plugin entry in an existing marketplace
- consolidate standalone skills into a suite
- rename a skill while moving it to another suite
- test plugin installation before opening a PR
Example prompts for the agent
- scan ./my-skills and build a marketplace.json for it
- add the tunnel-doctor skill as its own plugin entry
- move mermaid-tools and docs-lint into the daymade-docs suite
How to install marketplace-dev
1Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill marketplace-dev -a claude-code2Manually: put the files in place
~/.claude/skills/marketplace-dev/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/marketplace-dev/
1Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill marketplace-dev -a codex2Manually: put the files in place
.agents/skills/marketplace-dev/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill marketplace-dev -a cursor2Manually: put the files in place
.cursor/skills/marketplace-dev/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install daymade/claude-code-skills marketplace-dev2Manually: put the files in place
.github/skills/marketplace-dev/SKILL.md1Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill marketplace-dev -a gemini-cli2Platform CLI
gemini skills install https://github.com/daymade/claude-code-skills --path daymade-claude-code/marketplace-devManually: put the files in place
.devin/skills/marketplace-dev/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill marketplace-dev -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about marketplace-dev
How do I install marketplace-dev in Claude?
Run npx skills add daymade/claude-code-skills --skill marketplace-dev -a claude-code. The skill file lands at ~/.claude/skills/marketplace-dev/SKILL.md.
What does marketplace-dev do?
It converts a skills repository into a Claude plugin marketplace: writes .claude-plugin/marketplace.json, adds and updates plugin entries, and migrates skills into or between suites. The result is validated and installation-tested.
How is marketplace-dev different from marketplace-health-check?
marketplace-dev builds and edits the marketplace. marketplace-health-check audits the whole repository across code, docs, security, and manifest integrity. A targeted suite migration does not need that broad audit.
Source text
SKILL.md · MIT
---
name: marketplace-dev
disable-model-invocation: true
description: >-
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).
argument-hint: "[repo-path]"
---
# 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.
## Route the task before editing
| 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](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 |
## Phase 0: Evidence Intake
Before editing an existing marketplace, collect evidence instead of relying on the
default template:
1. Read the current `.claude-plugin/marketplace.json`.
2. Read this repo's marketplace rules (`CLAUDE.md`, README install section, changelog).
3. Read official docs for marketplace/plugin path semantics.
4. Use the current conversation as evidence. Mine earlier local Claude Code sessions
only when the user explicitly asks for or approves that private source.
When that history source is approved, 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):
```bash
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
```bash
# Find every SKILL.md
find <repo-path>/skills -name "SKILL.md" -type f 2>/dev/null
```
For each skill, extract from SKILL.md frontmatter:
- `name` — the skill identifier
- `description` — the ORIGINAL text, do NOT rewrite or translate
### Step 2: Read the repo metadata
- `VERSION` file (if exists) — this becomes `metadata.version`
- `README.md` — understand the project, author info, categories
- `LICENSE` — 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`, `utilities`
- `developer-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:
```text
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.md` frontmatter when the skill path points to a
directory containing `SKILL.md` directly.
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:
1. **`$schema` field is REJECTED** by `claude plugin validate`. Do not include it.
2. **Use the valid `metadata` fields**: `description`, `version`, `pluginRoot`.
`metadata.homepage` does NOT exist — the validator accepts it silently but it's not in the spec.
3. **`metadata.version`** is the marketplace catalog version, NOT individual plugin versions.
It should match the repo's VERSION file (e.g., `"2.3.0"`).
4. **Plugin entry `version`** is independent. For first-time marketplace registration, use `"1.0.0"`.
5. **`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.
6. **`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).
7. **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`.
8. **`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.
### Generate the marketplace.json
Use this template, filling in from the analysis:
```json
{
"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>"]
}
]
}
```
### 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.description` at marketplace level can be a new summary
## Maintaining an existing marketplace
Use 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:
1. **Bump `metadata.version`** — this is the marketplace catalog version.
Follow semver: new plugin = minor bump, breaking change = major bump.
2. **Update `metadata.description`** — append the new skill's summary.
3. **Set new plugin `version` to `"1.0.0"`** — it's new to the marketplace.
4. **Bump existing plugin `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.
5. **Bump existing plugin `version`** when its `source` or `skills` changes.
The installed cache path and component resolution changed even if SKILL.md did not.
6. **Audit `metadata` for invalid fields** — `metadata.homepage` is a common
mistake (not in spec, silently ignored). Remove if found.
### Adding a member skill to an existing suite
Update the following together when adding a member to an existing suite:
1. **The suite's `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.
2. **`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.
3. **`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).
4. **The suite's invocation list** (`/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](https://github.com/daymade/claude-code-skills/blob/main/daymade-skill/skill-creator/SKILL.md)
and [release readiness](https://github.com/daymade/claude-code-skills/blob/main/daymade-skill/skill-creator/references/release-readiness.md)
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.
## Phase 3: Validate
### Step 1: One-shot pre-flight check
Run the bundled validator. It runs the following checks and exits non-zero on
any required failure:
```bash
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 `.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` field
- `Duplicate plugin name` → ensure all names are unique
- `Path contains ".."` → use `./` relative paths only
- `No manifest found in directory` when validating an installed cache path → validate
the marketplace manifest or plugin source, not a `strict: false` cache directory.
### Step 2: Installation test
```bash
# 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:
```bash
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: `SKILL.md` plus its own `scripts/`, `references/`,
`assets/` as applicable.
- Suite plugin cache: only the suite member skill directories and suite-scoped
resources.
- If unrelated skill directories appear, `source` is 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)
```bash
# 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
bash scripts/check_marketplace.sh
```
Pass 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.
### Metadata check
Verify these by reading marketplace.json:
- [ ] `metadata.version` bumped from previous version
- [ ] `metadata.description` mentions all skill categories
- [ ] No `metadata.homepage` (not in spec, silently ignored)
- [ ] No `$schema` field (rejected by validator)
### Per-plugin check
For each plugin entry:
- [ ] `description` matches SKILL.md frontmatter EXACTLY (not rewritten)
- [ ] `version` is `"1.0.0"` for new plugins, bumped for changed plugins
- [ ] `source` points directly at the skill directory (e.g., `"./skill-name"`)
- [ ] Single-skill plugins omit the `skills` field (auto-discovery from `source`)
- [ ] Suite plugins list `skills` paths relative to `source`
- [ ] `strict` is `false` (no plugin.json in repo)
- [ ] `name` is kebab-case, unique across all entries
- [ ] CHANGELOG entry added for every bumped plugin, with the arrow's from/to
matching that bump — **no hook and no CI check requires this**, so it is the
item most often skipped
### Final validation
```bash
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
- Apply these pure-incremental constraints only when adding marketplace support to an
upstream repository. A user-approved suite consolidation necessarily moves existing
skill directories and updates the repository's install documentation; follow the
dedicated consolidation workflow for that route.
- **Pure incremental (new-marketplace route only)**: do NOT modify existing skill files; update README only when needed to expose the new install path
- **Squash commits**: avoid binary bloat in git history from iterative changes
- Only add: `.claude-plugin/marketplace.json`, optionally `scripts/`, optionally update README
### README update (if appropriate)
Add the marketplace install method above existing install instructions:
```markdown
## 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 marketplace support was added
- 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)
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.
## 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.
© daymade · MIT · daymade/claude-code-skills