claude.ai web and desktop plugin loaders ignore marketplace 'skills' array — every plugin gets every repo skill (CLI filters correctly)
Preflight Checklist
- [x] I have searched existing issues: this re-files #76448 (auto-closed as stale on 2026-09-07 with no maintainer response). Related: #13344 (original CLI report, fixed ~2.1.206), #15439 and #53948 (why marketplace authors have no workaround).
- [x] I can reproduce it on the current versions listed below.
What's Wrong?
When a marketplace plugin restricts its skill set via the skills array in marketplace.json (all plugins share "source": "./", the repo has a larger skills/ tree), the terminal CLI applies the array at load time, but the loaders used by claude.ai web (server-side packaging into /mnt/skills) and the desktop app's embedded Agent SDK do not. Every plugin from the marketplace serves the entire skills/ tree.
#76448 covered the desktop app (SHA-prefixed namespaces). On claude.ai web the namespaces are the plugin names, so this is not a single-loader bug: two non-CLI loaders ignore the same manifest field.
Observed on claude.ai web with our marketplace:
- All repo skills are mounted under every installed plugin. Installing a plugin that declares one skill mounts every skill in the repo under that plugin's namespace. With six plugins installed we had roughly six times the repo's skill count registered, six byte-identical copies of each (md5-verified).
- The plugin UI contradicts itself. Before install the plugin detail page lists all repo skills. After install it lists only the declared ones, while everything is actually mounted. So the
skillsarray is parsed for the post-install UI but not by the packager, and users cannot see the leak. - Each install is a whole-tree snapshot. A skill merged after plugin A was installed is missing from plugin A but present under every plugin installed later. From the user's side it looks like corruption: a skill absent from its own plugin, present under three unrelated ones.
- Skill ↔
mcpServerspairing breaks. Plugins deliberately bundle different MCP servers (Atlassian vs Figma) for their declared skills. Leaked skills land under plugins that never declared the server they need.
What Should Happen?
Plugin A exposes exactly the skills in its skills array, namespaced plugin-a:<skill>, on every surface (CLI, desktop app, claude.ai web). mcpServers bundled with plugin A apply only to those skills. Same behavior as the CLI after 2.1.206.
Error Messages/Logs
No errors. claude plugin validate on the marketplace passes.
Steps to Reproduce
- Publish a marketplace where two plugins share
"source": "./"and declare disjointskillsarrays (e.g. plugin A → 1 skill, plugin B → 3 skills) from a repo with more than 4 skills. - Add the marketplace on claude.ai web (or the desktop app) and install plugin A only.
- Start a chat and list available skills, or inspect
/mnt/skills. - Compare with the same marketplace in the terminal CLI: the CLI shows 1 skill, the web/desktop session shows all of them.
Claude Model
n/a (plugin packaging, not model behavior)
Is this a regression?
For the CLI it was (#13344, fixed ~2.1.206). For the web and desktop loaders we never observed correct filtering.
Last Working Version
Unknown for web/desktop.
Claude Code Version
CLI 2.1.280 (filters correctly). Claude desktop app (macOS) 2.7032.0. claude.ai web.
Platform
claude.ai web, Claude desktop app (macOS)
Operating System
macOS (Darwin 25.4.0)
Terminal/Shell
zsh (irrelevant; the bug is in non-terminal loaders)
Additional Information
Marketplace setup: private GitHub repo, 18 plugins, every plugin "source": "./", "strict": false, explicit skills array of 1–5 subdirectory paths each, no plugin.json files, no pinned versions; 36 SKILL.md folders in the repo. Full marketplace.json and repro repo available to maintainers on request.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗