fix(marketplace): restore /plugin install path and namespace per-skill entries#46
Merged
Merged
Conversation
…l entries The /plugin install path on v3.12.2 silently fails. Marketplace add and plugin install commands report success, but no slash command becomes available afterward. This change makes the marketplace plugin path work end-to-end and adds the missing install examples to README. Per-skill entries register zero skills today -------------------------------------------- The eight per-skill entries declare source: ./skills/<name>, but each subdirectory is flat: SKILL.md sits directly under it, with no .claude-plugin/plugin.json and no nested skills/<name>/SKILL.md. Claude Code's default auto-discovery only scans <plugin_root>/skills/<name>/SKILL.md and <plugin_root>/commands/*.md, so the per-skill plugins install without error but register zero skills. Add skills: ["./"] and strict: false to each per-skill entry. strict: false tells Claude Code that the marketplace entry is the full plugin definition, so a separate plugin.json is not required. skills: ["./"] tells the plugin loader that SKILL.md lives at the plugin root rather than in a skills/<name>/ subdirectory. Both fields are documented in the official plugin reference: skills: ["./"] — https://code.claude.com/docs/en/plugins-reference#path-behavior-rules strict: false — https://code.claude.com/docs/en/plugin-marketplaces#strict-mode Bundle entry was removed by mistake ----------------------------------- v3.12.2 removed the waza bundle entry as part of "keep desktop dispatcher out of source root." That commit also removed the repo-root SKILL.md so npx skills add tw93/Waza could discover the eight skills/<name>/ subdirectories without --full-depth. The bundle entry was removed alongside it because it was assumed to only register the dispatcher SKILL.md. That assumption is incorrect. With source: "./", the plugin loader's default auto-discovery walks the plugin root for skills/<name>/SKILL.md, exactly the same eight subdirectories the v3.12.2 layout already exposes. Installing the bundle therefore registers all eight skills under the waza namespace as /waza:think, /waza:check, /waza:hunt, etc. The dispatcher SKILL.md was not load-bearing for this behavior in the current plugin loader. Restore the waza bundle entry with a description that names the eight slash commands it exposes. Per-skill plugin names use a waza- prefix ----------------------------------------- To keep plugin path commands inside the same waza namespace as the bundle, each per-skill entry's plugin name is renamed from <skill> to waza-<skill>: waza-think, waza-check, waza-hunt, waza-design, waza-read, waza-write, waza-learn, waza-health. Installing waza-think@waza exposes /waza-think:think; installing the bundle keeps /waza:think. The skill source directories and SKILL.md frontmatter are unchanged. verify-skills.sh updated ------------------------ The marketplace section is rewritten to support both shapes: - The bundle entry is now required (the one-command install path is part of the project contract); its source is enforced to "./". - Per-skill entries must be named waza-<skill> with source ./skills/<skill>. An empty-suffix guard catches malformed names like 'waza-'. - Version and description cross-checks now key on the skill directory name derived from the plugin name. The README install-command guard for the default npx install command is unchanged. README updated -------------- - Document plugin marketplace install paths in the existing "Install and Update" section: the bundle (/plugin install waza@waza, exposes /waza:think etc.) and per-skill entries (/plugin install waza-think@waza, exposes /waza-think:think). - Add a single-skill install example (--skill think) under both the Claude Code direct slash commands section and the Codex section. What is unchanged ----------------- - The npx skills add CLI install path. It does not read marketplace.json and continues to discover skills/<name>/SKILL.md directly through the v3.12.2 source layout. - skills/<name>/SKILL.md content and frontmatter. - scripts/package-skill.sh and the Claude Desktop ZIP. The single-root SKILL.md is still generated only during make package. - All other verify guards: SKILL.md schema, RESOLVER.md coverage, description length and exclusion-clause checks, root-SKILL.md guard.
1e89537 to
45bb4f9
Compare
tw93
added a commit
that referenced
this pull request
May 6, 2026
fix(marketplace): restore /plugin install path and namespace per-skill entries
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(marketplace): restore /plugin install path and namespace per-skill entries
背景
v3.12.2 之后,
/plugin install这条路径处于静默失败状态:marketplace add 和 plugin install 命令都报告成功,但装完之后没有任何 slash 命令变得可用。这个 PR 让 marketplace plugin 路径完整可用,并在 README 里补全两条主流 host(Claude Code、Codex)的安装范例。这次修复的思路来自 tw93/Kami#16(已合并)。那条 PR 解决了 Kami 单 skill 扁平仓库下同类的
/plugin install路径校验问题:把字段从plugin.json移到 marketplace entry,加上skills: ["./"]+strict: false,让 Anthropic plugin loader 找到 plugin 根的SKILL.md。同一套字段组合在那条 PR 上验证有效;本 PR 把它泛化到 Waza 的多 skill 拓扑(bundle + 8 个 per-skill 入口),并配套处理命名空间和 verify 守卫。现象
命令报告成功,reload 不报错,但
/help里没有任何新增 slash 命令,/think:think、/think都不存在。/plugin install check@waza等其余 7 条 per-skill 入口同样表现。诊断
1. 8 个独立入口装上后注册 0 个 skill
marketplace.json里 8 条 per-skill 入口都声明source: "./skills/<name>",但每个目录都是扁平的:SKILL.md直接在那一层下,下面没有再嵌套.claude-plugin/plugin.json,也没有skills/<name>/SKILL.md。Claude Code 默认的 plugin 自动发现规则只扫
<plugin_root>/skills/<name>/SKILL.md和<plugin_root>/commands/*.md。这些 per-skill plugin 装上后发现机制找不到任何 skill 文件,注册数量为 0。安装命令本身不报错(marketplace 入口存在),但加载阶段静默失败。2. bundle 入口在 v3.12.2 被一并误删
v3.12.2 的 commit
c9851f6 fix: keep desktop dispatcher out of source root一次做了两件事,把它们的对错分开看:(a) 删除仓库根的
SKILL.md:方向正确。仓库根曾经存在的 dispatcher
SKILL.md让npx skills add tw93/Waza默认只扫到根那一层就停。npx CLI 默认找到根 SKILL.md 就装它,不会继续往子目录扫。issue #44 报告的"升级后只剩/waza"就是这条机制的副产品,多 skill 仓库不应该有根 SKILL.md。删掉它(动态生成逻辑搬到package-skill.sh),npx 默认行为回到扫子目录,能正常装出 8 个 skill。(b) 同时删除 marketplace.json 里的
wazabundle 入口:连带误删。release notes 第 4 条原话:
这条结论建立在一个隐含前提上:bundle 入口"只服务于根 dispatcher SKILL.md,根 SKILL.md 没了 bundle 也没用"。
这个前提不准确。bundle 入口的
source: "./"配合仓库已经存在的 8 个skills/<name>/SKILL.md子目录,自动发现机制会注册 8 个 skill 到wazanamespace 下:/waza:think、/waza:check、/waza:hunt、/waza:design、/waza:read、/waza:write、/waza:learn、/waza:health。dispatcher SKILL.md 对这条路径并非必需,bundle 不依赖根 SKILL.md,连带它一起删除是无意之举。release notes 同段说"marketplace installs remain available through individual entries such as
think@waza"也不成立。实测 v3.12.2 主干上think@waza装出来注册 0 skill,就是诊断 1 描述的失败模式。3. 命名空间为什么必须用
waza-<skill>前缀Claude Code plugin 的调用规则是
<plugin_name>:<skill_name>,每个 marketplace 入口的name在 plugin 系统下都是一个独立 plugin,有独立 namespace、独立安装、独立卸载。三种入口的命名结果:name: "waza":装/plugin install waza@waza后,8 个子 skill 落在/waza:namespace 下(/waza:think、/waza:check等)。namespace 直接就叫waza,不需要额外前缀。think、check...):plugin name 直接是think,调用名变成/think:think,同字重复。这种裸名在用户全局 plugin 列表里很容易和其他来源的同名 plugin 撞名(Anthropic 官方插件、其他社区插件都可能用同样的名字)。waza-前缀(waza-think、waza-check...):plugin name 是waza-think,调用名变成/waza-think:think,和 bundle 的/waza:同属 waza 命名空间。用户记一种规则就够,全局也不容易撞名。bundle 不需要前缀因为它本身就叫
waza;per-skill 必须前缀,因为每条都是独立 plugin,需要稳定的命名空间避免冲突。修复
marketplace.jsonname: "waza"、source: "./"的 bundle 入口(version: "3.12.2")name改成waza-<skill>:waza-think、waza-check、waza-hunt、waza-design、waza-read、waza-write、waza-learn、waza-healthskills: ["./"]+strict: falseskills: ["./"]告诉 plugin loader:"SKILL.md 直接位于 plugin 根,而不是skills/<name>/子目录"。strict: false告诉 Claude Code:"marketplace 入口本身就是完整 plugin 定义,不需要额外的plugin.json"。两个字段都是官方 plugin reference 明确支持的写法:
skills: ["./"]— https://code.claude.com/docs/en/plugins-reference#path-behavior-rulesstrict: false— https://code.claude.com/docs/en/plugin-marketplaces#strict-modescripts/verify-skills.shmarketplace 校验段重写以支持新拓扑:
"./"waza-<skill>且 source 必须为./skills/<skill>,空后缀(如name: "waza-")会被独立守卫拦下waza-前缀派生)旧守卫
if name == "waza": fail("MARKETPLACE BUNDLE REMOVED: ...")被删除,它和恢复 bundle 这条主线直接冲突。它原本要防止的(dispatcher 复活进源码树)现在由 bundle 入口 source 锁死为"./"这条新守卫继续兜底。README 默认 npx install 命令的 grep guard 不动。
Makefilesmoke-verify-skillstarget 的两个 fixture 同步更新到新命名拓扑:repo2 fixture 的 plugin name 从ghost改成waza-ghost(让它先通过INVALID PLUGIN NAME守卫,再被MISSING SKILL DIRECTORY: ghost拦下,保持 fixture 原意图),repo3 fixture 找name == 'check'改成name == 'waza-check',对应 grep keyword 改为WRONG SOURCE: waza-check。其他 4 个 fixture(frontmatter / broken link / RESOLVER / pipe)不受拓扑变化影响,保持不动。README.md在已有的
## Install and Update段落里:npx skills add tw93/Waza --skill think -a claude-code -g -y/plugin install think@waza改成 bundle + per-skill 双入口,前面加一句 prose 解释"waza装全部、waza-<skill>装单个"--skill think默认 npx 命令保留 v3.12.2 的形态(不带
--full-depth)。v3.12.2 删除根 SKILL.md 后,npx CLI 默认就会扫到skills/<name>/SKILL.md。本地用npx skills add tw93/Waza -l做 dry-run,带和不带--full-depth两种都报告Found 8 skills。验证
四条安装路径全部端到端测试通过,每条都从 clean uninstall + marketplace remove 起步:
/plugin marketplace add /Users/cyrus/projects/forks/Waza+/plugin install waza@waza/waza:*全部注册/plugin marketplace add qishaoyumu/Waza@fix/plugin-install-path+/plugin install waza@waza/waza:think触发 skill,base dir~/.claude/plugins/cache/waza/waza/3.12.2/skills/think/plugin install waza-think@waza/waza-think:think触发 skill,base dir~/.claude/plugins/cache/waza/waza-think/3.17.0/plugin install waza-check@waza/waza-check:check注册/plugin install think@wazaPlugin "think" not found in marketplace "waza"bash scripts/package-skill.sh重打 + 上传 dist/waza.zipnpx skills add tw93/Waza -a claude-code -g -yFound 8 skillsnpx skills add tw93/Waza --skill think -a claude-code -g -ythink入选/reload-plugins在每条路径下都报 0 error。bash scripts/verify-skills.sh通过(rc=0)。本地闭环测试(16 fixtures,不进 PR)
另起一份 16 case 闭环测试覆盖 PR 涉及的全部 fail 路径:baseline、bundle 缺失/重复/source 错、per-skill 缺前缀/空后缀/source 错位、缺 entry、多余 entry、version/description mismatch、plugin 缺 name/version/description、README 缺默认 npx 命令。15 条 fail case 全部按预期触发对应 keyword,1 条 baseline PASS。
Claude Desktop ZIP 不受 PR 影响的证据
.claude-plugin/整个目录被package-skill.sh的 awk filter 排除,zip 里没有marketplace.json,根 dispatcher SKILL.md 仍然仅在make package时动态生成。不影响的范围
marketplace.json,仍按 v3.12.2 的源码布局扫到skills/<name>/SKILL.mdskills/<name>/SKILL.md内容和 frontmatter:完全未动scripts/package-skill.sh:完全未动Scope
单 commit,分支
fix/plugin-install-path基于 upstream/main HEADa1acdba,0 behind / 1 ahead。