[BUG] `/plugin marketplace add <local-path>` registers but plugin installs with 0 skills (workaround: pre-create symlink)
Title
[BUG] `/plugin marketplace add <local-path>` registers but plugin installs with 0 skills (workaround: pre-create symlink)
Body
Bug
When registering a marketplace from a local directory via the slash command:
/plugin marketplace add /Users/me/my-skills-marketplace
Claude Code reports Successfully added marketplace: <name> and creates ~/.claude/plugins/marketplaces/<name>/.... However, after /plugin install <plugin>@<name> and /reload-plugins, the plugin loads with 0 skills (reported as Reloaded: 1 plugin · 0 skills · N agents due to lazy-loaded skills being categorized as agents, but the user-visible result is "the skills do not appear").
The workaround is to pre-create the entry under ~/.claude/plugins/marketplaces/ as a symlink to the local path before running /plugin marketplace add. With the symlink in place, the same add + install + /reload-plugins flow loads all skills correctly.
This breaks the documented onboarding flow for any team that distributes a marketplace as a local directory (cloned via gh repo clone for private repos, for example), which is exactly the use case the CLI is designed to support.
Steps to reproduce
# 1. Clone a private marketplace repo locally
gh repo clone betterme-sandbox/pm-sm-ai-skills-marketplace ~/pm-sm-ai-skills-marketplace
# 2. Start Claude Code
claude
# 3. In the Claude Code REPL:
/plugin marketplace add ~/pm-sm-ai-skills-marketplace
# → "Successfully added marketplace: shared-skills"
# Files appear under ~/.claude/plugins/marketplaces/pm-sm-ai-skills-marketplace/
/plugin
# → Discover → shared-skills → "Install for you" → confirm
/reload-plugins
# → "Reloaded: 1 plugin · 0 skills · 0 agents"
# Skills do NOT appear when invoked: @shared-skills:<skill-name> → not found
Expected
The five skills declared in .claude-plugin/marketplace.json (shared/skills/*/SKILL.md) should be loaded and available for invocation, e.g. @shared-skills:jira-researcher.
Actual
Reloaded: 1 plugin · 0 skills · 0 agents — neither lazy-loaded skills nor anything else is registered. The marketplace files are physically present under ~/.claude/plugins/marketplaces/<name>/, but the loader does not discover them.
Workaround (works reliably)
Replace the auto-created marketplace directory with a symlink to the original local path before running /plugin marketplace add:
# After cloning, BEFORE /plugin marketplace add:
mkdir -p ~/.claude/plugins/marketplaces
ln -sfn ~/pm-sm-ai-skills-marketplace ~/.claude/plugins/marketplaces/pm-sm-ai-skills-marketplace
# Then in Claude Code:
/plugin marketplace add ~/pm-sm-ai-skills-marketplace
/plugin install shared-skills@pm-sm-ai-skills-marketplace
/reload-plugins
# → "Reloaded: 1 plugin · 0 skills · 5 agents" — all 5 skills now available
We've shipped this workaround in our team installer (install.sh creates the symlink before the user runs /plugin marketplace add). See INSTALL.md, step 2.
Hypothesis
The copy step from a local path likely produces a directory whose internal marketplace.json references plugin files via paths that do not resolve in the cache location (e.g., relative paths anchored to the original cwd). A symlink keeps every internal path resolvable to the original tree, which is why the workaround succeeds. Could not confirm without source access.
Why it matters
Distributing a Claude Code marketplace as a local directory is the canonical path for:
- private/internal team marketplaces (cloned via
gh repo clone, sincecurl raw...returns 404 for private repos) - on-premise / air-gapped setups
- offline development
All of these silently fail with 0 skills unless every onboarding doc tells users to manually symlink — which most users will not do, so the result looks like "the marketplace doesn't work" rather than "there is a known workaround".
Environment
| | |
|---|---|
| Claude Code version | 2.1.123 |
| OS | macOS 14.4 (Sonoma, build 23E214) |
| Shell | zsh |
| Marketplace size | 5 skills, ~600 KB |
| Repro frequency | 100% (every fresh install without the symlink workaround) |
Suggested fixes (in order of preference)
- Best: make
/plugin marketplace add <local-path>symlink the directory by default (or behind a--symlinkflag), instead of copying. Local paths are inherently mutable; copy semantics surprise users who edit the source tree and expect changes to reflect. - If symlink-by-default is too aggressive, at minimum fix the copy so the resulting cache structure resolves the same way the source does.
- Print a non-zero exit code or a
[WARN]line whenmarketplace addsucceeds but the loader cannot discover any skills — current "Successfully added" + "0 skills" is silent failure.
Related
- #36655 —
marketplace addnot registered inknown_marketplaces.json(different surface, same family of "registered but not usable") - #52147 — local plugin installation in desktop app (feature request, related)
- #41392 — symlinks inside plugin dirs not dereferenced (related but distinct: that is inside a plugin, this is the marketplace-level path)
Happy to provide more diagnostics (a ~/.claude/plugins/marketplaces/<name>/ listing before/after, debug logs) if helpful.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗