Superpowers 跨平台钩子:3 个文件让 .sh 脚本在 Windows 上正常跑
【免费下载链接】superpowersAn agentic skills framework & software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers
在 Windows 上,.sh脚本被双击或从 CMD 里调起时,多半不是执行,而是被文本编辑器直接打开;就算环境里有 Git Bash,CMD 也默认不认它。Claude Code 这类工具的 SessionStart 钩子写在 bash 里,落到 Windows 上就经常无声失效。问题出在哪?Superpowers 跨平台钩子方案给出的答案是:别让两套 shell 互相打架,让同一个文件各读各的部分。
一套跨平台钩子方案:3 个文件各管一事
先说结论:Superpowers 用一份 polyglot(双语法)分发脚本同时兼容 CMD 和 bash,加上一个无后缀的钩子脚本和一份配置,共 3 个文件,各负责一件事:
hooks/hooks.json 配置:声明钩子,指向分发器 hooks/run-hook.cmd 分发器:Windows 走 batch,Unix 走 bash hooks/session-start 真正的钩子逻辑(无 .sh 后缀,刻意为之)hooks.json里的 command 写成"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd" session-start,并声明"shell": "bash"——强制走 Git Bash 这条通道,路径整体加引号以防目录含空格。
polyglot 脚本为什么一份文件两头都认
这一节解释方案的底牌:不是写了两份脚本互相调用,而是让一个文件被两种解释器各解析出一段可执行代码。
看分发脚本的关键几行就明白了:
: << 'CMDBLOCK' @echo off :: Windows 侧:按标准路径 -> 32 位路径 -> PATH 三处找 bash.exe, :: 找到就执行带参脚本;找不到则 exit /b 0 静默退出 CMDBLOCK # Unix 侧:从这一行开始执行 exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"一句话拆解:在 bash 里,:是空操作,<< 'CMDBLOCK'把后面整段 CMD 内容当作 here-doc 吞掉,然后直接执行文末的 Unix 逻辑;在 CMD 里,batch 部分逐行执行,exit /b直接结束,根本走不到 Unix 段。
可以把这份文件想成一扇门配两把钥匙:Windows 拿 batch 段开门,Unix 拿脚本段开门,谁也不用等对方。
还有一个细节值得注意:分发器按「C:\Program Files\Git\bin\bash.exe→ 32 位目录 → PATH」的顺序找 bash,三处都没有就退出码 0 静默跳过。钩子只是锦上添花的上下文注入,不该让没装 Git 的 Windows 用户整个插件报错。
上手:从 clone 到验证跑通 4 步
按顺序做,每步都有可观察的验证点。
- 拿到仓库。执行
git clone https://gitcode.com/GitHub_Trending/su/superpowers,进入hooks/目录确认上面 3 个文件都在。打开hooks/hooks.json,核对 command 指向run-hook.cmd且脚本名没有后缀。 - 在 Unix 上验证 bash 分支。Mac 或 Linux 终端里跑
bash hooks/run-hook.cmd session-start。应输出一段含additionalContext字段的 JSON,说明钩子逻辑执行成功。 - 在 Windows 上验证 CMD 分支。在 Git Bash 里执行
cmd /c hooks/run-hook.cmd session-start。无输出、退出码 0 即为通过(钩子逻辑依赖插件环境注入的变量,裸跑只验证分发链路)。 - 跑测试套件兜底。执行
bash tests/hooks/test-session-start.sh,看到连续的[PASS]就说明各平台行为都符合预期。
最容易踩的 3 个坑
这些坑都有明确的现象特征,对号入座即可。
- Windows 上钩子无声失败。现象:不报错、也不执行,Mac 上却正常。原因:分发器在三个位置都没找到 bash.exe,按设计静默退出 0。修复:装 Git for Windows 到标准路径,或让 MSYS2/Cygwin 的 bash 进 PATH。
- 脚本名带了
.sh后缀。现象:钩子命令被提前拦截,或直接报找不到文件。原因:Claude Code 在 Windows 上会给含.sh的命令自动补bash前缀,打乱分发路径。修复:钩子脚本一律无后缀,hooks.json里的引用同步保持session-start而不是session-start.sh。 - matcher 与事件名对不上。现象:钩子压根不触发,日志里查不到记录。原因:不同宿主的事件命名不同,Claude Code 用
startup|clear|compact,Cursor 用sessionStart(仓库里hooks/hooks-cursor.json是后者的变体)。修复:按自己宿主的 matcher 写配置。
一句话收尾
polyglot 分发器 + 无后缀脚本 + 静默降级,让同一份钩子在 Windows 和 Unix 上各走各的通道,互不干扰——跨平台钩子从此不需要维护两套脚本。想深入原理,直接读带完整注释的 hooks/run-hook.cmd,改完跑一遍 tests/hooks/test-session-start.sh;设计背景与取舍的完整记录在 docs/windows/polyglot-hooks.md。
【免费下载链接】superpowersAn agentic skills framework & software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考