[Bug] Windows: 插件 hook 命令中的 ${VAR:-默认值} 语法不被展开,经 cmd.exe 原样透传导致 hook 静默失败
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复(#441 同为 Windows 插件 shell hook 范畴,但议题不同:那边是弹出可见 Git Bash 窗口,本条是变量语法不展开导致的静默失败;#444 是 CLI 功能建议,亦不同)
- 我已阅读 CONTRIBUTING.md
问题类别 · Category
其他 · Other(插件 / hook 基础设施)
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
影响体验 · Major —— 对宿主 fail-open 无崩溃,但受影响插件的 hook 每次会话 100% 静默失败,其预期输出完全丢失,且 UI 与落盘日志中均无错误信息可查
复现频率 · Reproducibility
必现 · Always(每一个使用 ${VAR:-默认值} 语法的插件 hook,每一个会话)
问题描述 · Description
插件 hooks.json 中使用 Bash 标准默认值语法 ${CLAUDE_PLUGIN_ROOT:-fallback} 的命令,在 Windows 上会静默失败。完整因果链(源码位于 resources/glm/zcode.cjs,以下函数名为压缩后名称):
- 变量展开正则不支持
:-语法。expandPluginVariables()对命令串做正则替换,正则为:
只匹配/\$\{(CLAUDE_CODE_SESSION_ID|CLAUDE_PLUGIN_DATA|CLAUDE_PLUGIN_ROOT|CLAUDE_PROJECT_DIR|CLAUDE_SESSION_ID|CLAUDE_SKILL_DIR|ZCODE_PLUGIN_DATA|ZCODE_PLUGIN_ROOT|ZCODE_PROJECT_DIR|ZCODE_SESSION_ID|ZCODE_SKILL_DIR)\}/gu${NAME}后紧跟右花括号的精确形式。${CLAUDE_PLUGIN_ROOT:-${extensionPath:-.}}不命中,整段原样透传。 - 环境注入其实做了但用不上。
createPluginEnvOverlay()确实把CLAUDE_PLUGIN_ROOT=<插件根>放进了子进程 env。 - win32 下 shell 模式经 cmd.exe 执行:
AUe()对 win32 返回"cmd";shell 解析为ComSpec ?? "cmd.exe";参数构造为["/d","/s","/c", 命令]加 caret 转义。而 cmd.exe 的变量语法是%VAR%,不会展开${...}。 - 于是 bash 收到的脚本路径是那串字面量 →
No such file or directory→ exit 127。 processHookExecutionResult()的退出码判定:0 成功、2 阻断、其余一律抛 ToolExecutionFailed → 记hook.run.failed(warn 级,durationMs≈90)。- 附带问题:落盘的 warn 日志 context 没有 errorMessage/stderrPreview 字段(虽然
emitHookEvent收到了errorMessage,但logger.warn("Hook execution failed", {...})的 payload 未包含),导致这类失败在 UI 和日志里都不可见,只能靠 durationMs 猜。
影响面:任何面向 Claude Code 生态编写的插件,只要 hook 命令用了 ${CLAUDE_PLUGIN_ROOT:-...} 这类防御性跨平台写法,在 ZCode + Windows 上都会这样静默失败。实测样本:last30days 插件(v3.21.1,marketplace mvanhorn/last30days-skill),其 SessionStart hook 每会话失败一次。
复现步骤 · Steps to reproduce
- Windows 上安装 ZCode 3.10.2,安装任意 hook 命令含
${CLAUDE_PLUGIN_ROOT:-...}语法的插件(如 last30days) - 新建会话
- 查看日志:
~/.zcode/cli/log/zcode-<date>.jsonl中出现hook.run.failed - 手动执行同一脚本(设好
CLAUDE_PLUGIN_ROOT后bash .../check-config.sh)→ exit 0,输出正常,证明脚本本身无问题
期望表现 · Expected behavior
expandPluginVariables()支持${VAR:-default}(至少单层;嵌套默认值可渐进支持),展开后交由 cmd.exe 执行;或- win32 的 shell 模式在检测到 Git Bash 时经 bash 执行(与 #441 的诉求有交集)
- 退一步:落盘的
hook.run.failed日志应包含 errorMessage/stderrPreview,消除静默失败
实际表现 · Actual behavior
- hook 每会话失败一次,exit 127,脚本从未真正执行
- 复现输出(手动模拟 cmd 透传路径):
bash: ${CLAUDE_PLUGIN_ROOT:-${extensionPath:-.}}/hooks/scripts/check-config.sh: No such file or directory - 落盘日志行(context 无 error 字段):
{"level":"warn","event":"hook.run.failed","module":"core.hooks","message":"Hook execution failed","durationMs":90,"context":{"hookEventName":"SessionStart","hookIndex":0,"matcher":"","source":"plugin.last30days@last30days-skill.SessionStart.0.0"}} - 旁证:把缓存中 hooks.json 的命令改成纯
${CLAUDE_PLUGIN_ROOT}(去掉:-回退)后,正则即可命中展开,hook 正常工作 —— 说明展开链路本身是通的,缺的只是:-语法支持
ZCode 版本 · ZCode version
3.10.2.6414
设备 / 系统 · Device / OS
Windows 10 x64(10.0.26200),Git Bash 已安装,bash 在 PATH 上可用
截图 / 录屏 / 日志 · Screenshots / Recordings / Logs
见上方"实际表现"中的复现输出与日志行。zcode.cjs 相关函数:expandPluginVariables(变量正则)、createPluginEnvOverlay(env 注入)、AUe/LMn/FMn/zMn(win32 shell 解析与 cmd 参数构造)、processHookExecutionResult(退出码语义)。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in resources/glm/zcode.cjs by tracing expandPluginVariables(), createPluginEnvOverlay(), the win32 shell path (AUe/LMn/FMn/zMn), and processHookExecutionResult(). Reproduce the Windows hook failure with a ${VAR:-default} command and inspect the emitted hook.run.failed log. Done means the supported behavior is defined and verified, with failures exposing the reported error context.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, javascript
- Domain
- cli, operating-systems, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100