没有不值得去解决的问题,也没有不值得去学习的技术!

不想再守着 Codex 选择 Y/N:我的无人值守运行配置实践

【图1:Codex 执行 Go 测试时弹出人工审批提示,需要选择 Yes 或 No】

作者:

在

最近一直在使用 OpenAI Codex 开发和维护 Go Learning & Documentation Translations 多语言项目。随着项目规模不断扩大,Codex 执行的任务也越来越复杂。

有些任务需要运行十几分钟,有些可能超过半个小时。如果涉及大量 Go 测试、仓库验证或者工程修复,耗时还会更长。

长时间执行任务本身并不是最大的问题。真正让我感到不方便的是:Codex 经常在执行过程中要求我选择 Y 或 N。

例如,当 Codex 准备执行某条命令时,可能会出现以下选项:

  1. Yes, proceed
  2. Yes, and don’t ask again
  3. No, and tell Codex what to do differently

绝大多数情况下,我都会直接选择第一项,允许 Codex 继续执行。

但问题在于,我必须一直守在电脑旁边。

假设一个任务需要运行 30 分钟,我离开电脑去处理其他事情,而 Codex 恰好在第 5 分钟弹出审批提示。那么接下来的 25 分钟,它可能都在等待我输入 Y,根本没有继续工作。

这显然不是我希望的工作方式。

我的目标其实很简单:给 Codex 一个明确的任务,离开电脑 30 分钟,回来后直接查看执行结果,而不是发现它一直停留在某个审批界面。

经过一次实际配置,我基本解决了 Codex 自身的命令执行审批问题,还顺便处理了 Go 编译缓存的写入权限。

下面记录完整过程。

一、问题起因:Go 测试也需要人工审批

先看此前遇到的一个典型场景。

Codex 正在处理项目中的仓库工程问题,修改了部分 Go 代码和测试文件,随后准备执行:

Bash
go test -mod=readonly ./cmd/tour-i18n -run '^TestSiteContentCLIRejectsUnsafeInputs$' -count=1

结果弹出了人工审批窗口。

【图1:Codex 执行 Go 测试时弹出人工审批提示,需要选择 Yes 或 No】
【图1:Codex 执行 Go 测试时弹出人工审批提示,需要选择 Yes 或 No】

提示中还说明了原因:Go 测试需要写入编译缓存,而沙盒将相关缓存目录设置为只读。

从 Codex 的安全设计来看,这种行为有合理性。默认情况下,Codex 不应该随意修改工作区以外的文件。

但是对于我的使用场景,这类审批发生得太频繁了。

尤其是 Go 项目,运行测试本来就是日常开发中非常普通的操作。如果每次都需要我手动批准,Codex 就很难持续自主完成长时间任务。

最初我考虑过使用 codex exec 的非交互模式,但仔细想了一下,这并不符合我的日常工作方式。

因为我通常已经通过以下命令进入了 Codex:

Bash
cd ~/code/go-tour-i18n
codex

随后在交互式会话中不断提交任务、查看结果、继续修复。

我不希望每次为了避免审批,都专门退出当前会话,再用 codex exec 重新启动任务。

因此,我最终选择了另一种方案:修改 Codex 的全局配置,让普通的交互式会话默认不再请求命令执行审批。

二、找到 Codex 的全局配置文件

Codex 的用户级配置文件位于:

Plaintext
~/.codex/config.toml

我的实际路径是:

Plaintext
/home/wangqiang/.codex/config.toml

通过以下命令即可打开:

Bash
nano ~/.codex/config.toml
【图2:修改前的 Codex 全局配置文件,包含模型设置和多个已信任项目】
【图2:修改前的 Codex 全局配置文件,包含模型设置和多个已信任项目】

从截图可以看到,原来的配置已经包含不少内容,例如:

TOML
service_tier = "default"
model = "gpt-6.1-sol"
model_reasoning_effort = "high"

此外,还包含多个项目的信任配置:

TOML
[projects."/home/wangqiang/code/go-tour-i18n"]
trust_level = "trusted"

我一共配置了 11 个项目。

因此,这次修改有一个重要要求:不能为了增加两个权限参数,就覆盖原来的配置文件。

模型、推理强度、项目信任设置以及终端界面配置,都必须保留。

最终我采用 Python 脚本自动修改 TOML,并在写入前检查配置完整性。这样比手动删除、重建整个文件更加稳妥。

三、设置全局自动审批

真正需要修改的核心配置只有两项:

TOML
approval_policy = "never"
sandbox_mode = "workspace-write"

这两个参数的作用完全不同。

1. approval_policy = “never”

这个配置用于控制 Codex 的命令执行审批策略。

设置为 never 后,Codex 不再因为执行命令需要额外授权而暂停等待用户批准。

但有一个细节必须说明:

不再请求批准,并不代表所有操作都会自动获得权限。

如果某项操作超出了沙盒允许的范围,Codex 仍然可能执行失败。

区别在于,它不会再通过普通的执行权限审批窗口一直等待我选择 Y/N。

这正是我希望解决的问题。

2. sandbox_mode = “workspace-write”

这个配置让 Codex 可以在当前工作区内修改文件,同时保留沙盒限制。

以我的 Go 项目为例,通常需要访问以下目录:

目录用途
/home/wangqiang/code/go-tour-i18n项目源代码读写
/home/wangqiang/下载读取下载的 ZIP 等附件
/tmp临时文件读写

对于我的环境,workspace-write 已经能够满足项目工作区和 /tmp 的主要写入需求。

下载目录通常只需要读取,并没有必要额外开放写入权限。

我没有选择:

TOML
sandbox_mode = "danger-full-access"

因为我的目标只是减少不必要的人工干预,而不是让 Codex 获得整个系统的无限制操作权限。

3. 配置修改与验证

为了避免破坏原配置,我首先对文件进行了备份。

对于希望手动操作的用户,可以先执行:

Bash
cp ~/.codex/config.toml \
  ~/.codex/config.toml.bak-$(date +%Y%m%d-%H%M%S)

随后将前面的两项参数写入 config.toml。

需要注意:这两项属于 TOML 顶层配置,应放在第一个 [projects...] 或其他配置表之前,不能误写进某个项目的配置表中。

我使用自动修改脚本完成了这一步,并检查 TOML 语法以及原有配置是否保留。

最终输出为:

Plaintext
===== FINAL =====
RESULT=PASS
MODEL=gpt-6.1-sol
REASONING=high
APPROVAL=never
SANDBOX=workspace-write
PROJECTS_PRESERVED=11
TOML_VALID=PASS

这说明:

  • 自动审批配置已经写入。
  • 沙盒模式仍然是 workspace-write。
  • 模型与推理强度没有改变。
  • 原来的 11 个项目配置全部保留。
  • TOML 语法检查通过。

不过,配置文件检查通过,并不等于 Codex 已经加载新配置。

因此,我又重新启动 Codex,输入:

Plaintext
/status
【图3:Codex 首次验证全局配置,Permissions 显示 Custom (workspace, never)】
【图3:Codex 首次验证全局配置,Permissions 显示 Custom (workspace, never)】

关键输出是:

Plaintext
Permissions: Custom (workspace, never)

这说明新的审批策略已经被 Codex 识别。

到这里,我原本以为配置工作可以结束了。

但随后发现,还有一个值得一起解决的问题。

四、新问题:Go 编译缓存目录只读

在之前的一轮工程修复中,Codex 曾经报告:

另一次测试因默认 Go build cache 只读未启动,后续将使用 /tmp 临时 cache。

这个问题与前面遇到的人工审批提示,其实存在直接联系。

Go 运行测试时需要使用编译缓存。

通常情况下,可以通过以下命令查看当前 Go 缓存位置:

Bash
go env GOCACHE

在我的 Linux 环境中,输出是:

Plaintext
/home/wangqiang/.cache/go-build

但是这个目录位于用户主目录下,不属于 Codex 默认的项目工作区可写范围。

因此,即使已经设置了:

TOML
approval_policy = "never"

也不意味着 Codex 可以直接写入这个目录。

这实际上暴露出一个容易忽略的区别:

审批策略解决是否需要人工确认,沙盒策略决定命令究竟拥有哪些操作权限。

【图4:Codex 因默认 Go 编译缓存只读,改用 /tmp 临时缓存完成测试】
【图4:Codex 因默认 Go 编译缓存只读,改用 /tmp 临时缓存完成测试】

截图中的 Codex 采用了一个临时解决方案:

Bash
GOCACHE=/tmp/go-tour-qc004-build-cache \
go test -mod=readonly ./internal/sitecontent \
  -run '^TestQC004PackageScopeDiagnosis$' -count=1 -v

对应测试最终通过。

从完成当前任务的角度看,这种处理方式没有问题。

但是我并不希望长期这样运行。

因为 /tmp 中的临时缓存可能被清理,而且不同任务使用不同的缓存目录时,无法充分复用已有的编译结果。

对于需要反复执行 Go 测试的大型项目,这可能增加编译时间。

所以,我决定进一步调整配置:保留原来的 Go 缓存位置,同时只针对该目录开放写入权限。

五、只开放 Go 编译缓存目录的写入权限

Codex 的 workspace-write 模式支持额外指定可写目录。

对应的 TOML 配置是:

TOML
[sandbox_workspace_write]
writable_roots = ["/home/wangqiang/.cache/go-build"]

注意,/home/wangqiang/.cache/go-build 是我的实际路径。其他用户应该先执行 go env GOCACHE,确认自己的缓存目录后再修改。

如果配置文件已经存在 [sandbox_workspace_write],只需要在原有配置表中添加或修改 writable_roots,不要创建重复的 TOML 配置表。

这次我依然采用自动修改脚本,而不是直接重写配置文件。

脚本主要完成以下工作:

  1. 读取 go env GOCACHE,确认实际缓存目录。
  2. 检查现有审批与沙盒配置。
  3. 在 writable_roots 中添加 Go 缓存路径。
  4. 保留所有其他配置,并验证新的 TOML。
  5. 备份原文件后写入。

实际执行结果:

Plaintext
BACKUP=/home/wangqiang/.codex/config.toml.bak-20261030-195107

===== FINAL =====
RESULT=PASS
GOCACHE=/home/wangqiang/.cache/go-build
WRITABLE_ROOTS=['/home/wangqiang/.cache/go-build']
APPROVAL=never
SANDBOX=workspace-write
PROJECTS_PRESERVED=11
TOML_VALID=PASS

这次修改没有改变原来的 Go 缓存位置,也没有开放整个用户主目录。

我只是将原来无法写入的一个特定目录,加入 Codex 沙盒的可写范围。

从权限控制的角度看,这比直接使用无限制沙盒更加符合我的需求。

六、最终验证:Codex 已识别 Go 缓存权限

完成配置后,我重新进入 Codex,再次执行:

Plaintext
/status
【图5:Codex 最终权限状态,显示 Go 编译缓存目录已加入可写工作区,并保持 never 审批策略】
【图5:Codex 最终权限状态,显示 Go 编译缓存目录已加入可写工作区,并保持 never 审批策略】

这次显示的内容与之前有所不同:

Plaintext
Permissions: Custom (workspace [/home/wangqiang/.cache/go-build], never)

相比之前的:

Plaintext
Permissions: Custom (workspace, never)

已经明确增加了 Go 缓存目录。

这意味着 Codex 已经加载了新的可写目录配置。

截至这次验证,我能够确认的是:全局自动审批配置已经生效,新增的 Go 缓存可写目录也已被 Codex 识别。

此前使用 /tmp 缓存的 Go 测试已经成功通过;但这张最终状态截图本身并不能证明所有后续 Go 测试都会成功,也不能替代实际的缓存读写验证。

不过,对于这次配置工作的目标而言,关键的权限问题已经有了明确的解决方案。

七、无人值守并不意味着任务一定成功

这次调整完成后,Codex 已经更接近我希望的工作方式:

输入一个任务,让它持续运行,自己暂时离开电脑,之后再查看执行结果。

但我认为,有必要把“无人值守”与“保证完成”区分开。

即使设置了:

TOML
approval_policy = "never"

以下情况仍然可能造成任务中断或失败:

  • 任务需要访问尚未授权的目录。
  • 网络受限,导致某些依赖或资源无法访问。
  • 运行的第三方程序自身要求交互式输入。
  • Codex 遇到无法自主决定的业务问题。
  • Codex 使用额度耗尽或网络连接中断。
  • 电脑自动休眠,导致本地任务停止。

其中,关闭终端与离开电脑也不是同一回事。

如果只是离开电脑,保持 Codex 会话运行并避免系统休眠即可。

如果需要关闭终端或断开远程连接,则应该考虑通过 tmux 等工具维持终端会话。

因此,这次配置解决的是人工审批这一类阻塞,而不是所有可能影响长任务运行的问题。

另外,我仍然会对生产环境操作保留更加严格的限制。自动修改本地仓库与自动部署生产服务,风险显然不同。

对于数据库删除、线上部署、敏感配置修改等操作,不应该仅仅为了省去几次确认,就无条件开放权限。

八、为什么我没有继续扩大权限范围?

完成 Go 缓存权限调整后,其实还可以继续开放更多目录。

比如,允许 Codex 写入下载目录,或者把整个用户主目录添加为可写范围。

但我没有这么做。

原因很简单:目前还没有实际需求。

这次遇到的问题可以分成两个:

第一个问题是反复弹出命令审批窗口,需要统一解决。

第二个问题是 Go 编译缓存无法写入,需要针对特定目录解决。

这两个问题都已经找到对应的配置方式。

至于其他目录,目前没有出现必须增加权限的证据,自然也就没有必要提前修改。

我更倾向于以后继续采用这种方式:

先使用当前配置。如果某项任务确实因为权限不足而失败,再分析具体原因,只增加必要的权限。

这样既减少了维护工作,也避免随着配置不断增加,逐渐失去对 Codex 实际权限范围的控制。

九、总结:减少等待,比盲目扩大权限更重要

这次配置调整并没有涉及什么复杂的工程开发。

真正重要的,是将几个不同的问题区分清楚。

以前我遇到 Codex 弹出 Y/N,通常只是简单地选择允许,然后继续工作。

但随着长时间任务越来越多,我开始意识到:如果一个审批问题反复发生,就不应该始终依赖人工逐次处理。

通过修改 ~/.codex/config.toml,我完成了两项关键调整:

TOML
approval_policy = "never"
sandbox_mode = "workspace-write"

[sandbox_workspace_write]
writable_roots = ["/home/wangqiang/.cache/go-build"]

最终实现了以下配置效果:

项目结果
普通交互式 Codex继续使用
全局命令执行审批不再要求人工批准
当前项目写入权限保留
/tmp 临时目录保留默认可写能力
Go 编译缓存额外授权写入
下载目录不额外开放写入
其他系统目录不全面开放
现有项目和模型配置全部保留

对于经常需要运行几十分钟任务的开发者而言,这类配置的收益并不一定体现在某一条命令节省了多少秒。

它更重要的价值在于:降低任务执行过程对人工持续在线的依赖。

如果一个任务实际只需要 30 分钟,却因为一次审批而等待了我 25 分钟,那么真正浪费的并不是计算资源,而是整个工作流程的连续性。

我希望未来与 Codex 的协作方式,不再是自己始终守着终端、不断点击确认,而是明确任务目标和权限边界之后,让它尽可能独立完成工作。

至于后续出现的新问题,我仍然会坚持按需处理,而不是一次性放开所有权限。

毕竟,让 AI 更自主地完成工作,并不意味着必须放弃对执行环境的控制。


参考资料

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系