Skip to content

[BUG] marketplace.json plugins[].skills filter ignored when entries share source root and ship no plugin.json (anthropic-agent-skills repro) #53426

Description

@kreitter

Preflight Checklist

What's Wrong?

When a marketplace.json declares multiple plugin entries that share the same source: "./" (i.e. point at the marketplace root) and use the per-entry skills: array to express disjoint skill subsets, all installed plugins load all skills from the shared skills/ directory, not the declared subset.

This is observable today on the official anthropic-agent-skills marketplace (anthropics/skills). Its marketplace.json declares three plugins from a shared source:

// .claude-plugin/marketplace.json (excerpt)
"plugins": [
  { "name": "document-skills", "source": "./", "skills": ["./skills/xlsx", "./skills/docx", "./skills/pptx", "./skills/pdf"] },           // intended: 4
  { "name": "example-skills",  "source": "./", "skills": ["./skills/algorithmic-art", "./skills/brand-guidelines", /* ... 12 total */] },  // intended: 12
  { "name": "claude-api",      "source": "./", "skills": ["./skills/claude-api"] }                                                          // intended: 1
]

Observed: each installed plugin registers all 17 skills under its own namespace, not its declared subset.

Plugin marketplace.json skills: (intended) Skills actually registered
document-skills@anthropic-agent-skills 4 (xlsx, docx, pptx, pdf) 17
claude-api@anthropic-agent-skills 1 (claude-api) 17

Both /document-skills:claude-api and /claude-api:claude-api exist, with byte-identical SKILL.md content (verified via sha256).

What Should Happen?

The marketplace.json plugins[].skills array should act as a load-time filter, mirroring the per-plugin plugin.json skills field which is documented in plugins-reference.md as:

skills | string|array | Custom skill directories containing <name>/SKILL.md (replaces default skills/)

For document-skills, only xlsx, docx, pptx, pdf should register as /document-skills:* skills. /document-skills:claude-api should not exist.

If the current behavior is by design, then the docs at plugin-marketplaces.md should explicitly state that marketplace.json plugins[].skills is metadata-only (catalog hints, not a runtime filter). Today the field's description ("Custom paths to skill directories containing <name>/SKILL.md") parallels the plugin.json field but omits the "replaces default" parenthetical, leaving the semantics ambiguous.

Steps to Reproduce

  1. Add the marketplace and install both plugins:

    /plugin marketplace add anthropics/skills
    /plugin install document-skills@anthropic-agent-skills
    /plugin install claude-api@anthropic-agent-skills
    
  2. List skills under each namespace:

    /skills | grep -E '^/(document-skills|claude-api):'
    

    Expected: 4 entries under document-skills:, 1 under claude-api:. Observed: 17 under each.

  3. Sha256-verify the duplication is at the file level, not just the namespace:

    for s in algorithmic-art brand-guidelines canvas-design claude-api doc-coauthoring \
             docx frontend-design internal-comms mcp-builder pdf pptx skill-creator \
             slack-gif-creator theme-factory web-artifacts-builder webapp-testing xlsx; do
      a=$(shasum -a 256 ~/.claude/plugins/cache/anthropic-agent-skills/document-skills/*/skills/$s/SKILL.md | awk '{print $1}')
      b=$(shasum -a 256 ~/.claude/plugins/cache/anthropic-agent-skills/claude-api/*/skills/$s/SKILL.md     | awk '{print $1}')
      [ "$a" = "$b" ] && echo "IDENTICAL  $s" || echo "DIVERGENT  $s"
    done

    Result: all 17 byte-identical.

  4. Inspect marketplace.json to confirm the declared subset is not what loaded:

    cat ~/.claude/plugins/cache/anthropic-agent-skills/document-skills/*/.claude-plugin/marketplace.json
    

Root Cause Hypothesis

Per plugins-reference.md "Plugin manifest schema":

The manifest is optional. If omitted, Claude Code auto-discovers components in default locations and derives the plugin name from the directory name.

None of the three plugins in anthropic-agent-skills ship a per-plugin .claude-plugin/plugin.json — only the marketplace's catalog marketplace.json exists. So at install/load time, each plugin appears manifest-less and falls through to auto-discovery, which scans the entire shared skills/ directory.

Two possible fixes:

  • (a) Runtime fix — when constructing a plugin's component set, give precedence to marketplace.json plugins[].skills (and commands, agents, hooks, etc.) when present, the same way per-plugin plugin.json overrides default auto-discovery. This is the more defensible interpretation given the parallel field names.
  • (b) Docs fix + upstream restructure — declare marketplace.json plugins[].skills is metadata-only; reorganize anthropics/skills so each plugin has its own source subdirectory (./document-skills/, ./example-skills/, ./claude-api/) with per-plugin plugin.json files.

Either way addresses the user-visible symptom. (a) is preferable because it preserves the existing marketplace structure and matches the authoring intent expressed in the catalog.

Impact

  • Users who install both document-skills and claude-api from the official Anthropic marketplace get 17 skills loaded twice, doubling their contribution to the in-context skills budget (per skills.md, default 8000 chars or 1% of context window — easy to truncate with ~120 plugin-shipped skills typical of a power-user setup).
  • Surprising namespacing: /document-skills:claude-api exists but is not what document-skills was supposed to ship.
  • Cross-marketplace impact: any third-party marketplace using the shared-source pattern (legitimately, e.g. for monorepo authoring convenience) inherits the same surprise.
  • claude doctor does not surface this kind of in-namespace duplication today; the bug is silent until the user runs sha256 diffs.

Environment

  • Claude Code version: 2.1.119
  • OS: macOS Tahoe (Darwin 25.4.0, arm64)
  • Node: managed via asdf
  • Auth: --dangerously-skip-permissions mode under op run env wrapper
  • Affected marketplace: anthropic-agent-skills (https://github.com/anthropics/skills) at commit 5128e1865d67
  • Affected plugins: document-skills@anthropic-agent-skills, claude-api@anthropic-agent-skills

Related issues

Related upstream

If the resolution path is (b), file a paired issue against anthropics/skills to restructure the marketplace into per-plugin source subdirs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions