Summary
skill search results collapse namespaced skills with the same base name. For example, skills/kynan/commit and skills/will/commit both have name commit but different namespaces. Currently they collapse into one result because dedup uses bare name only.
Problem
SkillSearchItem has no namespace field — only name (extracted as the parent dir of SKILL.md)
- Ranking uses bare
name — two skills with same base name but different namespaces tie
- No dedup logic exists yet, but when added, it would need namespace awareness
Proposal
Follow the pattern from gh PR #13170:
-
Add namespace field to SkillSearchItem — extract from path: skills/<namespace>/<name>/SKILL.md → namespace=<namespace>, name=<name>. For non-namespaced paths (skills/<name>/SKILL.md or <name>/SKILL.md), namespace is empty.
-
Add qualifiedName() helper — returns namespace/name when namespace exists, just name otherwise.
-
Update ranking — use qualifiedName() instead of bare name for score matching. Exact match on qualifiedName → score 3, prefix → 2, includes → 1.
-
Add dedup by repo/qualifiedName — before returning results, deduplicate on repo + qualifiedName key. This prevents the same namespaced skill from appearing twice (e.g. if GitHub returns both skills/kynan/commit/SKILL.md and a re-publisher's copy).
-
Update --json output — include namespace in the JSON fields.
Scope
src/core/skill-search.ts only
- Add
namespace to SkillSearchItem interface
- Update
searchSkills mapping to extract namespace from path
- Add
qualifiedName() helper
- Update
rankItems/score to use qualified name
- Add dedup step before returning
- Update tests
Why
Without this, searching for "commit" would show one result when there are actually multiple distinct skills named "commit" from different authors. The qualified name (namespace/name) is how gh skill handles this, and it's the agentskills.io convention.
Summary
skill searchresults collapse namespaced skills with the same base name. For example,skills/kynan/commitandskills/will/commitboth have namecommitbut different namespaces. Currently they collapse into one result because dedup uses bare name only.Problem
SkillSearchItemhas nonamespacefield — onlyname(extracted as the parent dir ofSKILL.md)name— two skills with same base name but different namespaces tieProposal
Follow the pattern from
ghPR #13170:Add
namespacefield toSkillSearchItem— extract from path:skills/<namespace>/<name>/SKILL.md→ namespace=<namespace>, name=<name>. For non-namespaced paths (skills/<name>/SKILL.mdor<name>/SKILL.md), namespace is empty.Add
qualifiedName()helper — returnsnamespace/namewhen namespace exists, justnameotherwise.Update ranking — use
qualifiedName()instead of barenamefor score matching. Exact match onqualifiedName→ score 3, prefix → 2, includes → 1.Add dedup by
repo/qualifiedName— before returning results, deduplicate onrepo + qualifiedNamekey. This prevents the same namespaced skill from appearing twice (e.g. if GitHub returns bothskills/kynan/commit/SKILL.mdand a re-publisher's copy).Update
--jsonoutput — includenamespacein the JSON fields.Scope
src/core/skill-search.tsonlynamespacetoSkillSearchIteminterfacesearchSkillsmapping to extract namespace from pathqualifiedName()helperrankItems/scoreto use qualified nameWhy
Without this, searching for "commit" would show one result when there are actually multiple distinct skills named "commit" from different authors. The qualified name (
namespace/name) is howgh skillhandles this, and it's the agentskills.io convention.