<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>李的上下文</title>
    <link>https://www.licontext.com</link>
    <description>在真实项目中记录技术实践、项目复盘、读书总结与长期思考。</description>
    <language>zh-CN</language>
    <atom:link href="https://www.licontext.com/feed.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Codex 在 Windows 原生环境、WSL 与 PowerShell 编码问题排查记录</title>
      <link>https://www.licontext.com/codex-windows-wsl-powershell-encoding-notes</link>
      <guid isPermaLink="true">https://www.licontext.com/codex-windows-wsl-powershell-encoding-notes</guid>
      <description>## 背景 在 Codex 桌面端中，我最初遇到的是 Windows 原生环境下的编码风险，而不是 Codex 本身的能力问题。进一步分析后，我意识到乱码更可能来自本地编译和终端执行路径：当前系统是 Windows，当 Codex 通过 PowerShell 终端执行命令时，Codex 和现代工具链通常倾向于使用 UT</description>
      <content:encoded><![CDATA[<h2>背景</h2><p>在 Codex 桌面端中，Windows原生环境下，Codex在运行终端命令时使用本地powershell出现文件输出乱码，修复时导致文件损坏。</p><p>经过排查发现这更可能来自本地编译和终端执行路径：系统是 Windows，当 Codex 通过 PowerShell 终端执行命令时，Codex 和现代工具链通常倾向于使用 UTF-8，但 Windows PowerShell 或部分 Windows 命令链路可能仍然使用 GBK / UTF-16 / ANSI 等编码。这种不一致会导致中文输出乱码；更严重时，如果文件被再次读写，可能造成源码文件编码变化、BOM 变化，甚至文件内容损坏。</p><p>基于这个判断，我尝试将 Codex 设置中的智能体运行环境从 Windows 原生环境切换到 WSL，希望借助 Linux 用户空间和更一致的 UTF-8 工具链来规避 Windows PowerShell 编码问题。</p><p>切换后出现两个现象：</p><ul class="tight" data-tight="true"><li><p>历史对话 Session 看起来全部丢失。</p></li><li><p>智能体无法正常对话或执行任务。</p></li></ul><p>切回 Windows 原生环境后，历史 Session 和对话能力恢复正常。随后我继续沿着编码方向排查，确认真正需要处理的是 Windows 原生环境下 PowerShell 运行时和文件写入编码策略。</p><p>本文记录这两个问题的排查、处理方法和最终结论。</p><h2>一、WSL 切换后历史 Session 消失的问题</h2><h3>现象</h3><p>在 Codex 设置中将智能体运行环境从 Windows 原生环境切换到 WSL 后：</p><ul class="tight" data-tight="true"><li><p>历史对话不可见。</p></li><li><p>智能体无法正常使用。</p></li><li><p>切回 Windows 原生环境后，历史对话恢复。</p></li></ul><h3>排查</h3><p>首先检查 WSL 本体版本：</p><pre><code class="language-powershell">wsl --version</code></pre><p>检查结果显示 WSL 本体版本较新：</p><pre><code class="language-text">WSL version: 2.7.3.0
Kernel version: 6.6.114.1-1</code></pre><p>这说明问题并不是 WSL 本体版本过低。</p><p>继续检查 WSL 发行版：</p><pre><code class="language-powershell">wsl -l -v</code></pre><p>当时返回的信息表明：系统中没有可用的 Linux 发行版。也就是说，虽然 Docker 安装过程中启用了 WSL 相关组件，但并没有配置好一个可供 Codex 作为运行环境使用的 Linux 发行版。</p><h3>原因</h3><p>WSL 本体和 Linux 发行版不是一回事。</p><ul class="tight" data-tight="true"><li><p>WSL 本体：Windows 提供的 Linux 子系统能力。</p></li><li><p>Linux 发行版：Ubuntu、Debian 等实际的 Linux 用户空间环境。</p></li></ul><p>Docker 安装时可能会启用 WSL2，但这不等价于已经有一个适合 Codex 使用的默认 Linux 发行版。</p><p>同时，Codex 的历史 Session 在 Windows 原生环境和 WSL 环境之间大概率是隔离的：</p><ul class="tight" data-tight="true"><li><p>Windows 原生环境使用 Windows 用户目录和本地状态。</p></li><li><p>WSL 环境使用 Linux 发行版中的 <code>/home/&lt;user&gt;</code> 和对应状态。</p></li></ul><p>因此，切换到 WSL 后历史 Session 看起来为空，并不代表 Windows 原生环境下的历史被删除。切回 Windows 后历史恢复，就是这一点的直接证据。</p><h3>处理建议</h3><p>如果确实需要使用 WSL，可以安装并设置默认发行版：</p><pre><code class="language-powershell">wsl --list --online
wsl --install -d Ubuntu-24.04
wsl -l -v
wsl --set-default Ubuntu-24.04</code></pre><p>首次进入 Ubuntu 后，安装基础工具：</p><pre><code class="language-bash">sudo apt update
sudo apt install -y git curl ca-certificates build-essential</code></pre><p>如果非常依赖已有历史 Session，建议继续使用 Windows 原生环境；只在确实需要 Linux 工具链时切换到 WSL。</p><h2>二、Windows PowerShell 5.1 的编码风险</h2><h3>现象</h3><p>在 Windows 原生环境中运行 Codex 时，PowerShell 命令可能出现：</p><ul class="tight" data-tight="true"><li><p>中文输出乱码。</p></li><li><p>PowerShell 管道输出编码不一致。</p></li><li><p>文件再次写入后编码被改成 GBK/ANSI。</p></li><li><p>UTF-8 源码文件被破坏。</p></li></ul><h3>初始环境</h3><p>检查当前 PowerShell 版本和编码：</p><pre><code class="language-powershell">$PSVersionTable.PSVersion
[Console]::InputEncoding
[Console]::OutputEncoding
$OutputEncoding
chcp</code></pre><p>最初环境是 Windows PowerShell 5.1：</p><pre><code class="language-text">Major: 5
Minor: 1</code></pre><p>同时活动代码页为：</p><pre><code class="language-text">Active code page: 936</code></pre><p><code>936</code> 是简体中文 GBK 代码页。这个组合很容易导致现代 UTF-8 工具链出现乱码和文件编码问题。</p><p>此外，PowerShell profile 中还有一行：</p><pre><code class="language-powershell">fnm env --use-on-cd | Out-String | Invoke-Expression</code></pre><p>但当前环境中找不到 <code>fnm</code>，导致每次启动 shell 时都会输出报错，并且报错本身也可能出现乱码。</p><h3>第一阶段处理：修复 PowerShell profile</h3><p>对 Windows PowerShell 5.1 的 profile 做了 UTF-8 初始化：</p><pre><code class="language-powershell">chcp 65001 &gt; $null
</code></pre><p><code>$utf8 = New-Object System.Text.UTF8Encoding $false<br>[Console]::InputEncoding = $utf8<br>[Console]::OutputEncoding = $utf8<br>$OutputEncoding = $utf8</code></p><p><code>if (Get-Command fnm -ErrorAction SilentlyContinue) {<br>fnm env --use-on-cd | Out-String | Invoke-Expression<br>}<br></code></p><p></p><p>验证结果：</p><pre><code class="language-powershell">chcp
[Console]::OutputEncoding.WebName
$OutputEncoding.WebName</code></pre><p>得到：</p><pre><code class="language-text">Active code page: 65001
utf-8
utf-8</code></pre><p>这说明控制台输入输出已经切换到 UTF-8。</p><h3>关键发现：显示正常不等于写入安全</h3><p>虽然 Windows PowerShell 5.1 的控制台输出已经是 UTF-8，但进一步测试发现，默认 <code>Set-Content</code> 写入中文文件时，真实字节仍然是 GBK。</p><p>测试字符串：</p><pre><code class="language-text">微信读书 UTF-8 写入测试：中文正常 abc123</code></pre><p>Windows PowerShell 5.1 默认写入后的前几个字节：</p><pre><code class="language-text">CE A2 D0 C5 B6 C1 CA E9</code></pre><p>这是 GBK 编码下的“微信读书”，不是 UTF-8。</p><p>真正的 UTF-8 字节应该是：</p><pre><code class="language-text">E5 BE AE E4 BF A1 E8 AF BB E4 B9 A6</code></pre><p>这个发现说明：仅仅把 <code>chcp</code> 和输出编码改成 UTF-8，还不足以保证 Windows PowerShell 5.1 的文件写入安全。</p><h2>三、切换到 PowerShell 7</h2><h3>安装和验证</h3><p>安装 PowerShell 7：</p><pre><code class="language-powershell">winget install Microsoft.PowerShell</code></pre><p>进入 PowerShell 7：</p><pre><code class="language-powershell">pwsh</code></pre><p>验证版本：</p><pre><code class="language-powershell">$PSVersionTable.PSVersion</code></pre><p>最终确认版本为：</p><pre><code class="language-text">PowerShell 7.6.1</code></pre><p>继续验证编码：</p><pre><code class="language-powershell">chcp
[Console]::OutputEncoding.WebName
$OutputEncoding.WebName</code></pre><p>结果：</p><pre><code class="language-text">Active code page: 65001
utf-8
utf-8</code></pre><h3>PowerShell 7 写入测试</h3><p>Codex 重启后，再次测试“微信读书”中文写入。</p><p>结果显示 Codex 当前使用：</p><pre><code class="language-text">PowerShell 7.6.1</code></pre><p><code>pwsh.exe</code> 路径为：</p><pre><code class="language-text">C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.1.0_x64__8wekyb3d8bbwe\pwsh.exe</code></pre><p>写入文件后的真实字节：</p><pre><code class="language-text">E5 BE AE E4 BF A1 E8 AF BB E4 B9 A6</code></pre><p>并且：</p><pre><code class="language-text">HasUtf8Bom: False</code></pre><p>这说明 PowerShell 7 默认写入结果为 UTF-8 no BOM，符合预期。</p><h2>四、Windows Terminal 默认配置的补充说明</h2><p>排查过程中还发现，Windows Terminal 的默认 profile 仍然可能指向 Windows PowerShell 5.1：</p><pre><code class="language-text">Name: Windows PowerShell</code></pre><p>这不一定影响 Codex，因为 Codex 可以单独找到并使用 PowerShell 7。但如果希望手动打开 Windows Terminal 时也默认进入 PowerShell 7，需要修改 Windows Terminal 的默认 profile。</p><p>配置文件位置：</p><pre><code class="language-powershell">$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json</code></pre><p>将 <code>defaultProfile</code> 改成 PowerShell 7 对应的 GUID。例如本机 PowerShell 7 profile 是：</p><pre><code class="language-json">"guid": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
"name": "PowerShell",
"source": "Windows.Terminal.PowershellCore"</code></pre><p>则可将：</p><pre><code class="language-json">"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}"</code></pre><p>改成：</p><pre><code class="language-json">"defaultProfile": "{574e775e-4f2a-5b96-ac1e-a2962a402336}"</code></pre><p>注意：不同机器上的 GUID 可能不同，应以本机 <code>settings.json</code> 为准。</p><h2>五、写入 AGENTS.md 作为硬性标准</h2><p>为了避免后续 Codex 会话再次退回 Windows PowerShell 5.1，在 <code>E:\Project\AGENTS.md</code> 中加入了工作区级约束：</p><pre><code class="language-markdown">## Local PowerShell Runtime
</code></pre><ul class="tight" data-tight="true"><li><p><code>When running local PowerShell commands on Windows, Codex must use PowerShell 7 (pwsh) rather than Windows PowerShell 5.1 (powershell.exe).</code></p></li><li><p><code>This is a hard requirement to avoid Windows PowerShell 5.1 encoding issues, including GBK/ANSI file writes, garbled UTF-8 output, BOM changes, and source file corruption.</code></p></li><li><p><code>Before any command that writes files through PowerShell, verify the runtime is PowerShell 7 or invoke pwsh explicitly.</code></p></li><li><p><code>Avoid rewriting source files through ambiguous PowerShell pipelines or redirection. Prefer patch-based edits; when shell file writes are unavoidable, use explicit UTF-8 no BOM encoding.<br></code></p></li></ul><p>写入后验证：</p><pre><code class="language-text">PSVersion: 7.6.1
HasUtf8Bom: False</code></pre><p>说明 <code>AGENTS.md</code> 是通过 PowerShell 7 写入，并保持 UTF-8 no BOM。</p><h2>六、最终结论</h2><h3>1. WSL 问题结论</h3><p>Codex 切换到 WSL 后历史 Session 消失，并不是历史被删除，也不是 WSL 本体版本过低。</p><p>更准确的原因是：</p><ul class="tight" data-tight="true"><li><p>当时没有配置好可用的默认 Linux 发行版。</p></li><li><p>Windows 原生环境和 WSL 环境的用户目录、配置、缓存、Session 索引大概率是隔离的。</p></li></ul><p>因此，切回 Windows 原生环境后历史恢复是正常现象。</p><h3>2. PowerShell 编码问题结论</h3><p>Windows PowerShell 5.1 即使配置了：</p><pre><code class="language-text">chcp 65001
[Console]::OutputEncoding = utf-8
$OutputEncoding = utf-8</code></pre><p>也仍然可能在默认 <code>Set-Content</code> 写文件时使用 GBK/ANSI，存在破坏 UTF-8 源码文件的风险。</p><p>更稳妥的解决方案是：</p><ul class="tight" data-tight="true"><li><p>Codex 在 Windows 本地运行 PowerShell 命令时使用 PowerShell 7 <code>pwsh</code>。</p></li><li><p>避免通过 PowerShell 管道或重定向重写源码文件。</p></li><li><p>需要写文件时明确使用 UTF-8 no BOM。</p></li><li><p>将该要求写入 <code>AGENTS.md</code>，作为项目级硬性规范。</p></li></ul><h3>3. 当前状态</h3><p>当前 Codex 环境已经确认：</p><pre><code class="language-text">PowerShell: 7.6.1
中文写入: UTF-8
BOM: False</code></pre><p>也就是说，Codex 侧的 PowerShell 编码风险已经处理完成。</p><h2>七、推荐日常规范</h2><p>后续在 Windows 原生环境下使用 Codex，建议遵循以下规则：</p><ol class="tight" data-tight="true"><li><p>本地 PowerShell 命令优先使用 <code>pwsh</code>，不要使用 Windows PowerShell 5.1。</p></li><li><p>不使用 <code>Get-Content file | Set-Content file</code> 这类读写同一文件的管道操作。</p></li><li><p>不用 <code>&gt;</code> 或 <code>&gt;&gt;</code> 重定向生成或覆盖源码文件。</p></li><li><p>源码修改优先使用补丁方式或编辑器。</p></li><li><p>必须脚本写文件时，显式指定 UTF-8 no BOM。</p></li><li><p>对包含中文的文件，必要时检查真实字节，而不只看终端显示是否正常。</p></li></ol><h2>附：安全写入 UTF-8 no BOM 的示例</h2><p>PowerShell 7：</p><pre><code class="language-powershell">Set-Content .\file.md -Value $text -Encoding utf8NoBOM</code></pre><p>Windows PowerShell 5.1：</p><pre><code class="language-powershell">[System.IO.File]::WriteAllText(
  "C:\path\file.md",
  $text,
  (New-Object System.Text.UTF8Encoding $false)
)</code></pre>]]></content:encoded>
      <category>技术实践</category>
      <pubDate>Mon, 18 May 2026 09:07:42 GMT</pubDate>
    </item>
  </channel>
</rss>