调试一个本没有 bug 的 hook 是一种怎样的体验?上周,一位开发者在使用 Anthropic 发布的命令行 AI 工具 Claude Code 时,就经历了这样一场长达一小时的噩梦。他在 Windows 环境下编写了一个 UserPromptSubmit 钩子(hook)—— 一个用 PowerShell 编写的关键词路由脚本。该脚本旨在读取用户输入的提示词,若发现“mcp”或“코드 리뷰”(代码评审)等关键词,就自动注入提示信息以引导 Claude 启用相应的技能。由于其有一半的提示词是用韩文书写的,因此正则表达式中包含了大量的韩文字符。
奇怪的是,英文规则运行得极为完美,但韩文规则却彻底“装死”:没有匹配成功,没有抛出错误,也没有任何日志输出。脚本正常退出,退出码为 0,却对一半的韩文输入毫无反应。在尝试了各种常规调试方法(如打印 Prompt、在控制台测试正则、反复检查 JSON 解析、插入 Write-Host 调试信息)均无果后,作者终于发现了罪魁祸首——文件编码。
原来,Windows 默认的 PowerShell 5.1(即 powershell.exe,而非跨平台的 pwsh)在读取 .ps1 文件时,默认并不假定其为 UTF-8 编码。如果文件没有字节顺序标记(BOM),它就会回退到系统原有的旧代码页(Legacy Code Page)。因此,尽管编辑器将脚本保存为纯 UTF-8,但在 PowerShell 解析时,韩文部分已经被解释成了乱码(Mojibake),自然无法匹配任何真实的韩文输入。因为这是在解析阶段发生的错误,所以不会触发任何运行时报错。
解决办法其实非常简单:使用 PowerShell 脚本为该路由文件强行添加 UTF-8 BOM 头。你可以使用以下函数:
function Add-Bom($path) {
$text = [System.IO.File]::ReadAllText($path)
$enc = New-Object System.Text.UTF8Encoding $true
[System.IO.File]::WriteAllText($path, $text, $enc)
}
Add-Bom "$env:USERPROFILE\.claude\skill-router.ps1"重新保存后,一切便恢复正常。纯 ASCII 脚本不会受此影响,这也是为什么网上大多数基于 macOS Bash 的示例都能正常运行,而 Windows 用户却频频踩坑的原因。
经历了这次折磨后,作者顺便整理并优化了他的 Claude Code 配置,并分享了几个非常有价值的实用工具:首先是一个 PreToolUse 安全钩子,当检测到 Claude 试图运行 rm -rf /、DROP TABLE、git push --force 或 taskkill 等高危破坏性命令时,会强行注入确认提示;其次是将之前的 400 行个人路由规则重构为一个通用的路由模板;最后是一个小型回归测试工具,以确保新增规则不会悄悄破坏已有规则。
随着 Claude Code 等本地 AI 协同工具的兴起,开发者与 AI Agent 之间的交互正从传统的 Chat 走向深度嵌入式的工作流。本文所揭示的“编码静默失败”看似是个经典的 Windows 兼容性 Bug,但在 AI Agent 时代却代表了一种新型的安全与可用性隐患:Agent 对环境的感知完全依赖于底层系统的管道、I/O 编码及提示词上下文。任何微小的字符集解析偏差,都可能导致 Agent “失聪”或“误判”。这就要求我们在构建 AI Agent 生态时,必须将“防御性编程”理念升级为“防御性 Agent 交互”,通过在核心生命周期(如 PreToolUse、PostToolUse)中部署鲁棒的安全拦截器(Safety Hooks),来构建人机协作的最后一道安全防护网,确保 Agent 在复杂的真实宿主环境中既高效又可控。