# workspace 全景 · 153 个成员怎么分层

> codex-rs 的 members 列了 153 个 crate，按职责可以归成十二组：入口与终端界面、app-server 与传输、内核、工具与执行、沙箱与安全、扩展机制等。依赖方向很清楚：前端只认 app-server，app-server 驱动 codex-core，codex-core 再把工具、沙箱、MCP、模型调用、持久化分给几十个卫星 crate；TUI 甚至不直接依赖 codex-core。

- 作者：David（道雾轩）
- 专栏：Codex 源码解读（https://daiw.net/manual/codex-source.md）
- 最后更新：2026-09-29
- 原文：https://daiw.net/manual/codex-source/workspace-map
- 转载与引用：请注明出处并附原文链接（https://daiw.net/about/copyright）

# workspace 全景 · 153 个成员怎么分层

打开 `codex-rs/Cargo.toml`，`[workspace]` 的 `members` 列了 153 项。第一次看会晕，但它们不是平铺的：按职责能归成十来组，依赖方向也很清楚。这一篇给出一张分层地图，后面任何一个功能，都能先在这张图上定位到 crate，再翻进去读。

代码量沿用[专栏封面](https://daiw.net/manual/codex-source)的口径：只数 `.rs` 文件的物理行，去掉 `tests.rs`、`*_tests.rs`、`tests/` 目录与 `#[cfg(test)]` 块。153 个成员合计 4,770 个 `.rs` 文件、约 190 万行，去掉测试约 82 万行。

## 目录与命名

153 个成员里，108 个直接放在 `codex-rs/` 下，其余是三个子目录：

- `utils/`：26 个小工具库，如 `utils/absolute-path`、`utils/pty`、`utils/stream-parser`；
- `ext/`：16 个扩展 crate，建在扩展接口 `codex-extension-api`（就在 `ext/extension-api`）之上，如 `ext/goal`、`ext/memories`、`ext/mcp`；
- 另有 `memories/read`、`memories/write` 和测试辅助 `exec-server/tests/support`。

crate 名的规则写在根目录 `AGENTS.md` 第一条：目录名加 `codex-` 前缀，`core` 目录就是 `codex-core`。这条规矩不靠自觉，CI 脚本会逐个核对：

```python
def expected_package_name(path: Path) -> str | None:
    parts = path.relative_to(CARGO_RS_ROOT).parts
    if len(parts) == 2 and parts[1] == "Cargo.toml":
        directory = parts[0]
        return TOP_LEVEL_NAME_EXCEPTIONS.get(
            directory,
            directory if directory.startswith("codex-") else f"codex-{directory}",
        )
    if len(parts) == 3 and parts[0] == "utils" and parts[2] == "Cargo.toml":
        directory = parts[1]
        return UTILITY_NAME_EXCEPTIONS.get(directory, f"codex-utils-{directory}")
    return None
```

（`.github/scripts/verify_cargo_workspace_manifests.py:211`）

顶层目录是 `codex-<目录名>`（目录本身已带 `codex-` 前缀的，如 `codex-api`、`codex-mcp`，原样保留），`utils/` 下是 `codex-utils-<目录名>`；登记在案的例外只有两个：`windows-sandbox-rs` 叫 `codex-windows-sandbox`，`utils/path-utils` 叫 `codex-utils-path`。`ext/` 不在检查范围内，名字多是 `codex-<名>-extension` 的形式，例如 `ext/goal` 是 `codex-goal-extension`、`ext/items` 是 `codex-extension-items`，搜代码时要留意。

<Callout type="info">
  `members` 并不是全部。`chatgpt`、`message-history`、`windows-sandbox-rs` 三个目录没列在里面，但它们是 workspace 目录内的 path 依赖，Cargo 会自动把它们算作成员，测试辅助 crate `core_test_support`、`app_test_support` 也一样。其中 Windows 沙箱 `windows-sandbox-rs` 本身就有约 1.9 万行非测试代码，上面的总数没有计入它们。
</Callout>

## 按职责分成十二组

下面的分组是本文按职责划的，不是仓库里的正式分类，但每个成员都恰好落在一组里：

| 分组 | 成员数 | 非测试代码 | 代表成员 |
| --- | --- | --- | --- |
| 入口与终端界面 | 10 | 约 24.2 万行 | `tui`、`cli`、`exec`、`cloud-tasks`、`file-search`、实时语音的 `realtime-webrtc` 与 `voice-host` |
| app-server 与传输 | 12 | 约 8.4 万行 | `app-server`、`app-server-protocol`、`app-server-transport`、`app-server-daemon`、`app-server-client`、`uds` |
| 内核 | 7 | 约 13.8 万行 | `core`、`protocol`、`core-api`、`context-fragments`、`prompts`、`history` |
| 工具与执行 | 11 | 约 5.7 万行 | `exec-server`、`tools`、`shell-command`、`apply-patch`、`file-system`、`code-mode` 一族 |
| 沙箱、网络与安全 | 10 | 约 3.8 万行 | `network-proxy`、`linux-sandbox`、`sandboxing`、`bwrap`、`execpolicy`、`guardian-context` |
| 扩展机制 | 30 | 约 11.3 万行 | `core-plugins`、`rmcp-client`、`codex-mcp`、`hooks`、`skills`、`plugin`、`ext/` 下 16 个、`memories/*`、`external-agent-migration` |
| 模型与认证 | 16 | 约 2.9 万行 | `login`、`codex-api`、`codex-client`、`model-provider`、`models-manager`、`ollama`、`lmstudio` |
| 配置 | 5 | 约 2.1 万行 | `config`、`features`、`cloud-config` |
| 持久化 | 5 | 约 4.5 万行 | `thread-store`、`state`、`rollout`、`rollout-trace` |
| 遥测与反馈 | 5 | 约 1.5 万行 | `analytics`、`otel`、`feedback` |
| 云端后端客户端 | 4 | 约 0.5 万行 | `backend-client`、`codex-backend-openapi-models`、`cloud-tasks-client` |
| 基础库与工程辅助 | 38 | 约 2.9 万行 | `utils/` 下 26 个、`http-client`、`arg0`、`install-context`、`git-utils`、`test-binary-support` |

两个数字值得多看一眼。“入口与终端界面”一组占了近三成代码，几乎全是 `tui` 一个 crate；“扩展机制”成员最多，这是后面第 5 部分的地盘。

## 依赖怎么流

按各 crate `Cargo.toml` 的 `[dependencies]`（含平台相关依赖，不含 dev-dependencies）把主干画出来，箭头指向被依赖的一方，图里只画了主干边：

```mermaid
flowchart TB
  subgraph L1[入口]
    CLI[codex-cli<br/>二进制 codex]
    ARG0[codex-arg0]
  end
  subgraph L2[前端]
    TUI[codex-tui]
    EXEC[codex-exec]
  end
  subgraph L3[app-server 层]
    ASC[codex-app-server-client]
    AS[codex-app-server]
    ASP[codex-app-server-protocol]
    EXT[ext 下的扩展<br/>goal、memories、mcp 等]
  end
  subgraph L4[内核]
    CORE[codex-core]
    EAPI[codex-extension-api]
  end
  subgraph L5[能力]
    TOOLS[codex-tools]
    EXS[codex-exec-server]
    SBX[codex-sandboxing]
    LSB[codex-linux-sandbox]
    MCP[codex-mcp]
    API[codex-api]
    CFG[codex-config]
    STORE[codex-thread-store<br/>codex-rollout、codex-state]
  end
  PROTO[codex-protocol]
  CLI --> TUI & EXEC & AS & ARG0
  TUI --> ASC & ASP
  EXEC --> ASC & CORE
  ASC --> AS
  ASC -.->|legacy_core 转手配置类型| CORE
  AS --> CORE & ASP & EXT
  EXT --> CORE & EAPI
  CORE --> EAPI & TOOLS & EXS & SBX & MCP & API & CFG & STORE & PROTO
  ARG0 --> LSB
  LSB --> SBX
  ASP --> PROTO
```

从图里能读出几条贯穿全书的事实。

**TUI 不依赖 `codex-core`。** `codex-rs/tui/Cargo.toml` 的依赖里有 `codex-app-server-client`、`codex-app-server-protocol`、`codex-app-server-daemon`，却没有 `codex-core`：会话里的一切都要变成对 app-server 的请求。还没迁完的几条启动与配置路径，经客户端 crate 里的一个过渡模块转手：

```rust
/// Transitional access to core-only embedded app-server types.
///
/// New TUI behavior should prefer the app-server protocol methods. This
/// module exists so clients can remove a direct `codex-core` dependency
/// while legacy startup/config paths are migrated to RPCs.
pub mod legacy_core {
    pub mod config {
        pub use codex_core::config::*;

        pub mod edit {
            pub use codex_core::config::edit::*;
        }
    }
}
```

（`codex-rs/app-server-client/src/lib.rs:71`）

`codex-exec` 还直接依赖 `codex-core`，但它的运行同样经由进程内的 app-server。这个“前端只认 app-server”的结构，是[一条消息的生命周期](https://daiw.net/manual/codex-source/message-lifecycle)和整个第 1 部分的出发点。

**`codex-core` 是依赖的枢纽。** 它的 `[dependencies]` 里有 68 个本仓库 crate；153 个成员中有 23 个直接依赖它，直接依赖 `codex-protocol` 的则有 76 个。`codex-protocol` 定义了内核与外界之间的词汇：提交给内核的 `Op`、内核发出的 `EventMsg`、与模型往来的 `ResponseItem`，几乎人人都要用。

**卫星 crate 是刻意拆出来的。** `AGENTS.md` 专门有一节要求抵制往 `codex-core` 里加代码（见[读源码之前](https://daiw.net/manual/codex-source/reading-the-source)），于是工具规格（`codex-tools`）、上下文片段（`codex-context-fragments`）、提示词模板（`codex-prompts`）、扩展接口（`codex-extension-api`）都各自成 crate。扩展 crate 的依赖方向也值得注意：`codex-extension-api` 本身不依赖 `codex-core`；`ext/` 下需要内核能力的扩展（`goal`、`memories`、`mcp`、`web-search` 等）依赖 `codex-core`，由 app-server 在 `codex-rs/app-server/src/extensions.rs` 里装配；`codex-core` 自己只直接依赖其中少数几个，如 `codex-skills-extension`、`codex-guardian-reviewer`。

**Linux 沙箱是反着挂的。** 不是 `codex-sandboxing` 依赖 `codex-linux-sandbox`，而是反过来：沙箱助手是 `codex-arg0` 在程序名为 `codex-linux-sandbox` 时调起的独立入口（见[上一篇](https://daiw.net/manual/codex-source/build-and-run)），它的 bubblewrap 由 `codex-bwrap` 从 `codex-rs/vendor/bubblewrap` 下的 C 源码编出来。

## 最大的几个 crate

| crate | 非测试代码 | 做什么 | 本专栏 |
| --- | --- | --- | --- |
| `codex-tui` | 205,740 行 | 终端界面 | 第 6 部分 |
| `codex-core` | 113,796 行 | agent 内核：线程、Session、`run_turn`、工具路由与编排 | 第 2、3 部分 |
| `codex-app-server` | 43,575 行 | 所有前端共用的服务端 | 第 1 部分 |
| `codex-exec-server` | 26,595 行 | 命令执行与文件操作服务，可以跑在另一台机器上 | [exec-server](https://daiw.net/manual/codex-source/exec-server) |
| `codex-core-plugins` | 22,632 行 | 插件与 marketplace | [插件](https://daiw.net/manual/codex-source/plugins) |
| `codex-app-server-protocol` | 21,360 行 | app-server 协议类型与 schema 生成 | [v2 协议](https://daiw.net/manual/codex-source/app-server-protocol) |
| `codex-cli` | 20,670 行 | 命令行入口与各子命令 | 本部分 |
| `codex-protocol` | 20,256 行 | 内核协议 `Op`、`EventMsg`、`ResponseItem` 等 | 全书 |
| `codex-config` | 17,443 行 | 分层配置加载 | [配置系统](https://daiw.net/manual/codex-source/config-system) |
| `codex-thread-store` | 16,649 行 | 线程存储 | [会话持久化](https://daiw.net/manual/codex-source/rollout-and-storage) |
| `codex-network-proxy` | 16,437 行 | 联网权限的代理 | [网络代理](https://daiw.net/manual/codex-source/network-proxy) |
| `codex-rmcp-client` | 15,562 行 | MCP 客户端的传输与 OAuth | [MCP 客户端](https://daiw.net/manual/codex-source/mcp-client-oauth) |

另一头是一批小 crate：前端与服务端之间的整个客户端层 `codex-app-server-client` 不到 1,900 行，`codex-arg0` 约 540 行；最小的 `codex-collaboration-mode-templates` 只有两行 Rust，用 `include_str!` 把 `default.md`、`plan.md` 两份协作模式模板编进二进制。

作为参照，[Grok Build](https://daiw.net/manual/grok-build/workspace-map) 的 workspace 是 96 个 crate，[OpenCode](https://daiw.net/manual/opencode/monorepo-map) 是 36 个 TypeScript 包。Codex 的成员数最多，从上面的分组看，很大一部分来自内核周边拆出来的小 crate 和 `utils/` 下的工具库。

---

上一篇：[从源码构建与运行 · Cargo、Bazel 与 npm 包装](https://daiw.net/manual/codex-source/build-and-run) · 下一篇：[读源码之前 · 仓库的工程约定](https://daiw.net/manual/codex-source/reading-the-source)
