Codex CLI 里“不生效”的设置,几乎总是层级问题,而不是语法问题。同一个键可以写在好几个地方,而最终生效的值由文档规定的顺序决定,而不是由你最后编辑了哪个文件决定。官方配置文档把这个顺序定义为七层,优先级从高到低,外加一道安全闸门:项目未被信任时,它会静默地关掉整个一层。这三条信息足以解释大多数配置上的意外:顺序、信任闸门,以及在改动任何东西之前先定位“获胜层”的习惯。
下面的顺序和引文来自官方的配置基础页面,字段级的背景在 Codex 手册里。构建时请对照当前页面核实。
按文档顺序排列的七个层级
Codex 明确列出了这个解析顺序,优先级从高到低。这里按原样复述,不合并任何层级:
- CLI 标志和
--config配置覆盖项。该次调用在命令行上传入的值。 - 项目配置文件
.codex/config.toml,从项目根目录一直到你当前的工作目录,离得最近的文件获胜,仅限受信任的项目。 - Profile 文件,通过
--profile profile-name对应的命令行标志选择,~/.codex/profile-name.config.toml以独立文件的形式存放在 Codex 配置目录下。 - 用户配置,位于
~/.codex/config.toml用户主目录下的 config.toml。 - 云端托管的
config.toml默认值,在已登录的 workspace 下会被下发。 - 系统配置,如果存在的话:
/etc/codex/config.tomlUnix 上系统级路径下的 config.toml。 - 内置默认值。
那份清单里有两个细节很容易被略过。项目层不是一个文件:Codex 从仓库根目录一路走到你正在工作的目录,最近的那个文件获胜,这就是 monorepo 能让某个子目录拥有不同设置而不必复制一切的方式。而 profile 层位于用户配置之上,而不是之下,这意味着 profile 可以覆盖你个人配置里已经设好的键。
一个有用的心智模型是一叠覆盖项,而不是一组文件:每一层只贡献它实际设置的键,而第一个提到某个键的层决定该键的值。对某个键保持沉默的层对它没有任何贡献。
项目层上的信任闸门
最能解释“我的项目配置为什么被忽略”这类反馈的那句话,就在同一页面的开头:
出于安全考虑,Codex 只在你信任该项目时才加载项目的.codex/配置层。优先级表在括号里重复了这个约束:仅限受信任的项目。页面也说明了未受信任项目的后果:Codex 会跳过项目范围内的.codex/配置层,包括项目本地的配置、hooks 和 rules;而用户配置和系统配置仍然会加载,包括用户级和全局的 hooks 与 rules。
这是安全边界,不是 bug。你克隆下来的一个仓库,不应该仅仅因为里面包含一个目录就能改变你的 agent 的行为,所以项目层在你明确同意之前是关着的。如果.codex/config.toml config.toml 里的某个设置看起来毫无效果,先检查项目的信任状态,优先于任何 TOML 调试。
策略不是一个你能覆盖的层
还有第二种机制看起来像优先级,其实不是:托管要求。文档把分工说得很直白:
要求约束行为;配置值提供默认值。
配置层决定哪个默认值适用;要求决定什么根本被允许。在受管机器上,组织可以通过requirements.toml强制执行约束,比如禁止某种审批策略或 sandbox 模式。去找一个优先级更高的配置层赢不过一条要求,因为要求并不在同一条梯子上竞争。当某个值在受管设备上拒绝改变时,要问的是有没有一条要求按住了它,而不是你还有哪个配置文件没改。
一个设置该放在哪里
顺序清楚之后,实际问题就变成放在哪。文档自己的指引很简洁:利用优先级把共享默认值放在config.toml用户配置里,并让 profile 文件只专注于那些不同的取值。
| 情形 | 该用的层 |
| --- | --- |
| 团队共享默认值 | 用户配置,~/.codex/config.toml用户主目录下的 config.toml |
| 仓库特定行为 | 仓库里的 config.toml.codex/config.toml,同时记得信任要求 |
| 环境或角色差异 | 一个 profile 文件加上--profile profile-name对应命令行标志 |
| 一次性或脚本化调用 | 命令行上的--config覆盖项 |
| 全机器范围、无策略的默认值 |/etc/codex/config.toml Unix 上的系统配置 |
键本身的语义,包括 provider 字段及其默认值,在自定义 provider 指南里。还有一条相关边界值得理清:凭证来自哪里是它自己的话题,不是一个配置层,存储模式在凭证指南里。
CI 里的取舍
持续集成让分层变得可见,因为 CI runner 恰恰是那种不能假定项目层存在的环境。一次 checkout 的信任状态不是流水线该依赖的东西,而那台机器上的用户配置可能根本不是你写的。由此有两个习惯。对每个环境不同的值,一个 profile--profile 保留一小组具名配置;对每次调用不同的值,--config命令行覆盖项把它们显式传进去。两种情况里,重要的值都在流水线里写明,而不是从某个没人审计过的层继承。在流水线里跑编码 agent 的更多模式在 CI 指南里。
如果问题里的设置是受管网络上的证书包或代理配置,那它属于企业环境的话题,而不是层级挑选;企业网络指南讲了这些。
调试一个怎么都改不动的值
从上往下过这些层,停在第一个提供该值的层:
- 信任状态。项目到底被信任了吗?如果没有,到此为止:项目层根本不在场。
- 命令行。这次调用是否带了
--config配置覆盖项,或者某个设置该键的标志? - 项目层。对于受信任的项目,是否存在一个比你编辑的那个更靠近工作目录的
.codex/config.tomlconfig.toml? - Profile。是否有某个
--profileprofile 处于激活状态,而那个 profile 文件设置了同一个键? - 用户配置。这个值是否在
~/.codex/config.toml用户 config.toml 里,而且可能比你记得的更旧? - 云端托管的默认值。是否有已登录的 workspace 在下发某个托管的
config.toml默认值? - 系统配置和内置默认值。最后,检查
/etc/codex/config.tomlUnix 上的系统配置,再看文档列出的内置默认值。
这个顺序也是验证假设最快的方式:用--config覆盖项为当前这次调用设一次值。如果行为变了,就说明键是对的,问题在放置位置;如果没变,问题在键本身或要求层。把你改过的层和获胜的层记下来;这一对是一次配置决策唯一持久的记录,也能让下一个人省掉同一趟排查。
CLI 和 IDE 共享同一套层
文档指出 CLI 和 IDE 扩展共享同一套配置层。从任一界面编辑用户配置都会同时改变两者的行为,这很方便,直到有人编辑了一个项目文件,以为它只会影响 IDE。文档里打开文件的路径很短:在 IDE 扩展里,点击右上角的齿轮图标,然后进入 Codex Settings > Open config.toml。在 ChatGPT 桌面应用里,同一个文件通过 Settings > Configuration > Open config.toml 打开,手册如此说明。同一套层,从任一工具看过去,都以相同的顺序解析。
检查清单
- 在调试任何项目层的值之前,先确认项目的信任状态。
- 用一次性的
--config覆盖项复现生效值。 - 把共享默认值放在用户配置里,而不是散落在各个项目文件中。
- 把仓库特定的值放进
.codex/config.tomlconfig.toml,并记住信任闸门。 - 让 profile 只专注于那些不同的取值,用
--profile对应标志来选择。 - 在 CI 里显式写明关键值,而不是依赖项目层。
- 当受管机器拒绝某项改动时,先查要求,再查配置层。
- 从上到下走一遍这七层,并把团队的放置约定一次性写下来。
七层,一道信任闸门,还有一个站在梯子之外的策略机制。大多数配置之谜都能收拢成一个问题:这里哪一层有权说话,又是哪一层在说话。本站记录的兼容服务的端点级细节在它自己的文档里,而第一次把这些层放进上下文的四工具配置在共享密钥指南里。一如既往,请对照构建时官方页面的当前内容核实顺序和引文。