[BUG] Skill invocation loads the user-scoped skill even when a same-named project-scoped skill exists in cwd's repo
[BUG] Skill invocation loads the user-scoped skill even when a same-named project-scoped skill exists in cwd's repo
Claude Code version: 2.1.232
Summary
When a user-scoped skill (~/.claude/skills/<name>/SKILL.md) and a project-scoped skill (<repo>/.claude/skills/<name>/SKILL.md) share the same name, invoking the skill from inside that project loads the user-scoped one — even though the working directory is inside the repo that has its own more-specific version.
This contradicts the documented resolution rule for the Skill tool, which states: "Directory-scoped skills are listed with a path prefix... when both scoped and unscoped variants of a name exist, pick the one whose directory contains the files you're working on (most specific wins; unscoped otherwise)." In this case the opposite happened: the unscoped (user-level) variant won even while actively working inside the directory that owns the scoped variant.
Repro steps
- Create
<repo>/.claude/skills/eod-check/SKILL.mdinside a git repo, e.g.~/projects/myrepo. - Separately create
~/.claude/skills/eod-check/SKILL.md(different content, e.g. with a distinguishing string in its body). cd ~/projects/myrepo- Invoke the skill by name (
/eod-check, or ask the assistant to use it). - Observe which file's content gets loaded — check the "Base directory for this skill:" line the harness prints when a skill launches.
Expected
Base directory reported as <repo>/.claude/skills/eod-check — the project-scoped, more specific version, per the documented resolution rule.
Actual
Base directory reported as /Users/<user>/.claude/skills/eod-check — the user-scoped (global) version, despite the session's cwd being inside <repo> and <repo>/.claude/skills/eod-check/SKILL.md existing and being non-empty at the time of invocation.
Impact
A project-scoped skill written specifically to override/specialize a same-named global one is silently never used from inside its own project — the opposite of the documented and presumably intended behavior. In our case the global skill's own body even says "prefer the project-scoped one if it exists," which the assistant had to notice and manually work around by re-reading the project file and re-running its instructions by hand, defeating the purpose of having two scoped variants at all.
Workaround
None automatic. The assistant can detect the mismatch (check test -f <repo>/.claude/skills/<name>/SKILL.md after the global one loads) and manually switch to following the project-scoped file's instructions instead, but this requires the global skill's author to have anticipated the collision and written explicit fallback-check instructions into the global skill's body — ordinary skills won't self-correct.
Additional context
Both files are named eod-check intentionally — the project one is a specialized, repo-specific version of the general-purpose global one, matching the pattern the tool description itself describes ("Directory-scoped skills are listed with a path prefix... most specific wins"). This is exactly the scenario that resolution rule exists for, and it did not apply.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗