Codex config.toml 配置:8 个关键字段默认值与改动对照
~/.codex/config.toml 决定 Codex 用哪个模型、何时请求审批、命令能写到哪里,以及终端界面和工具如何工作。网上片段最大的风险不是少一个字段,而是版本混用:旧枚举、错误的布尔类型、写进错误 TOML 表,都会让配置失效。本文以 Codex CLI 0.156.1 当前二进制生成的 schema 和 --strict-config 解析结果为口径,只选八个高价值字段,不冒充全字段清单。更完整的分层与 provider 讨论见 Codex config.toml 深度解析。
本文要回答的问题
- 怎样从当前安装的 Codex 取得字段定义,而不是照抄过期文章?
- 八个常用字段未设置时是什么行为,改动后又影响什么?
approval_policy与sandbox_mode为什么必须一起配置?history.persistence、notify、TUI 和搜索有哪些容易误解的边界?
读这张图时把两组安全字段放在一起看:审批是「要不要问人」,沙箱是「问过以后能做到哪一步」。其余字段不会改变这个权限边界;模型更聪明、通知更及时,都不等于命令更安全。
一、先让当前版本自己给出答案
当前二进制可以直接生成 app-server 协议的 JSON Schema,其中包含 Config、AskForApproval、SandboxMode 与 WebSearchMode 等定义。再配合 --strict-config,可以逐项检查字段是否被这版程序接受:
codex --version
codex app-server generate-json-schema --out /tmp/codex-schema
CODEX_HOME=/tmp/codex-probe codex --strict-config \
-c 'tui.alternate_screen="never"' doctor --json本次生成的枚举很明确:审批为 untrusted | on-request | never,沙箱为 read-only | workspace-write | danger-full-access,顶层搜索为 disabled | cached | indexed | live。八个样例均通过严格解析。
这张终端卡最重要的不是八个 PASS,而是它给出了可重复的版本锚点。严格解析能发现未知字段、错误类型和非法枚举,却不能证明模型提供方支持某个模型,也不会替你完成一次通知或搜索调用。下表中的「配置语义」和「实测解析」因此分开表述。
终端卡中第 5 至 7 行是当前二进制的枚举,第 8 至 15 行才是字段检查结论。升级 Codex 后应重新生成,不要把这份 0.156.1 的结果当成永久兼容承诺。完整探针输出如下(临时路径已脱敏为 <tmp>):
$ codex --version
codex-cli 0.156.1
$ codex app-server generate-json-schema --out <tmp>/schema
approval_policy untrusted | on-request | never
sandbox_mode read-only | workspace-write | danger-full-access
web_search disabled | cached | indexed | live
strict-config model="gpt-5.5" PASS
strict-config model_reasoning_effort="low" PASS
strict-config approval_policy="never" PASS
strict-config sandbox_mode="workspace-write" PASS
strict-config notify=["/bin/true"] PASS
strict-config history.persistence="none" PASS
strict-config tui.alternate_screen="never" PASS
strict-config web_search="live" PASS
未提供 PROBE_PROVIDER_CONFIG;仅执行离线 schema 与严格配置检查。二、配置从哪里来,为什么改了却没生效
Codex 的配置不是只看一个文件。内置默认值、用户配置、profile 和命令行覆盖会合并,组织管理策略还可能约束最终可用范围。临时排错时,用独立 CODEX_HOME 是最干净的办法:既不修改日常配置,也能排除旧 profile 的干扰。
图里最容易被忽略的是命令行覆盖:文件里写了 read-only,启动又加 --sandbox workspace-write,最终当然是后者。另一个坑在 TOML 本身——在 [model_providers.xxx] 表尾追加 model = "...",它属于 provider 子表,并不会回到顶层。本文八个字段都应放在顶层,或使用顶层点号写法。
三、八个字段:默认值与改前改后对照
下表的「默认」指不显式配置时的行为;模型与推理档位会随 provider 和模型目录变化,不能脱离环境给一个永久模型名。所有「改后」样例均已在 0.156.1 上通过严格解析,运行效果一栏则明确区分可静态确定的配置语义与需要在线会话才能验证的效果。
| 字段 | 未设置时 | 本文改后样例 | 改动后的行为 | 验证口径 |
|---|---|---|---|---|
model | 由 provider 与当前模型目录决定 | "gpt-5.5" | 请求该模型 ID;provider 不支持仍会失败 | 实测解析;可用性另查 provider |
model_reasoning_effort | 跟随模型默认档 | "low" | 请求较低推理档;可选档由模型决定 | 实测解析;非所有模型同档 |
approval_policy | on-request | "never" | 不再请求人工审批;失败直接返回给 Agent | 实测解析;配置语义 |
sandbox_mode | read-only | "workspace-write" | 允许写工作区及配置的可写根,不等于全机权限 | 实测解析;配置语义 |
notify | 不执行外部通知程序 | ["./notify.sh"] | 事件发生时调用程序,并传入 JSON 通知 | 实测解析;回调需会话验证 |
history.persistence | save-all | "none" | 不保存交互历史;不是通用的会话删除开关 | 实测解析;配置语义 |
tui.alternate_screen | "auto" | "never" | 不使用备用屏幕,输出留在终端滚动区 | 实测解析;界面效果需 TUI 验证 |
web_search | disabled | "live" | 启用实时原生搜索工具,而非只改提示词 | 实测解析;搜索调用需联网验证 |
模型与推理:合法 ID 不等于 provider 可用
model 是发给模型提供方的标识,不是 Codex 随便接受的别名。可以用 codex debug models --bundled 查看当前二进制内置目录,再用 provider 的模型列表核对。model_reasoning_effort 同理:low 能过解析,只说明字段类型和值被接受,并不保证每个模型都实现这一档。
审批与沙箱:两个旋钮必须成组修改
never + workspace-write 适合边界明确的自动化工作区,但不适合目录里混有生产凭据或不可回滚数据的任务。never 只是不再询问,不会把沙箱关掉;反过来,on-request 也不会把只读环境变成可写。更完整的选择方法见 Codex config.toml 配置下的沙箱与审批模式。
通知与历史:都不要望文生义
notify 是程序数组,不是 shell 命令字符串,参数拆分由 Codex 完成。通知 JSON 可能包含会话标识和路径,接收脚本应限制文件权限,不要直接转发到公开频道。history.persistence = "none" 也不能替代 codex exec --ephemeral:前者是历史配置,后者才明确表达非交互运行不持久化会话文件,二者不要混用概念。
TUI 与搜索:当前版本的两个写法变化
tui.alternate_screen 当前接受 "auto" / "always" / "never",写成布尔 false 会在严格检查中失败。需要保留终端滚动历史时用 "never",效果与命令行 --no-alt-screen 同类。搜索则使用顶层 web_search = "live";不要看到旧片段里的工具表写法,就推断它在所有新版本里仍是推荐形式。
四、一份可审查的改后配置
model = "gpt-5.5"
model_reasoning_effort = "low"
approval_policy = "never"
sandbox_mode = "workspace-write"
notify = ["./notify.sh"]
history.persistence = "none"
tui.alternate_screen = "never"
web_search = "live"把这段放进日常配置前,至少做三项调整:把模型换成 provider 实际支持的 ID;确认工作区可以承受自动写入;把通知程序换成绝对路径或确认启动目录。尤其不要原样复制 never + workspace-write 到权限复杂的主力机器。
| 症状 | 优先检查 | 处理 |
|---|---|---|
| 启动报配置无法加载 | 当前版本是否认识字段和值 | 加 --strict-config,逐项用 -c 缩小范围 |
| TUI 布尔值报错 | 是否照抄旧版 alternate_screen = false | 改为 "never" |
| 字段看似没生效 | 是否写在 provider 等子表内;是否有 CLI 覆盖 | 移回顶层,检查启动参数与 profile |
| 模型名合法但请求失败 | provider 是否支持该 ID 与推理档 | 对双方模型目录,不靠修改其他字段碰运气 |
| 关闭历史后仍看到会话产物 | 是否把 history 与 exec 持久化混为一谈 | 非交互场景另用 --ephemeral |
实验环境
- 机器/系统:Mac(x86_64)/ macOS 26.5.2
- 工具版本:Codex CLI 0.156.1(
codex --version输出codex-cli 0.156.1) - 日期:2026-11-01
- 完整命令:
codex --version;codex app-server generate-json-schema --out <独立临时目录>/schema;对八个字段分别执行CODEX_HOME=<独立临时目录> codex --strict-config -c '<字段与值>' doctor --json。全部检查在独立临时目录完成,未修改现有用户配置。
代码获取:八字段样例、通知接收脚本、可重复探针和真实输出见公开仓库
experiments/codex-config-toml-fields/。运行bash probe.sh offline.log可重新生成当前版本的 schema 并逐项检查;如需观察启动行为,再通过PROBE_PROVIDER_CONFIG传入自己的配置,凭据不会写入实验目录。
这一篇在知识体系里的位置
本篇是 Codex 配置主题的版本化速查页:字段分层与 provider 细节交给 Codex config.toml 深度解析,权限组合交给 Codex 沙箱审批模式,无人值守执行则接着看 Codex 非交互模式。三篇分别回答「怎么配」「放多少权」「怎样自动跑」。
总结
Codex config.toml 配置要以当前版本的 schema 和严格解析为准:八个字段中,模型与推理档受 provider 能力约束,审批与沙箱必须成组评估,notify 和搜索效果需要真实会话另行验证,history 不等于 exec 的临时运行开关,TUI 备用屏幕在当前版本使用字符串枚举。先固定版本、再逐项验证、最后写入日常配置,比复制一份所谓全字段模板可靠得多。