Claude-skill-registry managing-marketplaces
Use when working with Claude Code plugin marketplaces - adding, updating, creating, or understanding how marketplace versioning and caching work.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cc-managing-marketplaces" ~/.claude/skills/majiayu000-claude-skill-registry-managing-marketplaces && rm -rf "$T"
skills/data/cc-managing-marketplaces/SKILL.mdManaging Marketplaces
Overview
Plugin marketplaces are catalogs of available plugins. This skill covers how updates work, caching, and versioning.
Key Locations
| Path | Purpose |
|---|---|
| Git clones of remote marketplaces |
| Cached plugin versions |
| Marketplace registry with update timestamps |
Update Mechanism
Marketplace Level (No Version Pin)
Marketplaces track main branch HEAD - no commit pinning:
// known_marketplaces.json { "superpowers-marketplace": { "source": { "source": "git", "url": "https://github.com/obra/superpowers-marketplace.git" }, "lastUpdated": "2026-01-09T15:25:06.447Z", "autoUpdate": true } }
pulls latest on startup/refreshautoUpdate: true
Plugin Level (Version Pinned)
Plugins ARE versioned via the
version field in plugin.json:
~/.claude/plugins/cache/ ├── superpowers-marketplace/ │ └── superpowers/ │ └── 4.0.3/ ← version from plugin.json └── claude-plugins-official/ └── hookify/ └── e30768372b41/ ← commit hash for official plugins
Update Flow
digraph update_flow { rankdir=TB; "Claude Code starts" [shape=box]; "Pull marketplace (git pull main)" [shape=box]; "Read marketplace.json" [shape=box]; "For each enabled plugin" [shape=diamond]; "Check if version cached" [shape=diamond]; "Use cached version" [shape=box]; "Fetch plugin from source" [shape=box]; "Cache at version directory" [shape=box]; "Claude Code starts" -> "Pull marketplace (git pull main)"; "Pull marketplace (git pull main)" -> "Read marketplace.json"; "Read marketplace.json" -> "For each enabled plugin"; "For each enabled plugin" -> "Check if version cached"; "Check if version cached" -> "Use cached version" [label="yes"]; "Check if version cached" -> "Fetch plugin from source" [label="no"]; "Fetch plugin from source" -> "Cache at version directory"; "Cache at version directory" -> "For each enabled plugin"; "Use cached version" -> "For each enabled plugin"; }
Version Pinning Summary
| Layer | Pinned? | Update Mechanism |
|---|---|---|
| Marketplace | No (tracks main HEAD) | or |
| Plugin | Yes (version field) | Bump version in plugin.json → new cache dir |
Commands
# List known marketplaces /plugin marketplace list # Update marketplace metadata /plugin marketplace update <marketplace-name> # Add marketplace /plugin marketplace add owner/repo # GitHub /plugin marketplace add ./local-path # Local /plugin marketplace add https://url.git # Git URL # Remove marketplace (also uninstalls plugins from it) /plugin marketplace remove <marketplace-name>
Local Development
ccd CLI (Recommended)
For marketplaces with a CLI for managing symlinks, use it:
cd ~/projects/my-marketplace pnpm install pnpm ccd link activate # Symlink all plugins (creates cache if needed) pnpm ccd link review # Check status pnpm ccd link deactivate # Remove symlinks
Run
pnpm ccd --help for full documentation including path resolution diagrams.
Workflow:
- Activate symlinks:
(no install required)pnpm ccd link activate - Develop: edit source, restart CC to see changes
- Relink after any
(overwrites symlinks)claude plugin install
Manual Symlink Method
For marketplaces without the CLI, manually replace cache with symlinks.
Key insight: Cache path uses marketplace's
name field from marketplace.json, not the source (GitHub vs local). So ~/.claude/plugins/cache/<name>/... is the same whether you installed from GitHub or local path.
# 1. Clone repo locally (if not already) git clone https://github.com/owner/marketplace ~/projects/my-marketplace # 2. If not installed, add and install (skip if already from GitHub) claude plugin marketplace add ~/projects/my-marketplace claude plugin install my-plugin@my-marketplace # 3. Replace cache with symlink (works for GitHub or local installs) rm -rf ~/.claude/plugins/cache/<marketplace-name>/my-plugin/*/ ln -s ~/projects/my-marketplace/plugins/my-plugin \ ~/.claude/plugins/cache/<marketplace-name>/my-plugin/<version>
Caveats:
- Reinstall overwrites symlink - re-run step 3 after any install
- Session-based reload, not hot-reload in same session
Why this works: CC loads plugins from cache path. Symlink makes cache path point to source. CC follows symlinks transparently.
Standard Method
Official docs show uninstall/reinstall cycle:
/plugin uninstall my-plugin@my-marketplace /plugin install my-plugin@my-marketplace
Enabling Plugins
In project or user
settings.json:
{ "enabledPlugins": { "plugin-name@marketplace-name": true } }
Creating Plugins in a Marketplace
CRITICAL: When creating a new plugin, you MUST do BOTH:
- Create the plugin directory with
plugin.json - Register the plugin in
marketplace.json
marketplace/ ├── .claude-plugin/ │ └── marketplace.json ← MUST add entry here └── plugins/ └── new-plugin/ └── plugin.json ← AND create this
Failure mode: Creating only the directory results in
/doctor errors like:
Plugin new-plugin not found in marketplace marketplace-name
Checklist for New Plugin
- Create
with name, version, descriptionplugins/<name>/plugin.json - Add entry to
plugins array.claude-plugin/marketplace.json - Entry must include:
,name
(e.g.,source
),"./plugins/<name>"description - Run
to verify no plugin errors/doctor
Notes
- Removing a marketplace uninstalls all plugins from it
- Multiple versions can coexist in cache (old versions not auto-cleaned)
timestamp tracks when marketplace was last refreshedlastUpdated