Desktop app embedded loader ignores plugin manifest 'skills' array — serves all repo skills under every plugin, SHA-namespaced (CLI 2.1.206 correct)

Status Closed — not planned
Reported on v2.1.206
Maintainer reply None cached
Activity 3 comments · opened Jul 10, 2026 · closed Sep 7, 2026

Summary

When a marketplace plugin's manifest restricts its skill set via a skills array (repo has a larger skills/ subdir; the array should replace the directory scan), the terminal CLI (2.1.206) honors the array correctly, but the Claude desktop app's embedded Agent SDK loader ignores it: it serves ALL skills found in the cached repo under EVERY plugin from that marketplace, and namespaces them by the install version/SHA directory name instead of the plugin name.

This looks like the same regression that was fixed for the CLI in ~2.1.206 (pre-2.1.206 the CLI also installed/served the full scan), still present in the app-embedded loader.

Environment

  • Claude desktop app (macOS): 1.20186.0
  • claude --version (terminal): 2.1.206
  • macOS: Darwin 25.5.0
  • Marketplace: single GitHub repo with source: "./" for both plugins, top-level skills/ dir containing 10 skills; plugin A's manifest lists 7 of them in its skills array, plugin B lists the other 3.

Expected (and observed on terminal CLI 2.1.206)

Session skill list contains exactly:

plugin-a:skill1 ... plugin-a:skill7
plugin-b:skill8 plugin-b:skill9 plugin-b:skill10

claude plugin details also reports 7 and 3 correctly.

Actual (desktop app session, same machine, same installed cache)

All 10 skills are served under BOTH plugins (20 entries), and the namespace prefix is the cache version directory name (first 12 chars of the git commit SHA), not the plugin name:

68dfbd7acf1d:skill1
...all 10...
68dfbd7acf1d:skill1   <- repeated block from the second plugin
...all 10 again...

Notes

  • The installed cache under ~/.claude/plugins/cache/<marketplace>/<plugin>/<sha>/skills/ contains all 10 skill folders for both plugins — expected with source: "./" (whole repo materialized), since the CLI filters at load time. The app loader appears to scan that skills/ dir wholesale instead of applying the manifest array.
  • The SHA-based namespacing (68dfbd7acf1d: instead of plugin-name:) also breaks any workflow that references skills by their documented plugin:skill name.

Impact

Audience-scoped plugin splits (e.g. ops skills vs dev skills from one team repo) silently collapse for desktop-app users: everyone gets every skill, and the namespaced names differ between app and CLI sessions on the same machine.

View original on GitHub ↗

3 Comments

ruslan-taghiyev · 2 months ago

Seeing the same thing on claude.ai web, so this isn't limited to the desktop app's embedded loader. The server-side packaging that builds /mnt/skills for claude.ai chats also ignores the manifest skills array.

Setup: private company repo, 13 plugins, every plugin has "source": "./" and an explicit skills array of subdirectory paths ("strict": false, no plugin.json files, no pinned versions). We verified all of this after re-adding the marketplace from scratch on 2026-07-30.

  1. Installing a plugin that declares a single skill mounts all 23 skills from the repo under that plugin's namespace. With six plugins installed we ended up with ~140 registered skills for a 23-skill repo, six byte-identical copies of each (checked the md5s). One difference from your report: namespaces here are the plugin names, not SHA prefixes.
  1. The plugin pages contradict each other. Before install, the detail page lists all 23 repo skills. After install, the same page shows only the declared ones, even though all 23 are actually mounted. So the skills array is parsed and used for the post-install UI, just not by the packager. Users have no way to notice the leak from the UI.
  1. Each install is a snapshot of the whole tree at that moment. Two skills were merged into the repo on 2026-07-29. The one plugin that declares them was installed earlier and didn't have them; three unrelated plugins installed later all did. From the user side this looks like random corruption: a skill missing from its own plugin while sitting under three foreign namespaces.
  1. The skill-to-MCP-server pairing falls apart. Our plugins intentionally bundle different mcpServers (Atlassian vs Figma) for their declared skills. With skills leaking into every namespace, a skill ends up under plugins that never declared the MCP server it needs. We haven't checked whether mcpServers get unioned the way skills do, but the declared mapping is broken either way.

We haven't re-tested CLI load filtering on this marketplace; all we checked is that claude plugin validate on 2.1.220 passes it. Related:
#13344 (the original CLI report),
#15439 and #53948 (why marketplace authors have no workaround).
Happy to share the full manifest and repro details with maintainers.

github-actions[bot] · 1 month ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

ruslan-taghiyev · 21 days ago

Re-filed as #96319 with the claude.ai web reproduction and current versions (CLI 2.1.280, desktop 2.7032.0), since this was closed as stale without a maintainer response.