在 Codex 的命令行界面(CLI)中,daemon_auto_start 目前默认处于启用状态,会在用户未明确要求时自动启动一个持续驻留、并能自行更新的后台守护进程。这一默认行为应当调整为用户主动选择开启(opt-in),而不是让常驻且自动更新的后台守护进程成为默认配置。
正文
你使用的是哪种 Codex?
CLI — 0.157.0,通过 npm install -g @openai/codex 安装,Linux (WSL2)
希望增加什么功能?
请把 daemon_auto_start 改为 CLI 的可选开启(默认 false),或者至少在开启前询问一次。
自 0.157.0 起,仅仅打开一个交互式 codex 会话:
- 启动一个常驻后台守护进程(
codex app-server --managed-daemon)。它在自己的会话中运行,没有 TTY,并且在所有 Codex 窗口关闭后继续运行(被 reparent 到 PID 1),直到执行codex app-server daemon stop或重启系统。 - 复制整个平台包(约 374 MB:包含
codex、codex-code-mode-host、捆绑的bwrap/zsh/rg)到~/.codex/packages/app-server-daemon/releases/<version>/——与 npm 刚安装的内容逐字节相同——并从该副本运行守护进程。从此,后端版本就与我用包管理器安装的 CLI 版本解耦。 - 启动一个分离(detached)的更新器(
codex app-server daemon pid-update-loop),在启动 5 分钟后检查更新,之后每小时检查一次,下载新版本并重启后端(这可能终止正在进行的轮次,参见 app-server daemon: auto-update force-kills active turns after a 60s drain budget, and cannot be disabled#40969)。 - 固定(Pin)恰好启动它的那个会话的环境。我通过一个包装器启动 Codex,每次调用都会设置
HTTPS_PROXY;守护进程保留第一个会话的代理变量,其出站连接都通过该代理,无论后续会话是用什么环境启动的。Hooks in --remote mode receive the daemon's cwd, not the session's#42457 和 Hooks spawned by the app-server daemon cannot identify the client terminal, breaking terminal-targeting hooks#37537(守护进程的 cwd / 终端而不是会话的)看起来是同一个根本原因。
对于 CLI 来说,最不会让人意外的默认行为是:后端随窗口生死,运行我安装的那个二进制文件,并且不在后台自我更新。共享的、自我更新的守护进程对 Remote Control / 桌面应用是合理的,所以在那里启用它,或者在用户显式运行 codex app-server daemon start / bootstrap 时启用,都是可以的。
如果默认保持开启,请至少:
- 在最后一个客户端断开时退出自动启动的守护进程;
- 当 CLI 是通过包管理器(npm/brew/pacman)安装时,不要复制/自我更新——改为运行已安装的二进制文件(Support externally managed app-server daemon executables#41188、npm update leaves app-server on old version, but daemon update/restart refuse recovery#46468、Codex 0.157.0 no longer starts with the Arch Linux package unless --no-daemon is used#48050)。
附加信息
关闭时发现的 bug:codex app-server daemon stop 会停止 app-server,但让 pid-update-loop 更新器继续运行(70 秒后仍存活,只能手动杀掉)。
我目前使用的解决方法:
codex features disable daemon_auto_startcodex app-server daemon stoppkill -f 'app-server daemon pid-update-loop'(daemon stop不会停止此进程)rm -rf ~/.codex/packages/app-server-daemon
关闭该 flag 后,新的 TUI 会话不再派生守护进程。
动态
megahall 评论:感谢报告这个问题,我自己也遇到了……不应该在小版本更新时突然创建神秘的服务器和进程,却完全不事先通知大家……
kr8vka0z 评论:同意。在修复之前,CLI 根本无法使用。
tagorr 评论:我可以在 Windows 10 LTSC 和 Codex CLI 0.157.0 上确认这一点。在 config.toml 中设置 daemon_auto_start = false 可解决该问题。
两点改进会有帮助:
- 当守护进程启动被权限提升阻止时,自动回退到本地模式,而不是要求使用
--no-daemon。 - 把守护进程自动启动改为可选开启,而不是默认开启。
这样既能保留安全限制,又不会干扰正常的 CLI 工作流程。
Yihua-Liu-1997(作者)评论:确实——第 1 点和第 2 点都可行~
felipeelopes 评论:在 Windows 上,由于这个 bug,Codex CLI 无法使用。
zdd 评论:太糟糕了。我在 CLI 里根本无法输入任何内容。你们应该尽快修复这个问题,并给我们 100 次 banked reset!
aetherxeg-source 评论(通过 ChatGPT Codex Connector):
这个请求背后有一个有用的来源边界:
installed CLI identity != daemon execution identity(已安装的 CLI 身份 != 守护进程执行身份)
一旦 CLI 把自己复制到受管理的发布目录,并且后台更新器可以替换该副本,那么为后续轮次提供服务的进程,就未必是用户显式安装或调用的那个产物了。
我会让守护进程为每次客户端连接暴露一个小的执行收据(execution receipt),至少包含:
client_cli_version + daemon_binary_digest + daemon_generation + updater_state + inherited_environment_generation
这样客户端就能区分:
- 相同的已安装产物,相同的守护进程代(generation);
- 相同的 CLI,但不同的守护进程代;
- 守护进程二进制独立于包管理器状态发生了变化;
- 守护进程继承了更早会话的环境。
一个强的回归测试是:在环境 A 下启动守护进程,从环境 B 连接,更新已安装的 CLI,并验证客户端能确切看到哪个守护进程代/二进制/环境对该轮次具有权威性,而不是从前台 CLI 版本去推断。
相关运行时行为完整性工作:https://github.com/AETHERXGLOBAL/execsurface
laurynas-karvelis 评论:基本上——这是恶意软件的特征。说实话,我甚至不认为这是意外造成的。
skhaz 评论:+1 支持禁用这个。
评论
多数人质疑 Codex CLI 的后台守护进程与自动更新:认为它偷偷驻留、占满硬盘、弄坏权限且不透明;少数人则认为自动更新已是行业标准,或是出于安全与稳定不得不做的取舍。分歧主轴在于这类“隐形后台行为”究竟是现代软件的必要交付方式,还是对用户机器的失控侵占。
认为后台守护进程和自动更新是在侵占用户机器
- 许多人反感 Codex 在用户不完全察觉的情况下常驻后台、自动更新并保留旧版本;有人清理时发现旧版本竟占了约 12GB,质疑一个“只是 harness”的工具不该如此臃肿。(较多人)
- 更严重的是对稳定性的不信任:自动更新会随机改坏权限,把 .git 变成只读,导致任务几小时就被卡住;Windows 下执行每条命令还弹新控制台,被认为把好用的 CLI 越改越糟。(较多人)
- 这些批评背后是对控制权的焦虑:用户不希望一个命令行工具在后台自行其是,更不希望它因为自动更新而破坏工作区。(较多人) > 自动更新时它会随机把权限弄坏,让 .git 变成只读,我每隔几小时就被这种随机 Bug 卡住,根本不敢信任它执行任务。(@dllu)
认为 Codex 并非特例,Claude Code 也是同一套机制
- 有人指出 Codex 与 Claude Code 其实是相同的操作模型:本地会保留多个旧版本二进制,后台常驻任务,UI 也会提示更新,因此只骂 Codex 并不公平。(少数人)
- 这说明争议应从单产品扩展到整个 LLM harness 生态:后台更新、驻留和不透明进程像是这类工具的默认设计,而不是某家偶发失误。(少数人)
- 连 Claude 桌面端也被吐槽:休眠唤醒后风扇狂转,留下几十个进程和大量 Python,让人觉得应用对自己在做的事并不诚实。(少数人) > 这跟 Claude Code 是同一套操作模型,我能看到好几个旧版二进制和后台任务,而且 UI 也会提示更新。(@timdorr)
认为自动更新是行业标准或安全稳定的必要取舍
- 少数人为自动更新辩护:现代软件迭代很快,浏览器早已自动更新,harness 没理由不跟上;从维护者角度,把带 Bug 的版本留在用户机器上才是更用户敌对的做法。(少数人)
- 这种视角强调取舍而非恶意:强制或频繁检查更新是为了安全和稳定,若真无法接受,用户至少还有“不再运行它”的明确选择。(少数人) > 我们评估过守护进程方案,最后选择每次启动都硬检查更新:把带 Bug 的应用放出去才是用户敌对,若不接受自动更新,你可以不再运行它。(@piker)
对 LLM 驱动开发的现状感到悲观
- 有人明确把 Codex CLI 和 Claude Code 的质量视为当前 LLM 驱动开发的诚实缩影,并直接表示对未来不乐观。(少数人)
- 更广泛的不信任在于:如果连这类 harness 都频繁出现权限、后台和稳定性 Bug,那么把更重要的开发目标交给“模型 + harness”范式自动执行就更值得怀疑。(较多人) > Codex CLI 和 Claude Code 的质量诚实反映了 LLM 驱动开发的现状,未来看起来并不真的乐观。(@esjeon)
主张回归轻量、透明、可配置的 CLI
- 少数人已经转向极简 harness:只带少量工具,让模型主要依赖 bash,需要的功能自己写成命令行工具并在系统提示里声明,觉得比“过度工程”的封装更清爽。(少数人)
- 更普遍的不满其实是:用户要的只是一个有少量工具、内置且可配置沙箱的 CLI,而不是守护进程、自动更新和花哨终端 UI 这些多余负担。(较多人) > 我用几乎不带工具的极简 harness,让模型主要依赖 bash;需要特殊动作就自己写个命令行工具,再在 system prompt 里告诉它,这种方式非常清爽。(@reacharavindh)
主张用发行版打包和 XDG 规范来约束这类工具
- 少数人认为,正确做法是把这类工具交给操作系统发行版打包:由打包者测试、设定合理默认值,从源头阻止乱写配置、乱留后台进程等“胡闹”。(少数人)
- 不遵循 XDG 规范被看作危险信号:一个连配置和数据该放哪都随意来的应用,往往会在其他地方也继续横冲直撞;做好与系统、发行版适配的包管理并不难。(少数人) > 拒绝遵循 XDG 规范是个强烈的危险信号,这种应用往往会在别的方面也横冲直撞;做符合系统和发行版习惯的包管理其实并不难。(@quotemstr)
有价值的补充
- 关闭后台守护进程目前没有正式文档,但可在 ~/.codex/config.toml 的 features 段把 daemonautostart 设为 false;也可用 --no-daemon 启动,或把 codex 包一层默认带 --no-daemon 的 shell 函数。
- 有用户进一步加固:把 ~/.codex 启动时会写的 pid、lock 等文件删掉,替换为指向 /dev/null 的符号链接,再用 chattr +i 使其不可写;这样即使将来去掉该开关,后台守护进程启动时也会崩溃。
- 终端 UI 的改动也可关闭:用环境变量 CODEXTUIDISABLEKEYBOARDENHANCEMENT=1,或用 /tui 命令回退;若想彻底没有自动更新和后台进程,有人直接复制可执行文件再配合 --no-daemon 使用。
- 一个反直觉的基准测试发现:Codex 初次运行之后的“快”,可能正是后台守护进程或预热带来的,其他 harness 也有类似行为;为保证测量准确,有人用 bwrap 把这类工具包起来隔离测试。