记一次 Codex 读取中文乱码问题:明明指定 UTF-8,为什么还是乱码?
摘要:本文分析了在Windows环境下使用Codex处理含中文的Markdown文件时出现乱码的问题。作者发现问题的根源在于Codex调用PowerShell时加载了用户profile脚本,导致输出被错误解码。提出了两种解决方案:一是在项目AGENTS.md中提示使用非login shell,二是在Codex配置中设置allow_login_shell=false。建议结合用户级配置和项目级指导来
背景
最近在 Windows 环境下使用 Codex 处理一个 Python 项目时,遇到了一个很迷惑的问题。
项目里有一个 Markdown 文件,里面包含大量中文内容。我让 Codex 读取这个文件,并且明确要求它按照 UTF-8 编码读取。命令大概是这样:
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8;
$i=1;
Get-Content LOGIC_MAP.md -Encoding UTF8 |
ForEach-Object { '{0,4}: {1}' -f $i, $_; $i++ } |
Select-Object -First 40
但 Codex 返回的内容是乱码,类似这样:
# 关键逻辑æµç¨‹
一开始我以为是文件编码有问题。但我自己在本地 PowerShell 里执行同样的命令,输出却是完全正常的:
# 关键逻辑流程
这就说明一个问题:文件本身大概率没有坏,Get-Content -Encoding UTF8 也不是根因。
真正的问题出现在 Codex 调用 shell 工具时的执行环境。
现象
这个问题有几个典型特征。
第一,Codex 读取中文文件时会出现乱码,即使命令里已经写了:
-Encoding UTF8
第二,我自己在控制台执行同样的命令,中文显示正常。
第三,这个问题不是每次都出现。有时候新开一个 Codex 会话,新的 Codex 又能正常读取中文。
第四,在一次新会话里,我让 Codex 执行同一个读取命令,结果发现它执行了两次:一次乱码,一次正常。
我问 Codex 原因,它指出差异在于工具调用时是否使用了 login: false。当使用非 login shell 时,不加载用户的 PowerShell profile,中文输出就正常了。
根因分析
这个问题不是简单的“文件编码错了”。
从数据流上看,读取一个中文文件至少经过了几步:
文件字节
-> PowerShell 按 UTF-8 读成字符串
-> PowerShell 把字符串输出到 stdout/stderr
-> Codex runner 捕获输出
-> Codex 把输出文本放进上下文
Get-Content -Encoding UTF8 只解决第一步,也就是“PowerShell 怎么读取文件”。
但 Codex 看到的内容还经过了后面的 stdout/stderr 捕获和解码过程。只要 Codex 启动的 shell 环境、PowerShell 编码、控制台 code page、profile 脚本、工具捕获层之间有一个地方不一致,就可能出现乱码。
这也是为什么我自己在终端里执行正常,而 Codex 执行不正常。因为两者虽然都叫 PowerShell,但它们不一定是同一个执行环境。
profile 脚本为什么会影响 Codex?
PowerShell 启动时可能会加载用户 profile。profile 本质上是一个 .ps1 脚本,里面常见内容包括 conda 初始化、别名、模块导入、提示符美化、编码设置等。
如果 Codex 调用 shell 工具时使用了 login shell 语义,它就可能加载这些 profile 脚本。
问题在于,Codex 是一个自动化执行环境。它不需要你的交互式 shell 配置。profile 里任何输出、报错、编码设置,都可能污染 Codex 的工具结果。
我这次的问题里,Codex 输出中还出现过类似 PowerShell profile 加载失败的报错。也就是说,Codex 在真正读取 Markdown 文件之前,已经先尝试加载了 profile。这个报错本身又被错误解码,于是进一步干扰了结果。
所以问题并不是:
Markdown 文件坏了
而更像是:
Codex 启动 PowerShell 时加载了 profile
profile 报错或改变了 shell 环境
PowerShell 输出被 Codex 捕获时又发生了错误解码
最终 Codex 看到乱码
为什么 login: false 能解决?
login: false 的核心作用是让 Codex 调用 shell 工具时,尽量不要以 login shell 的方式启动命令。
简单理解就是:不要加载用户 profile。
这样可以避免:
1. PowerShell profile 脚本先于命令执行
2. profile 报错污染 stdout/stderr
3. profile 修改编码环境
4. profile 初始化 conda、oh-my-posh、模块等内容导致额外输出
对 Codex 这种自动化 agent 来说,shell 输出应该尽可能干净、可预测。交互式终端的 profile 配置,不应该参与 Codex 的工具调用。
两种解决方式
方式一:在 AGENTS.md 里写项目提示
如果是团队协作项目,可以在项目根目录放一个 AGENTS.md,告诉 Codex 在运行 PowerShell 命令时优先使用非 login shell。
示例:
## Shell
- When running PowerShell commands, prefer `login: false` to avoid loading user profile scripts unless explicitly needed.
- When reading or writing text files containing Chinese, use UTF-8 explicitly.
- Prefer deterministic, non-interactive commands.
- Avoid relying on user-specific PowerShell profile behavior.
这种方式适合放在项目里。团队成员打开这个项目时,即使不知道本机可以配置 allow_login_shell = false,Codex 也能读到项目里的协作规则。
Codex 官方文档说明,Codex 会在开始工作前读取 AGENTS.md,并且可以通过全局指导和项目级指导叠加形成一致的项目约定。项目里的 AGENTS.md 会随着仓库一起被团队成员共享,这很适合记录这类项目级注意事项。(OpenAI 开发者)
但要注意,AGENTS.md 是提示层约束,不是强制执行层配置。它能提高 Codex 选择正确工具参数的概率,但不能从机制上禁止 login shell。
方式二:在 Codex 配置里关闭 login shell
更稳定的方式是在 Codex 配置文件里加:
allow_login_shell = false
用户级配置文件通常在:
~/.codex/config.toml
Windows 上一般对应:
C:\Users\<你的用户名>\.codex\config.toml
例如:
allow_login_shell = false
Codex 官方配置参考里对这个选项的说明是:allow_login_shell 控制 shell 工具是否允许使用 login-shell 语义,默认值是 true;当设置为 false 时,login = true 的请求会被拒绝,省略 login 时也会默认使用非 login shell。(OpenAI 开发者)
官方安全配置示例里也把它作为一个可选加固项,用来禁止基于 shell 的工具使用 login shell。(OpenAI 开发者)
也就是说,如果只是想解决自己机器上的稳定性问题,建议直接配:
allow_login_shell = false
如果是团队项目,则建议两者都做:
个人机器:config.toml 里设置 allow_login_shell = false
团队项目:AGENTS.md 里提示 PowerShell 使用 login: false
推荐配置
我个人建议这样做。
1. 用户级 Codex 配置
编辑:
C:\Users\<你的用户名>\.codex\config.toml
加入:
allow_login_shell = false
[shell_environment_policy.set]
PYTHONUTF8 = "1"
PYTHONIOENCODING = "utf-8"
其中 allow_login_shell = false 是关键。后面两个环境变量主要是让 Python 子进程在处理中文时更稳定。
2. 项目级 AGENTS.md
在项目根目录加:
# AGENTS.md
## Shell
- When running PowerShell commands, prefer `login: false` to avoid loading user profile scripts unless explicitly needed.
- Use explicit UTF-8 when reading or writing text files.
- Avoid relying on user-specific shell profile behavior.
- Prefer non-interactive, deterministic commands.
## Windows encoding
- For PowerShell commands that read Chinese text, use `-Encoding UTF8` where applicable.
- If command output still appears garbled, avoid using PowerShell output as the source of truth.
- Prefer Python for UTF-8 file reads and writes when editing Chinese files.
这样做的好处是,团队里的其他人即使没改自己的全局 Codex 配置,Codex 在这个项目里也有更大概率避免踩坑。
不过项目级配置 .codex/config.toml 和 AGENTS.md 的加载规则不同。Codex 官方文档说明,项目级 .codex/config.toml 只有在项目被信任时才会加载;而项目指导文件会按项目路径规则被发现和合并。(OpenAI 开发者)
所以如果只是写团队协作建议,AGENTS.md 更适合提交进仓库。如果要做执行层限制,还是建议每个人在本机的 Codex 用户配置里设置 allow_login_shell = false。
不建议做什么
不要看到乱码就让 Codex 修复文件编码。
如果你自己在本地 PowerShell、VS Code 或 Python 里读取文件是正常的,说明文件大概率没坏。这个时候让 Codex 根据它看到的乱码去“修复编码”,反而可能把一个正常 UTF-8 文件二次转码,真的写坏。
更安全的判断方法是:
Format-Hex .\LOGIC_MAP.md -Count 64
如果文件字节本身是正常 UTF-8,就不要改文件。
另外,也不要为了让 profile 能加载而随便执行:
Set-ExecutionPolicy Unrestricted
这不是解决 Codex 工具乱码的好方法。Codex 不应该依赖你的交互式 profile。对自动化 agent 来说,干净的非交互式 shell 更可靠。
我的最终结论
这次问题的关键不是 UTF-8 读取参数,而是 Codex 调用 PowerShell 工具时的 shell 启动方式。
Get-Content -Encoding UTF8 只保证 PowerShell 按 UTF-8 读文件,不保证 Codex runner 捕获和解码 stdout/stderr 时一定不会出错。
如果 Codex 以 login shell 方式启动 PowerShell,它可能加载用户 profile。profile 脚本的报错、输出或环境修改,都可能影响 Codex 的工具结果。
最终我的解决方案是:
1. 在 Codex 用户配置里设置 allow_login_shell = false
2. 在团队项目的 AGENTS.md 里提示 PowerShell 命令优先使用 login: false
3. 读取和写入中文文件时显式使用 UTF-8
4. 不要让 Codex 根据乱码输出去修复原文件编码
这套方案解决的不是单个文件乱码,而是让 Codex 的 shell 工具执行环境更干净、更稳定、更适合团队协作。
更多推荐



所有评论(0)