关于codex shell的一些坑

记录一下自己在windows 11下使用codex遇到的一些问题和原因

我是都把全局utf8打开的,因为我没有老旧软件使用的需求,所以可能也因此没有遇到过codex乱码问题。

codex的shell机制

codex本身并没有读取文件和编辑文件的工具,也就是cc那样的read,write工具

cc自带的工具

codex自带的工具 (可以说是非常的克制了

所以为了codex方便的修改文件,codex在shell工具里加了一个机制

  1. 命令是否为bash -lc开头, 是则去掉并使用系统bash执行命令

  2. 命令是否为apply_patch,是则执行文件编辑操作

官方指令中的apply_patch prompt 有兴趣可以看看
## `apply_patch`

Use the `apply_patch` shell command to edit files.
Your patch language is a stripped‑down, file‑oriented diff format designed to be easy to parse and safe to apply. You can think of it as a high‑level envelope:

使用 `apply_patch` shell 命令编辑文件。
你的补丁语言是一种精简的、面向文件的差异格式,设计为易于解析和安全应用。你可以将其视为一个高级封装:

*** Begin Patch
[ one or more file sections ]
*** End Patch

Within that envelope, you get a sequence of file operations.
You MUST include a header to specify the action you are taking.
Each operation starts with one of three headers:

在该封装内,你得到一系列文件操作。
你必须包含标头来指定你要执行的操作。
每个操作都以三个标头之一开始:

*** Add File: <path> - create a new file. Every following line is a + line (the initial contents).
*** Delete File: <path> - remove an existing file. Nothing follows.
*** Update File: <path> - patch an existing file in place (optionally with a rename).

*** Add File: <path> - 创建新文件。每个后续行都是 + 行(初始内容)。
*** Delete File: <path> - 删除现有文件。没有后续内容。
*** Update File: <path> - 就地修补现有文件(可选择重命名)。

May be immediately followed by *** Move to: <new path> if you want to rename the file.
Then one or more "hunks", each introduced by @@ (optionally followed by a hunk header).
Within a hunk each line starts with:

如果要重命名文件,可以立即跟随 *** Move to: <new path>。
然后是一个或多个"块",每个都由 @@ 引入(可选择跟随块标头)。
在块内,每行开始于:

For instructions on [context_before] and [context_after]:
- By default, show 3 lines of code immediately above and 3 lines immediately below each change. If a change is within 3 lines of a previous change, do NOT duplicate the first change's [context_after] lines in the second change's [context_before] lines.
- If 3 lines of context is insufficient to uniquely identify the snippet of code within the file, use the @@ operator to indicate the class or function to which the snippet belongs. For instance, we might have:

关于 [context_before] 和 [context_after] 的说明:
- 默认情况下,显示每个更改正上方的 3 行代码和正下方的 3 行代码。如果更改在前一个更改的 3 行内,不要在第二个更改的 [context_before] 行中重复第一个更改的 [context_after] 行。
- 如果 3 行上下文不足以唯一标识文件内的代码片段,使用 @@ 操作符指示片段所属的类或函数。例如,我们可能有:

@@ class BaseClass
[3 lines of pre-context]
- [old_code]
+ [new_code]
[3 lines of post-context]

- If a code block is repeated so many times in a class or function such that even a single `@@` statement and 3 lines of context cannot uniquely identify the snippet of code, you can use multiple `@@` statements to jump to the right context. For instance:

- 如果代码块在类或函数中重复如此之多,以至于即使单个 `@@` 语句和 3 行上下文也无法唯一标识代码片段,你可以使用多个 `@@` 语句跳转到正确的上下文。例如:

@@ class BaseClass
@@ 	 def method():
[3 lines of pre-context]
- [old_code]
+ [new_code]
[3 lines of post-context]

The full grammar definition is below:
Patch := Begin { FileOp } End
Begin := "*** Begin Patch" NEWLINE
End := "*** End Patch" NEWLINE
FileOp := AddFile | DeleteFile | UpdateFile
AddFile := "*** Add File: " path NEWLINE { "+" line NEWLINE }
DeleteFile := "*** Delete File: " path NEWLINE
UpdateFile := "*** Update File: " path NEWLINE [ MoveTo ] { Hunk }
MoveTo := "*** Move to: " newPath NEWLINE
Hunk := "@@" [ header ] NEWLINE { HunkLine } [ "*** End of File" NEWLINE ]
HunkLine := (" " | "-" | "+") text NEWLINE

完整的语法定义如下:
补丁 := 开始 { 文件操作 } 结束
开始 := "*** Begin Patch" 换行
结束 := "*** End Patch" 换行
文件操作 := 添加文件 | 删除文件 | 更新文件
添加文件 := "*** Add File: " 路径 换行 { "+" 行 换行 }
删除文件 := "*** Delete File: " 路径 换行
更新文件 := "*** Update File: " 路径 换行 [ 移动到 ] { 块 }
移动到 := "*** Move to: " 新路径 换行
块 := "@@" [ 标头 ] 换行 { 块行 } [ "*** End of File" 换行 ]
块行 := (" " | "-" | "+") 文本 换行

A full patch can combine several operations:

完整的补丁可以组合多个操作:

*** Begin Patch
*** Add File: hello.txt
+Hello world
*** Update File: src/app.py
*** Move to: src/main.py
@@ def greet():
-print("Hi")
+print("Hello, world!")
*** Delete File: obsolete.txt
*** End Patch

It is important to remember:

重要的是要记住:

- You must include a header with your intended action (Add/Delete/Update)
- You must prefix new lines with `+` even when creating a new file
- File references can only be relative, NEVER ABSOLUTE.

- 你必须包含你预期操作的标头(Add/Delete/Update)
- 即使在创建新文件时,也必须为新行添加 `+` 前缀
- 文件引用只能是相对的,永远不能是绝对的。

You can invoke apply_patch like:

你可以这样调用 apply_patch:

shell {"command":["apply_patch","*** Begin Patch\n*** Add File: hello.txt\n+Hello, world!\n*** End Patch\n"]}
  1. 如果都不符合则使用,pwsh或者powershell.exe -NoLogo -NoProfile -Command包裹执行

  2. 如果使用的是rg命令则会显示

  3. 如果使用的是sed命令则会显示
    image

明白了这些之后,我们就可以解释一些问题了

  1. 有时候会使用powershell执行apply_patch,因为gpt5输出了使用powershell包裹执行的apply_patch,所以导致了shell检测到的是powershell,而不是apply_patch,于是被当作命令执行了。

这个问题会导致全部命令都使用包裹执行,于是还会导致全是
image
而不是

所以我们可以在prompt中添加相关的约束

禁止使用`bash -lc`或者`pwsh -Command`包裹调用

而是直接调用(e.g `{"command":["sg", "-p", "'console.log($$$ARGS)'"],"timeout_ms":120000,"workdir":"C:\\Users\\username"}`)
  1. 但新出的codex模型上面的问题会出现的更频繁,新模型是gpt5经过coding语料微调的,但是很明显大翻车,coding sft之后指令遵循能力变弱了,于是上面的指令已经约束不了了,于是我又遇到了和上面一样的情况。然后我就升级了我的prompt
### 已安装

- ast-grep
- busybox (无需带busybox前缀 e.g `{"command":["sed","-n","1p","file"]}`)
- rg
- dust (Like du but more intuitive)
- gh
- jq

### shell调用限制

进行代码搜索或批量替换时必须优先使用`ast-grep` 而不是使用`rg` 因为`ast-grep`更适合查找代码

已安装的工具必须直接调用(e.g `{"command":["sg", "-p", "'console.log($$$ARGS)'"],"timeout_ms":120000,"workdir":"C:\\Users\\username"}`)

必须使用`workdir`指定路径 而不是在命令中使用`cd`

禁止使用`bash -lc`或者`pwsh.exe -NoLogo -NoProfile -Command`或者`powershell.exe -NoLogo -NoProfile -Command`包裹调用已安装的工具
  1. “感觉codex新模型降智了”。有这种感觉很正常,因为发布中说的

    很明显是基于router的技术,也就是使用分类模型判断你的请求应该分配更长的思考时间,还是直接就不需要分配。这个技术我就不评价了,为了省钱大家都在这样做(点名某ultrathink。但是codex这次很明显都没有调好就放出来了,于是就会导致复杂任务反而没怎么分配思考,导致效果较差。对于这个问题,我暂时没有很好的办法,因为openai并没有像anthropic那样在文档中说明可以使用关键词触发强制思考,所以最好的办法就是暂时不要使用codex模型,而是使用gpt5。
48 个赞

哇哦,沙发欸

2 个赞

大佬分析得仔细

3 个赞

佬研究的透彻,我最近几天也头疼这个事呢,学习了

2 个赞

期待佬研究出可以强制高思考的方法。

强诶ww

谢谢分享 :hand_with_index_finger_and_thumb_crossed:

codex就是个手动挡,各种半成品就端出来,现在改文件我都是让它用desktopcommand这个MCP去改,乱码和用错命令的问题倒是都解决了。

2 个赞

呃,我试试加入AGENT.md看看效果怎么样,之前让它自己用powershell看的我心碎

太强了,大佬

十分认同

会不会不小心给你c盘删了这种?

codex 是不是不会使用 zsh ?只会在 bash 里面操作?蛋疼

codex 略显简陋。在使用claude 时,像平常说话基本没什么问题的。 但codex明显要谨慎一些,尽量讲清楚。不然他会走歪了。 然后我希望他撤回之前的操作,他会飞快告诉我完成了。 实际我看文件时没有会退。 :joy:

沙盒策略和授权策略配置好就行 我有空再写一篇

我反而是用cc的时候歪得很严重,用codex基于已有代码让他去重构东西,基于已有框架实现需求,效果很好基本一次过,这个可能跟prompt有关系,我的prompt都是偏通用性的,不限制agent的workflow。

嗯 你提到了 prompt, 我在使用中没有调整prompt,只执行了初始化。

初始化就是生成了项目级的prompt 在项目内启动就会带上

我也是真的想说,让他跟着spec-workflow mcp走一个0-1的设计,出来的效果简直让我崩溃,换gpt-5-high,好了。

嗯 了解了。 那目前看我体感cc 好一些。继续体验两个。