Codex 在 Windows 下的 Shell 使用体验优化
我在 Windows 上使用 Codex 时,经常看到它执行 Shell 命令失败。最初的处理办法是升级 PowerShell、安装 Microsoft.Coreutils,再把一整段 PowerShell 提示词放进全局 AGENTS.md。这篇文章的旧版也推荐过这套做法。
用了一段时间,我保留了 PowerShell 7,删除了那段提示词,并在 2026 年 9 月卸载了 Coreutils。升级 PowerShell 对我的使用体验有帮助;另外两项没有达到预期,Coreutils 还改变了我手动输入命令时的行为。
目前我的选择是 Windows 原生 Codex 代理配合 PowerShell 7。要改善执行体验,还得分清代理到底用了什么环境、命令经过了哪些解析,以及错误发生在哪一步。
安装 PowerShell 7,注意 Wix 参数
在我的环境里,下面这条安装命令值得保留,尤其是最后的 --installer-type wix:
winget install --id Microsoft.PowerShell --source winget --installer-type wix这个参数决定安装包类型。微软的 PowerShell 安装文档说明,从 PowerShell 7.6.0 的 WinGet 包开始,默认安装 MSIX;指定 wix 才选择 MSI。对我当前的 Windows 开发环境,我优先使用这种安装方式。
这条经验有版本边界。同一份文档说明,PowerShell 7.7 起不再提供 MSI 包,因此不能把“必须指定 Wix”当成适用于所有未来版本的规则。这里记录的是 PowerShell 7.6 的安装选择,也没有据此认定 Codex 完全不能使用 MSIX 安装的 PowerShell。
安装后重新打开 Codex,再让代理执行下面的命令,确认它实际使用的版本和路径:
$PSVersionTable.PSVersion
$PSHOME
Get-Command pwsh | Select-Object Name, Source本次核查中,代理实际运行的是 PowerShell 7.6.5,可执行文件位于 C:\Program Files\PowerShell\7\pwsh.exe。powershell.exe 是 Windows PowerShell 的命令名,pwsh.exe 是 PowerShell 7 的命令名;仅仅安装了新版,不代表每个终端和代理进程都会自动切换过去。
改集成终端,不等于改代理的 Shell
Codex 桌面应用里有两个容易混淆的设置:
Integrated terminal shell决定手动打开的集成终端使用什么 Shell。Agent environment决定代理在 Windows 原生环境还是 WSL 中运行。
官方 Windows 使用说明明确指出,这两个设置相互独立。Windows 原生代理默认通过 PowerShell 执行命令;把集成终端改成 Git Bash,并不会让代理自动改用 Bash。要让代理本身运行在 WSL2 中,需要切换代理环境并重启应用。
我目前的仓库和开发工具都在 Windows 文件系统中,因此继续使用原生代理更符合现有工作方式。如果项目本来就依赖 Linux 工具链,可以考虑 WSL2,并在其中安装运行时和依赖。对于运行在 WSL 中的代理,官方 WSL 指南建议把仓库放在 Linux 主目录下,例如 ~/code/REPO,减少跨文件系统访问带来的性能、符号链接和权限问题。
为什么我卸载了 Coreutils
旧版文章把 Microsoft.Coreutils 简单介绍成补齐 GNU 命令的工具,遗漏了它与 PowerShell 的交互方式。
我安装过的是 Coreutils for Windows 2026.6.16。它是微软维护、基于 uutils/coreutils 等项目构建的 Windows 工具集。安装后,我手动使用 rm 的感觉变了:参数不像原来的 PowerShell 用法,删除依赖目录也明显变慢。但 Codex 平时又很少显式使用这套工具。
同样输入 rm,可能执行不同命令
最初检查命令解析时,得到的结果大致是:
rm Alias Remove-Item
rm.exe Application C:\Program Files\coreutils\bin\rm.exe只看这个结果,很容易以为 rm 一直是 PowerShell 的 Remove-Item 别名。
后来检查本机 PowerShell Profile,发现安装程序写入了约 200 行集成代码。其中的 PSConsoleHostReadLine 会在交互输入完成后,把支持的命令改写为 Coreutils 的 .cmd 入口。输入 rm 时,命令会转向 C:\Program Files\coreutils\cmd\rm.cmd。
Coreutils 官方说明也确认了这层处理:它通过 PSReadLine 集成交互输入,却不删除 PowerShell 的别名,所以 Get-Command、Get-Help 仍可能显示原来的别名或内置命令。
因此,手动在终端输入 rm,与 Codex 通过非交互方式执行 rm,可能走不同的入口。非交互调用不经过这层读行改写时,仍会按 PowerShell 自己的规则解析。这也说明,单凭 Get-Command rm 无法完整判断安装 Coreutils 后的交互行为。
安装工具集没有把 PowerShell 变成 Bash
Coreutils 尝试让通配符和引号更接近 Unix 命令的使用习惯,但 Shell 本身仍然是 PowerShell。官方文档特别提到,PowerShell 的转义符仍是反引号,不能直接照搬 Bash 的反斜杠转义。Windows 的路径、权限与信号机制也有自己的限制。Coreutils 的 Windows 差异说明
对我来说,这增加了辨认成本:同一个短命令,既要看别名,又要看交互输入是否被改写。既然没有依赖这套工具的固定脚本,我选择卸载:
winget uninstall --id Microsoft.Coreutils --exact卸载后需要重新打开 PowerShell,让旧进程中已经加载的函数退出。如果行为仍然异常,再检查 $PROFILE 是否残留 Coreutils 集成代码,保留自己的其他配置。
删除依赖目录变慢是我的实际感受,但这次没有做同等条件下的删除耗时测试,也没有测量卸载后的速度变化。能够确认的是命令入口发生了变化;还不能把“Coreutils 删除目录一定更慢”写成结论。需要这些工具的人可以继续使用,只是我不再把它列为改善 Codex 体验的常规安装步骤。
整段 Shell 提示词为什么没有解决问题
旧版文章引用了 KimiX 的 PowerShell 工具提示词,其中包含 interactive=True、task_id、wait_for_pattern 等参数。这些属于另一套工具接口,不能直接作为当前 Codex 的调用规则。
我曾把这类说明放进全局 AGENTS.md,后来删除了。PowerShell 的语法提示有参考价值,但复制一段其他工具的说明,并不能让 Codex 获得相应接口,也不能替代每次调用前对实际参数的检查。
另一个问题是,执行失败未必与 Shell 语法有关。在一次核查中,Codex 调用了带旧版本目录的 codex.exe,报错提示程序无法识别。找到当前安装目录后,同一项操作就成功了。这类错误需要先验证可执行文件路径,升级 PowerShell 或换成 Bash 都不能修复一个不存在的路径。
把命令写简单,比继续加语法速查表更实用
我把这些执行约束写进了全局 AGENTS.md。下面是实际使用的规则,可以按需合并到自己的规则文件中:
## Windows Shell 执行
- 在 Windows 原生环境中按实际 PowerShell 版本生成命令;执行工具已经使用 PowerShell 时,直接传入命令正文,不额外嵌套 `pwsh -Command`,除非任务明确需要另一个 PowerShell 进程。
- 精确文本搜索优先使用 `rg -n -F`,多个条件使用多个 `-e`;只有需要正则匹配时才编写正则表达式。
- 文件路径使用明确的引号;PowerShell 文件操作遇到含空格、方括号等字符的路径时使用 `-LiteralPath`,避免通配符解析。
- 文件修改优先使用补丁工具;复杂数据处理写成脚本文件执行,避免长篇 `python -c`、`node -e` 和多层 Shell 字符串转义。
- 优先使用已验证的命令入口;路径未知或可能随更新变化时,先用 `Get-Command` 或限定目录查找确认,不猜测或复用未经验证的版本哈希路径。
- 命令失败后先根据报错区分路径、参数、语法与环境问题,再修正对应部分;不要反复增加转义符或切换 Shell 碰运气。这几条约束针对命令构造和排错方式,不包含另一套工具的接口参数。它们仍然需要代理在执行时遵守,不能保证所有命令一次成功。
例如,检查命令路径和读取特殊文件名可以分别这样写:
Get-Command git, bun, pwsh | Select-Object Name, SourceGet-Content -LiteralPath 'app/posts/[slug]/page.tsx'需要调查命令行为不一致时,可以先运行:
Get-Command rm -All | Select-Object Name, CommandType, Source, Definition
$PROFILE | Select-Object *第一条检查别名和可执行程序,第二条列出当前宿主对应的 Profile 路径。若安装过会改写交互输入的工具,还要检查相应 Profile;不能把别名查询结果当成完整的执行记录。
我的日常环境因此保留了 PowerShell 7,移除了没有实际收益的 Coreutils 和整段 Shell 提示词。接下来判断 Codex 的执行体验,要看它是否减少了错误的路径假设和复杂命令拼接,以及失败后能否按报错修正,而不是看环境里装了多少套命令工具。