Plugin SKILL.md scan should be scoped to declared skill paths, not recursive
Problem
Claude Code's harness scans plugin caches for SKILL.md more aggressively than the plugin spec implies. When a plugin ships duplicate SKILL.md files outside the canonical skills/<name>/ path (intentionally or otherwise), each gets registered as the same skill name. The second registration silently drops the description in the available-skills list — keyword auto-trigger breaks but the skill remains invocable via the Skill tool.
Real-world examples
vercel/vercel-pluginshipsskills/<name>/upstream/SKILL.mdfor 10 customized skills (preserved upstream-source copies). Both register; second loses description.JuliusBrussee/cavemanships SKILL.md files inskills/,plugins/caveman/skills/,.cursor/skills/,.windsurf/skills/, plus top-level dirs. Each skill registers 4-5 times.
In one user's setup this dropped descriptions for ~30 skills, blocking auto-routing for many vercel and caveman skills until manual cache cleanup.
Suggested fix
Option A (strict): only scan <plugin_root>/skills/<name>/SKILL.md (one level deep under skills/). Reject anything deeper.
Option B (declare): respect a skills: field in plugin.json listing exact paths; scan only those.
Option C (ignore-list): respect a .claudeignore or skip directories named upstream, .cursor, .windsurf by default.
Option A is cleanest and matches the documented plugin layout.
Detection
find ~/.claude/plugins/cache -name SKILL.md \
| awk '{n=split($0,p,"/"); print p[n-1]}' \
| sort | uniq -c | sort -rn | awk '$1>1'
Same skill name appearing >1 → silent description-drop on second-pass registration.
Workaround
Local SessionStart hook prunes known-bad paths. Cache repopulates on plugin update so the hook re-runs each session.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗