仓库不是一个 CLI 文件
在本教材冻结的 commit 上,主实现位于 codex-rs/ Rust workspace。它把交互面、核心运行时、协议、执行工具与平台安全拆成多个 crate。阅读时最危险的做法是从目录名逐个扫描;更有效的是沿一次任务的数据流建立地图。
flowchart TB subgraph Surfaces["交互表面"] CLI["cli<br/>参数与子命令"] TUI["tui<br/>终端 UI"] EX["exec<br/>非交互执行"] AS["app-server<br/>产品集成协议"] end subgraph Runtime["核心运行时"] CORE["core<br/>Session / Turn / Context / Tools"] PROTO["protocol<br/>Op / Event / wire types"] CONFIG["config<br/>配置加载与约束"] end subgraph Action["执行与边界"] TOOLS["core/tools<br/>router / registry / handlers"] EXEC["exec / exec-server<br/>进程执行"] SANDBOX["linux-sandbox / seatbelt<br/>平台隔离"] end CLI --> TUI CLI --> EX TUI --> CORE EX --> CORE AS --> CORE CORE <--> PROTO CORE --> CONFIG CORE --> TOOLS TOOLS --> EXEC EXEC --> SANDBOX
大型 workspace 中,同一个概念会跨入口、协议、核心和平台实现,单文件阅读容易误判。
按职责分层,再沿用户输入到 Event 的链路逐层阅读。
交互、协议、决策和副作用分开后,既能复用核心也便于测试边界。
cli/tui/exec/app-server → core → protocol/tools → exec/sandbox。
目录和类型会随版本调整;本地图只对冻结 commit 可追溯,不替代 Cargo 图。
第一层:交互表面
codex-rs/cli
参数解析与总入口。它决定运行 TUI、exec、MCP、App Server 等哪条路径。
codex-rs/tui
交互式终端界面:输入、消息呈现、审批、diff、状态等。理解 Agent Loop 不应从这里开始,但调 UI/Event 映射要回来读它。
codex-rs/exec
非交互模式,适合脚本和自动化。官方也提供 Non-interactive mode 文档。
codex-rs/app-server
为客户端集成提供服务端协议。它不是模型服务端本身,而是把本地 Codex 能力暴露给产品表面。协议说明见官方 App Server。
第二层:核心运行时
codex-rs/core
最值得投入阅读时间的 crate:
core/src/
├─ session/ Session、submission loop、Turn
├─ tasks/ 普通任务、compact 等任务封装
├─ context_manager/ 历史与模型上下文
├─ tools/ ToolSpec、router、registry、handlers
├─ config/ 运行时配置模型
├─ rollout/ 会话轨迹
├─ thread_manager.rs Thread 创建、恢复、fork
├─ codex_thread.rs 对外控制句柄
├─ compact.rs 上下文压缩
└─ agents_md.rs 仓库指令发现
codex-rs/protocol
跨界面的共同语言。先读 Op、Event、EventMsg、审批和沙箱策略,再看具体消费者。
codex-rs/config
负责配置来源、加载和约束;core 再把结果组装为运行时 Config。分开后,配置发现和业务使用不必耦在一起。
第三层:动作与隔离
core/src/tools
它不是“一堆函数”,而是一条能力管线:
spec → router → registry → orchestrator → handler → output
codex-rs/exec*
处理进程执行、I/O 与相关协议。Shell handler 最终需要这些更底层能力。
平台 sandbox crates
仓库包含 Linux sandbox、macOS Seatbelt 相关代码及 Windows 支持路径。平台细节不同,但上层通过共同策略表达读写与网络意图。
推荐阅读顺序
45 分钟:建立骨架
- 根
README.md与codex-rs/README.md; cli/src/main.rs::cli_main;protocol/src/protocol.rs::{Op, EventMsg};core/src/codex_thread.rs。
90 分钟:追一次 Turn
thread_manager.rs::spawn_thread;session/mod.rs::Session::spawn;session/turn.rs::run_turn;stream_events_utils.rs::handle_output_item_done。
90 分钟:追一次工具
tools/router.rs;tools/registry.rs;tools/orchestrator.rs;tools/handlers/shell.rs;tools/handlers/apply_patch.rs。
读源码时记录四种证据
| 证据 | 能证明什么 |
|---|---|
| 类型与枚举 | 系统公开建模了哪些状态 |
| 控制流 | 某个版本实际怎样串联 |
| 测试 | 维护者认为哪些行为必须保持 |
| 文档 | 面向用户承诺的稳定表面 |
下一章不再只问“怎么实现”,而问 Codex 为什么这样设计。