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

@kreitter

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions