横向对比 · Codex 与 Grok Build、OpenCode

把 Codex 和站里另外两本源码解读的对象——Rust 写的 Grok Build、TypeScript 加 Effect 写的 OpenCode——并排比较。三家都让界面只当客户端,但协议各选各的:自定的 app-server v2、开放的 ACP、HTTP;安全上一家给每条命令套沙箱,一家把整个进程关进沙箱,一家不设沙箱;Codex 只说 Responses API,另两家追求提供方中立。关于 Grok Build 与 OpenCode 的说法都出自站内专栏并附链接。

作者 David更新于 第 56 篇(共 57 篇)

横向对比 · Codex 与 Grok Build、OpenCode

站里拆过的开源编码 agent 里,《Grok Build 源码解读》与《OpenCode 源码解读》是和本专栏最适合对照的两本:一本同样用 Rust,一本用 TypeScript,三份代码的基准日期相差不到三周。这一篇里关于 Grok Build 与 OpenCode 的每一条说法都出自那两本专栏,并链接到出处;它们的基准分别是 2026-09-09 的提交 37949780 与同日的 v1.18.30,那两本之后若有更新,以它们为准。Codex 这边的说法出自本专栏各篇。

基本面

CodexGrok BuildOpenCode
语言RustRustTypeScript 加 Effect,跑在 Bun 上
组织Cargo workspace,显式成员 153 个Cargo workspace,crates/ 下 96 个 cratemonorepo,36 个 workspace 包
代码量(不含测试)约 82 万行约 85 万行近 50 万行,其中 agent 相关约 17 万行
许可Apache-2.0Apache-2.0(读完之后)MIT(OpenCode 是什么)
分发npm 包里的 codex.js 挑出本平台的原生二进制(Codex CLI 是什么)二进制 xai-grok-pager,官方安装包装成 grok(专栏首页)npm 包里的小脚本挑出 Bun 编译的独立可执行文件(OpenCode 是什么)

三家体量相当,Codex 的成员数最多,很大一部分来自内核周边刻意拆出的小 crate(见 workspace 全景)。

界面只是客户端:三种协议

图表加载中…

Codex 自定协议,并把它做成产品的中心。TUI、codex exec、IDE 扩展、桌面端与 Python SDK 都经 app-server 的 v2 JSON-RPC 访问内核,TUI 的依赖里没有 codex-core;协议是双向的,审批、提问是服务端反过来发给客户端的请求;交互式 TUI 默认连本机的守护进程,几个客户端共享同一批线程(app-server、守护进程与传输)。

Grok Build 用开放的 ACP,再以 x.ai/* 方法扩展。stdio、WebSocket 服务、经 grok.com 的中继、leader 四种传输汇入同一个 MvpAgent,编辑器集成走的是 stdio;leader 模式让多个客户端共享一个后端进程,崩溃后还能重放恢复(ACP);headless 在进程内拉起 agent、开一条 ACP 通道(Headless 模式);TUI 收的也是来自 SessionActor 的 ACP 事件(TUI 架构)。

OpenCode 用 HTTP。默认的 opencode 把服务端放进一个 Bun Worker 线程,TUI 只发 SDK 请求、订阅事件;加上 --port 或改用 serve、web 就真正对外监听,Web 与桌面端走同一套 API(专栏首页、启动链路)。它的 session.prompt 要等整轮对话结束才返回,另有立即返回的 prompt_async(一条消息的生命周期);Codex 的 turn/start 只有“立即返回”一种形态。

三家殊途同归:界面只是客户端,进度全靠事件。区别在协议归谁。Codex 自定协议,审批往返、线程管理、配置读写都能按自己的需要设计,代价是每个编辑器都得专门接入;Grok Build 借开放协议,编辑器现成就能接;OpenCode 选 HTTP,任何能发请求的程序都能驱动它。把后端托管成共享的后台进程,三家也都做了:Codex 的 app-server 守护进程、Grok Build 的 leader 模式、OpenCode 新 CLI 在后台拉起并复用的 V2 服务(新 CLI 与守护进程)。

逐项对比

内核

CodexGrok BuildOpenCode
一轮怎么转RegularTask 反复调用 run_turn,模型还要工具或来了插话就再采样;可重试的流错误在采样函数里就地退避(run_turn)单线程 actor SessionActor 跑 process_conversation_turn,外加 TodoGate、动作停滞检测与瞬时故障重投(主循环)每个会话一个 Runner 跑 runLoop,每一步调一次 AI SDK 的 streamText,工具结果靠下一步回灌(一条消息的生命周期)
模型协议只说 Responses API,经 HTTP 的 SSE 或 WebSocket(模型客户端)Chat Completions、Messages、Responses 三种流归一成 SamplingEvent(三种 API 流)models.dev 目录加 Vercel AI SDK,实验开关下改走自研的 @opencode-ai/llm(模型调用层)
上下文压缩默认在窗口的 90% 触发;OpenAI 等由服务端返回不透明的压缩条目,其余本地写交接摘要;新历史基本只剩用户消息与摘要(上下文压缩)默认 85% 触发;把整盘对话总结成九段式摘要再重建历史,不留尾巴(上下文压缩)隐藏的 compaction agent 写结构化摘要,按预算原样保留最近几轮;修剪旧工具输出默认关闭(上下文压缩)
Plan 模式协作模式,“不改文件”只写在提示词里,代码只拦下 update_plan(任务类型与 Plan 模式)工具层硬拦:除 plan.md 外的编辑一律拒绝,放行一切的 yolo 下也成立(Plan mode)plan agent 的 edit 权限一律 deny,只放行计划文件(OpenCode 是什么)

工具与安全

CodexGrok BuildOpenCode
工具契约ToolExecutor 把 spec 与处理器绑在一起;工具表每次采样前重建;一把读写锁管并行(工具系统总览)一个类型实现 Tool 与 ToolMetadata 两个 trait,schema 从参数类型生成,执行结果是流(工具契约)Tool.define 给出说明、Effect Schema 参数与执行体,每轮由 SessionTools.resolve 包上插件钩子与权限询问(工具契约与注册表)
改文件只有 apply_patch:按文件分段、不带行号的精简 diff(apply_patch)search/replace、concise、hashline 三种格式(三种编辑格式),另有逐字照搬 Codex 规范的 apply_patch(与别家 agent 互通)edit 的九级匹配级联;GPT 系列模型改用同一种补丁格式的 apply_patch(文件工具)
执行命令unified exec:exec_command 起进程,write_stdin 续写或轮询,进程可以跨轮复用(执行命令)非流式与流式两条路径,跨平台杀进程树,还有一个完整的 PTY 控制器(Shell 执行与 PTY)工具 ID 仍叫 bash;tree-sitter 拆出每条子命令,按命令前缀记“总是允许”(Shell 工具)
权限与审批沙箱与审批是两个正交的量;Starlark 执行策略;审批请求依次交给 hook、自动审查、用户(权限模型、审批流程)权限管理器按判定瀑布决定放行、询问或拒绝;打开 auto_allow_bash(默认关)后,沙箱激活时 bash 调用可自动放行(workspace 抽象、沙箱与权限)规则取最后一条匹配;默认全部放行,只对疑似死循环、工作区外的目录与 .env 询问(权限系统)
沙箱每条命令单独套:macOS 现拼 Seatbelt 策略,Linux 用 bubblewrap 加 seccomp,Windows 用写受限令牌、elevated 模式另建专门的沙箱用户;联网经本地代理(权限模型、网络代理)整个进程一次性关进去:Landlock 或 Seatbelt 在启动时施加、不可撤销,子进程网络另用 seccomp 封(沙箱与权限)不设沙箱,Shell 从来不是沙箱(收尾复盘)

扩展

CodexGrok BuildOpenCode
Skills扫描多个根目录,清单按预算进上下文,$名字 显式注入;要不要自动选用由模型自己决定(Skills)SKILL.md 按作用域排优先级,带 glob 门控的技能碰到匹配文件才现身(Skills)提示词里放一份 <available_skills> 清单,正文由 skill 工具取回(Agent、命令与 Skills)
HooksClaudeHooksEngine,12 个事件;处理器是命令或 MCP 工具;按内容哈希记账,审阅信任后才运行(Hooks)16 个事件名;处理器是命令或 HTTP 回调;钩子自身失败时放行;认 Claude 与 Cursor 的事件名(Hooks)由插件提供:进程内模块返回 tool.execute.before 这类钩子,按加载顺序串行调用(插件系统)
插件打包 skills、MCP、应用连接器与 hooks,装进版本化缓存;装上不等于信任,带来的每条 hook 仍要单独审阅(插件)打包 skills、commands、agents、hooks、MCP、LSP;信任按作用域判定,未受信的插件只露出元数据(插件)进程内的 JS 与 TS 模块,来自内置、配置声明的 npm 包或目录发现,提供钩子、自定义工具与 TUI 插件(插件系统)
MCPstdio 与可流式 HTTP,带 OAuth 与 elicitation;工具进 mcp__服务器 命名空间,支持工具搜索的模型上默认延迟加载,由 tool_search 取回(MCP 工具调用)三种传输、单飞握手、OAuth;模型只看到 search_tool 与 use_tool 两个元工具(MCP 客户端、MCP 工具进注册表)本地走 stdio,远程先试可流式 HTTP 再退回 SSE;工具名是“服务器名_工具名”;客户端能力只开了 roots(MCP 集成)
多 agent子代理是同一个 ThreadManager 里的另一条线程;V1、V2 两代工具,V2 经信箱交回结论(多 agent)协调器把每个子代理放到独立的 OS 线程上,默认后台跑;能力模式按 ToolKind 裁掉工具;可选 worktree 隔离(Subagents)task 工具派生子会话,跑完整个主循环后交回最后一段文字;深度默认 1(子代理、待办与提问)

会话与界面

CodexGrok BuildOpenCode
会话持久化每个线程一个只追加的 rollout JSONL 为真相,SQLite 是可以重建的投影(会话持久化)updates.jsonl 是回放的真相源,chat_history.jsonl 存模型面的历史;SQLite 只做全文检索缓存(Sessions)SQLite 加 Drizzle;事件、序号与投影在同一个事务里写(存储)
终端界面基于 ratatui,codex-tui 约 20.6 万行(不含测试);可以把定稿的历史交给终端回滚,也可以全屏;最高 120 帧每秒(TUI 架构)基于 ratatui,pager 与 render 合计约 26.5 万行(不含测试);Elm 式的 Action、dispatch、Effect 三段(TUI 架构)独立的 @opencode-ai/tui 包,OpenTUI 加 SolidJS;事件每 16 毫秒攒一批(终端界面)
无界面与 SDKcodex exec 内嵌 app-server;TypeScript SDK 每轮起一次 codex exec,Python SDK 经 stdio 讲 v2(codex exec 与 SDK)grok -p 复用同一个 SessionActor,四种输出格式(Headless 模式)opencode run 与 serve;旧 SDK 由 OpenAPI 规格生成(SDK、协议与客户端)
与别家互通/import 把 Claude Code 与 Cursor 的配置一次性改写成 Codex 的格式,只补不覆盖(从别的 agent 迁移)运行时直接读 CLAUDE.md、.cursor/rules 与 Claude 的 hooks;有 Codex 命名空间的 apply_patch,/resume 能接手 Codex 的会话(与别家 agent 互通、Sessions)技能扫描包括 ~/.claude/;内置的提供方插件里有 Codex(Agent、命令与 Skills、插件系统)

几处值得细看的差别

安全模型差得最远。 Codex 的沙箱是按命令套的:每条命令单独包进 macOS 的 sandbox-exec、Linux 的 bubblewrap 或 Windows 的受限令牌里,所以沙箱拒绝之后还能按审批策略请求提权,只把这一条命令重跑一次(审批流程)。Grok Build 在启动时把整个进程关进笼子、之后不可撤销,恢复会话时沙箱档位必须与创建时一致;换来的是笼子焊死之后,权限层可以少问几次(沙箱与权限、Sessions)。OpenCode 不设沙箱,边界全靠权限规则,而规则默认全部放行(收尾复盘)。三种选择背后是三种假设:每条命令都不可信、整个 agent 都不可信、由用户自己决定信任到哪。

同一个“先规划”,落在三层。 Codex 的 Plan 模式落在提示词层,Grok Build 落在工具层,OpenCode 落在权限层。Grok Build 与 OpenCode 至少在编辑工具上由代码拦住,Codex 要做到硬性只读,得另外靠沙箱与审批设置。

模型接入是深与广的取舍。 Codex 只说 Responses API,于是能放心依赖服务端:远程压缩返回不透明条目,WebSocket 只发增量输入,推理以密文往返,一轮之内带着粘性路由令牌(模型客户端、上下文压缩);代价是别家后端也得说同一种协议,Ollama、LM Studio、Amazon Bedrock 都不例外(模型目录与提供方)。Grok Build 把三种 API 流归一成一套中立的事件(三种 API 流);OpenCode 靠 models.dev 与 AI SDK 做到提供方中立,再用近两千行的 provider/transform.ts 抹平各家差异(专栏首页)。

三家都把日志当真相,但压缩时留下的东西不同。 Codex 的 rollout 与 Grok Build 的 updates.jsonl 都是只追加的回放真相,数据库只是派生物;OpenCode 把事件、序号与投影放进同一个 SQLite 事务,数据库里的旧消息一条不删,只是模型看不到(收尾复盘)。压缩时,Codex 基本只留用户消息原文,Grok Build 一条不留、全靠九段式摘要,OpenCode 按预算保留最近几轮原文。

兼容别家:改写还是原地读。 Codex 选择一次性迁移,把 Claude Code 与 Cursor 的配置改写成自己的格式;Grok Build 在运行时直接读别家的约定,连 Codex 的补丁格式与会话都认;OpenCode 扫描 ~/.claude/ 下的技能。有意思的是 Codex 的 apply_patch 格式成了一种公共语言:Grok Build 逐字照搬了它的规范,OpenCode 给 GPT 系列模型提供的也是同一种补丁格式(与别家 agent 互通、文件工具)。

能力谱上,三家几乎重合:AGENTS.md 一类的项目指令、Skills、钩子、MCP、子代理、上下文压缩、Plan 模式、无界面模式都有。差别不在“有没有”,而在每一项落在哪一层、信任谁、交给谁决定。

同组的其它几本

同一组还有四本同类专栏:《Kimi Code 源码解读》(TypeScript,DI 容器加作用域的引擎)、《MiMo Code 源码解读》(从 OpenCode 分叉,为长程任务加了检查点与分层记忆)、《MiniMax Code 源码解读》(TypeScript,以 pi-mono 的 Agent 循环为底座)、《ZCode 源码解读》(同一个运行时驱动终端、桌面端与 Web 三种宿主)。想拿闭源产品的用法来对照,Grok Build 专栏的 grok Build vs Claude Code 用《Claude Code 中文手册》做过一次。


上一篇:复盘 · 对照《从 LLM 到 Coding Agent》 · 下一篇:读完之后

本页目录