harness 一词来自 Uber 那篇「软件工厂」文章,指 agent 的执行环境 / 工具台——具体到 Claude Code 与 Codex,就是这两个 CLI 工具作为「AI 编程 agent 运行时」的工程架构本身。 本文从技术栈、架构形态、对外协议、配置、沙箱、会话、扩展等维度拆解两者的实现,并给出源码层面的证据。结论性观点标注「实证 / 推断」。
| 维度 | Claude Code | Codex |
|---|---|---|
| 实现语言 | TypeScript / Node.js | Rust(codex-rs) |
| 架构形态 | 单进程 CLI,agent 逻辑就在 CLI 进程里 | 前后端分离:codex(TUI 前端)+ codex app-server(后端进程) |
| 对外协议 | JSONL 流式(--output-format stream-json) |
ACP(Agent Client Protocol) RPC,stdio:// / http:// |
| 配置 | settings.json + 环境变量(ANTHROPIC_*) |
config.toml + models.json(带 schema 校验) |
| 安全模型 | permission mode(bypassPermissions 等) |
真沙箱(seatbelt / bwrap / Landlock / Windows sandbox) |
| 会话 | ~/.claude/history.jsonl + --resume |
thread-store(线程持久化,thread/start、thread/resume) |
| 扩展 | hooks、slash commands、subagents、plugins、Agent SDK | plugins、skills、code-mode、hooks |
| MCP | 原生,--mcp-config |
codex-mcp crate,mcp_servers 段 |
| 子代理模型 | CLAUDE_CODE_SUBAGENT_MODEL(显式独立) |
由模型路由/配置决定 |
一句话本质:Claude Code 是「把 CLI 输出协议化」的单进程 harness;Codex 是「把 agent 做成一个可被多方连接的 server」的 client-server harness(更接近 LSP 的设计思想)。
@anthropic-ai/claude-code,核心 agent 逻辑都在 JS 层(实证:Multica 源码里启动路径为 /usr/lib/node_modules/@anthropic-ai/claude-code/bin/claude)。claude 命令启动后,agent 循环、工具调用、上下文管理、会话状态全部在同一个 Node 进程内。--output-format stream-json --input-format stream-json 运行时,通过 stdin/stdout 传输 JSON 事件流(一行一个 JSON 对象)。claude.go 及测试 fixture):session.start / session.tools_updatedtool.execution_complete(工具执行完成)assistant.message(助手消息,带 token 用量)terminal_reason(本轮结束原因,如 prompt_too_long、max_turns)这意味着任何外部程序(如 Multica)都能通过「解析 stdout 的 JSON 流」来驱动 Claude Code,而不必理解其内部状态机。
~/.claude/settings.json(含 env、enabledPlugins、theme 等)。ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL、ANTHROPIC_DEFAULT_*_MODEL、CLAUDE_CODE_SUBAGENT_MODEL、CLAUDE_CODE_EFFORT_LEVEL、CLAUDE_CODE_AUTO_COMPACT_WINDOW 等。CLAUDE.md(项目上下文)、.claude/ 目录(hooks、skills、settings.local.json)。claude login(OAuth)或 ANTHROPIC_AUTH_TOKEN(API key,走兼容 endpoint)。default / acceptEdits / plan / bypassPermissions。--permission-mode bypassPermissions(实证:Multica 硬编码此 flag 并禁止覆盖)。~/.claude/history.jsonl;--resume <session_id> 恢复。CLAUDE_CODE_AUTO_COMPACT_WINDOW(默认 768K token)。CLAUDE_CODE_SUBAGENT_MODEL 指定子代理模型)openai/codex,核心在 codex-rs/,用 Bazel 构建(实证:仓库 BUILD.bazel、MODULE.bazel、codex-rs/Cargo.toml)。codex-cli/ 是 npm 包 @openai/codex 的包装层,实际二进制是 Rust 编译产物。codex-rs/ 下有 100+ 个 crate(core、tui、app-server、codex-mcp、exec、sandboxing、thread-store 等)。codex app-server 子命令,真正的 agent 引擎跑在 app-server 后端进程里;codex 命令本身只是前端(TUI / 无头)。codex.go 启动命令):
go
args := []string{"app-server", "--listen", "stdio://"}stdio://(或 http://)通信,因此同一份 agent 引擎可被多个前端复用(CLI TUI、VS Code 插件、桌面 App)。app-server-protocol / app-server-client / app-server-transport 等 crate。thread/start、thread/resume),app-server 响应。acp_deliverable.go、acp_effort.go、acp_terminal.go、acp_usage.go(解析 ACP 协议消息),而 Claude Code 没有对应物(它走 stream-json)。~/.codex/config.toml:TOML 格式,含 model、model_provider、model_reasoning_effort、preferred_auth_method、forced_login_method、[model_providers.*]、[mcp_servers.*] 等段。~/.codex/models.json:模型目录(模型元数据:上下文窗口、输入模态、推理档位)。config.toml / models.json 有 JSON Schema(codex-rs/core/config.schema.json),写入前校验语法。experimental_bearer_token,直接写在 config.toml)。sandboxing crate + 多后端:seatbelt(macOS)、bwrap(Linux)、Landlock、Windows sandbox、mxc-sandbox。sandbox_mode 配置:read-only / workspace-write / danger-full-access 等。codex_semantic_inactivity、codex app-server no progress timeout 等失败模式,且支持 windows.sandbox=unelevated/elevated 的 opt-in。thread-store crate:线程(thread)持久化,thread/start、thread/resume RPC。CODEX_HOME(运行级隔离,不污染 ~/.codex/)——实证:Multica 文档「每次运行拥有运行级 CODEX_HOME」。core-plugins,如 browser/chrome/pdf/spreadsheets)$CODEX_HOME/skills/)code-mode / code-mode-host / code-mode-runtime crate)| 维度 | Claude Code | Codex |
|---|---|---|
| 语言 | TypeScript/Node.js | Rust |
| 进程模型 | 单进程 | 前端 + app-server 后端 |
| 协议 | JSONL stream-json | ACP(RPC) |
| 通信 | stdin/stdout 事件流 | stdio/http RPC |
| 配置 | settings.json + env | config.toml + models.json(schema 校验) |
| 安全 | permission mode(无沙箱) | 真沙箱(seatbelt/bwrap/Landlock) |
| 会话 | history.jsonl | thread-store |
| 运行隔离 | 共享 ~/.claude | 运行级 CODEX_HOME |
| 子代理 | Task 工具 + 独立模型变量 | 模型路由/配置 |
| 代码模式 | 无 | code-mode(省 token) |
| 可嵌入性 | Agent SDK(代码构建 agent) | ACP(协议连接 agent) |
| 失败信号 | terminal_reason | ACP 状态 + 语义停滞检测 |
Claude Code = 把「CLI 输出」协议化。 它是一台「自带 UI 的 agent 机器」,外部程序通过解析它的 JSON 输出流来遥控它。优点:简单、启动即用、生态成熟(hooks/subagents/Agent SDK);缺点:无沙箱、前端与引擎耦合、可编程性靠"解析文本流"。
Codex = 把「agent」做成一个 server。
它把 agent 引擎抽成 app-server,用 ACP(类 LSP 协议)让任意前端连接。优点:前后端解耦、真沙箱、Rust 性能、code-mode 等成本优化、IDE/CLI/桌面可共享同一引擎;缺点:架构更重、协议更复杂、生态相对新。
本质:两者代表了 agent harness 的两个代际——「流式事件」 vs 「结构化 RPC」,类似「日志驱动」vs「API 驱动」的关系。
api.deepseek.com/anthropic 兼容端点,Codex 走 api.deepseek.com/ 的 Responses API + models.json 模型目录。Multica(适配 26 种 agent CLI 的开源平台)的 server/pkg/agent/ 目录里,每个工具一个 Go 文件。两者启动方式的差异一望即知:
// claude.go —— 直接起 CLI,用 stream-json 流式协议
args := []string{
"--output-format", "stream-json",
"--input-format", "stream-json",
"--permission-mode", "bypassPermissions",
"--mcp-config", mcpConfigPath, // MCP 写临时文件传入
}
// codex.go —— 起 app-server 子进程,用 stdio 承载 ACP 协议
args := []string{"app-server", "--listen", "stdio://"}
stream_json_result.go、stream_scanner.go(解析 JSONL 流);Codex 侧有 acp_terminal.go、acp_usage.go、acp_deliverable.go(解析 ACP RPC 消息)。terminal_reason(prompt_too_long 等);Codex 用 codex_semantic_inactivity、codex app-server handshake timeout 等。这组源码对照,正是本文「单进程流式协议 vs app-server RPC 协议」结论的最硬证据。
来源:openai/codex 仓库(codex-rs 架构、app-server、ACP、sandboxing、code-mode 等 crate)、multica-ai/multica 仓库(
server/pkg/agent/claude.go、codex.go及acp_*.go)、DeepSeek 官方文档(Codex/Claude Code 接入配置)。标注「实证」的均来自源码或官方文档;标注「推断」的为架构判断。