Rust 原生 Windows bridge(opencode-pwsh.exe):透明、可靠地将 opencode 的 pwsh 调用接入 PowerShell 7,保证 UTF-8 中文输出。
opencode 底层用 cross-spawn 固定以 pwsh -NoProfile 启动子进程,跳过 profile 使 [console]::OutputEncoding 停留在 GB2312,导致中文输出乱码。此前的 CMD wrapper 方案(opencode-shell.cmd)因 cross-spawn 强制经 cmd.exe /d /s /c 执行而存在命令过滤出错问题(参数含 & | > < 等特殊字符时被二次解析破坏)。
本方案使用 Rust 编写的原生 Windows 可执行文件,不经 cmd.exe,参数以 argv 逐参数透传(Node → exe → pwsh 链路无损),保证中文 UTF-8 输出。
本问题在 opencode 官方仓库(anomalyco/opencode)有多个 issue 跟踪:
- #36985:fix(shell): force UTF-8 console encoding for PowerShell on Windows
- #37915:Garbled text in PowerShell output on non-English Windows
- #23636:fix: PowerShell output encoding for non-ASCII characters on Windows
- #30615:"shell": "pwsh" config not respected, still uses PowerShell 5.1 on Windows
本仓库定位为社区 workaround:不修改 opencode 源码,仅通过 opencode.jsonc 的 shell 配置将子进程启动桥接到本工具,删除该配置行并重启 opencode 即可完全回退,零副作用。官方修复合入上游后,本工具可作为备用方案继续使用。
graph LR
A[opencode<br/>cross-spawn] -->|CreateProcessW<br/>argv 逐参数无损| B[opencode-pwsh.exe<br/>Rust bridge]
B -->|Command 继承句柄<br/>注入 UTF-8 prefix| C[pwsh -NoProfile ...]
C -->|输出字节级透传| A
-
构建 release 版本并部署:
cargo build --release Copy-Item target\release\opencode-pwsh.exe D:\Documents\PowerShell\Scripts\
-
修改
~/.config/opencode/opencode.jsonc,将shell指向新 exe: -
验证:在 opencode 中执行
Write-Output "中文测试:你好世界",输出应无乱码;$PSVersionTable应显示 PowerShell 7。
| 变量 | 默认值 | 说明 |
|---|---|---|
OPENCODE_PWSH |
自动探测 | 指定 pwsh.exe 路径(优先于默认探测路径) |
OPENCODE_PWSH_DEBUG |
关闭 | 设为 1 时向 stderr 输出解析过程日志,默认零输出 |
OPENCODE_PWSH_NO_JOB |
关闭 | 设为 1 时禁用 Job Object(KILL_ON_JOB_CLOSE),用于嵌套 job 冲突场景 |
| 退出码 | 含义 |
|---|---|
| 0-255 | pwsh 原样透传 |
| 1 | wrapper 被信号杀死 |
| 2 | pwsh 路径不存在 |
| 3 | 进程 spawn 失败 |
- Rust 1.96.0(stable,edition 2024),目标平台
x86_64-pc-windows-msvc - 测试:
cargo test(30 单测 + 10 集成,集成测试在无 pwsh 环境自动跳过) - 验收:
pwsh -NoProfile -File scripts/acceptance.ps1(14 项需求验收,15 断言) - 设计决策:D1-D9 见
docs/02-Architecture/系统架构.md(D7 正常退出保留后台 / D8 spawn 后立即 assign / D9 -NoProfile 全变体过滤)
文档与设计决策见 docs/ 目录(需求/架构/契约/ADR/部署/测试)。
{ "shell": "D:/Documents/PowerShell/Scripts/opencode-pwsh.exe" }