# Codex CLI 是什么 · 开源的是哪一部分

> Codex CLI 是 OpenAI 在你本机运行的编码 agent，仓库 openai/codex 以 Apache-2.0 开源。开源的是本地这一侧：Rust 写的 CLI、TUI、app-server、agent 内核、工具与三套沙箱，外加 npm 启动器和 TypeScript、Python 两个 SDK；模型、ChatGPT 后端、IDE 扩展与桌面应用都不在仓库里。npm 包里的 codex.js 只是一个挑平台二进制、转发信号的启动器。

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

# Codex CLI 是什么 · 开源的是哪一部分

仓库根目录 `README.md` 的第一句是：Codex CLI is a coding agent from OpenAI that runs locally on your computer——OpenAI 出品、在你本机运行的编码 agent。它读你的代码、改文件、跑命令、调 MCP 工具：模型推理在云端，这些动作都在你的机器上执行。

本专栏读的就是这份代码：[github.com/openai/codex](https://github.com/openai/codex)，Apache-2.0 许可，2025-04-13 建仓，基准 tag `rust-v0.158.0`（版本、commit 与统计口径见[专栏封面](https://daiw.net/manual/codex-source)）。这一篇先回答两个问题：这个仓库里到底有什么，没有什么。

## 先看它怎么用

`README.md` 给了四种安装方式：官方安装脚本（`install.sh`、`install.ps1`）、npm 包 `@openai/codex`、Homebrew 的 `codex` cask，以及 GitHub Release 里的单文件二进制（Linux 版用 musl 目标构建，文件名形如 `codex-x86_64-unknown-linux-musl`）。装好之后：

- 直接敲 `codex`，进入全屏终端界面（TUI），也就是日常用的交互模式；
- `codex exec "..."` 非交互地跑完一个任务，适合脚本和 CI；
- `codex app-server` 把同一套 agent 以 JSON-RPC 服务的形式开放出去，IDE 扩展、Python SDK 等都通过它接入。

`codex-rs/cli/src/main.rs:143` 的 `Subcommand` 枚举一共 30 个变体，其中 4 个标了 `hide = true`（`tcp-tunnel`、`execpolicy`、`responses-api-proxy`、`stdio-to-uds`），属于内部工具。各命令的用法、登录方式与配置，见[《Codex 中文手册》](https://daiw.net/manual/codex)的[安装、登录与升级](https://daiw.net/manual/codex/installation)和[启动命令行选项](https://daiw.net/manual/codex/cli-flags)，这里不重复。

## 仓库里有什么

git 跟踪的 8,670 个文件里，8,145 个在 `codex-rs/` 下。顶层目录的分工如下：

| 目录 | 内容 |
| --- | --- |
| `codex-rs/` | Rust Cargo workspace，`members` 共 153 个：CLI、TUI、app-server、内核 `codex-core`、工具、沙箱、MCP、登录、持久化……发布出去的 `codex` 二进制全部出自这里 |
| `codex-cli/` | npm 包 `@openai/codex` 的外壳，运行时只有 `bin/codex.js` 一个文件，另有打包脚本 |
| `sdk/typescript/` | `@openai/codex-sdk`：启动 `codex exec --experimental-json`，经 stdin、stdout 交换 JSONL 事件 |
| `sdk/python/` | `openai-codex`：以 `codex app-server --listen stdio://` 启动子进程，走 JSON-RPC |
| `sdk/python-runtime/` | `openai-codex-cli-bin`：给 Python SDK 带上对应平台的 Codex 二进制，只发 wheel |
| `docs/` | 多数页面只剩一句指向 developers.openai.com 的链接，`install.md`、`contributing.md` 等少数几篇有正文 |
| `MODULE.bazel`、`defs.bzl`、`bazel/`、`patches/` | Bazel 构建（下一篇细讲） |
| `scripts/`、`.github/` | 打包发布脚本与 CI 工作流 |
| `.codex/skills/` | 仓库自带的 Codex skills：代码审查、PR 描述、远程测试等，供在这个仓库里干活的 Codex 使用 |
| `third_party/`、`tools/` | 第三方资源（`v8`、`wezterm` 等）与自有工具（`argument-comment-lint`、`buildifier`） |

`docs/` 几乎是空壳并非疏忽。根目录 `AGENTS.md` 明确要求不要往 `docs/` 里写面向用户的产品文档，官方文档另有去处，唯一的例外是 app-server 的 API 文档。

`NOTICE` 里还有一条值得一提：仓库包含从 Ratatui（MIT 许可）派生的代码，TUI 的终端渲染就建在 ratatui 之上。

## 不在仓库里的

开源的是“本机这一侧”。下图把仓库内外画在一起：

```mermaid
flowchart LR
  subgraph OSS[仓库 openai/codex 里的代码]
    NPM[codex-cli<br/>npm 启动器 codex.js]
    BIN[codex 二进制<br/>codex-rs]
    SDK[sdk<br/>TypeScript 与 Python]
  end
  subgraph REMOTE[不在仓库里]
    IDE[IDE 扩展]
    APP[桌面应用]
    MODEL[模型服务<br/>Responses API]
    CLOUD[ChatGPT 后端<br/>账号与 Codex Cloud]
  end
  NPM -->|spawn| BIN
  SDK -->|codex exec 或 app-server| BIN
  IDE -.->|codex app-server| BIN
  BIN -->|codex app 下载或打开| APP
  BIN -->|HTTPS 或 WebSocket| MODEL
  BIN -->|登录与 codex cloud| CLOUD
```

逐项看：

- **模型**：仓库里只有调用方。模型提供方的线协议枚举 `WireApi` 只剩一个变体 `Responses`（`codex-rs/model-provider-info/src/lib.rs:103`），注释写明是 OpenAI 在 `/v1/responses` 暴露的 Responses API；HTTP 与 WebSocket 客户端在 `codex-api`，怎么调用见[模型客户端](https://daiw.net/manual/codex-source/model-client)。
- **Codex Cloud**：`codex cloud` 子命令（crate `codex-cloud-tasks`）只是一个浏览云端任务、把 diff 应用到本地的客户端，默认后端地址是 `https://chatgpt.com/backend-api`（`codex-rs/cloud-tasks/src/lib.rs:55`）。后端接口的数据类型放在 `codex-backend-openapi-models`，它的 `lib.rs` 注明其中没有手写类型，全部由脚本从 OpenAPI 生成。
- **IDE 扩展**：源码不在这里，但留下了接入痕迹。`codex app-server` 以 `SessionSource::VSCode` 作为会话来源启动（`codex-rs/cli/src/main.rs:1270`），参数 `--analytics-default-enabled` 的注释说，这是给 VS Code 扩展这类第一方用例准备的（`codex-rs/cli/src/main.rs:591`）。扩展与 app-server 之间怎么通信，见 [app-server](https://daiw.net/manual/codex-source/app-server-architecture)。
- **桌面应用**：`codex app`（只在 macOS 与 Windows 上编译）负责打开或安装它，macOS 从 `persistent.oaistatic.com` 下载 DMG，Windows 走 Microsoft Store（`codex-rs/cli/src/desktop_app/`），应用本身不开源。

## npm 包里的 codex.js：一个启动器

很多人是 `npm install -g @openai/codex` 装上的，于是以为 Codex 是个 Node 程序。其实 `codex-cli/bin/codex.js` 不到 300 行，只做四件事：

1. 按 `process.platform` 和 `process.arch` 算出目标三元组，一共六种：Linux 的 x64 与 arm64（都用 musl）、macOS 的 x64 与 arm64、Windows 的 x64 与 arm64，找到对应的平台包；
2. 在平台包的 `vendor/<三元组>/bin/` 下找 `codex`（Windows 上是 `codex.exe`），找不到就按探测到的包管理器提示一条重装命令；
3. 探测是被 npm、bun、pnpm 还是 Vite+ 装上的，把结果写进环境变量；
4. 启动原生二进制，`stdio` 直通，转发终止信号，最后照搬子进程的退出方式。

第 3、4 步是这一段：

```js
const env = {
  ...process.env,
  CODEX_MANAGED_PACKAGE_ROOT: codexPackageRoot,
};
delete env.CODEX_MANAGED_BY_NPM;
delete env.CODEX_MANAGED_BY_BUN;
delete env.CODEX_MANAGED_BY_PNPM;
delete env.CODEX_MANAGED_BY_VITE_PLUS;
env[packageManagerEnvVar] = "1";

const child = spawn(binaryPath, process.argv.slice(2), {
  stdio: "inherit",
  env,
});
```

（`codex-cli/bin/codex.js:231`）

`CODEX_MANAGED_BY_*` 是写给 Rust 侧看的：`codex-install-context` crate 据此判断安装方式（`codex-rs/install-context/src/lib.rs:121` 的 `InstallContext::current`），升级提示才能给出对的命令。信号方面，`SIGINT`、`SIGTERM`、`SIGHUP` 原样转给子进程；子进程若被信号杀死，父进程用同一个信号结束自己，这样 shell 看到的退出码（128 加信号编号）与直接运行二进制时一致。平台包是怎么被挑中、装进 `node_modules` 的，留到[下一篇](https://daiw.net/manual/codex-source/build-and-run)讲。

## 读之前知道的两件事

**不收外部代码贡献。** `docs/contributing.md` 开宗明义：We do not accept external code contributions or pull requests。社区的参与方式是提 issue、给复现步骤和根因分析，代码由 Codex 团队来改。团队内部遵循的工程约定集中写在根目录 `AGENTS.md` 里，读代码前值得先过一遍，见[读源码之前](https://daiw.net/manual/codex-source/reading-the-source)。

**它也是写给 AI 看的。** `AGENTS.md` 里有这样的话：你在沙箱里运行，用 `shell` 工具时会设置 `CODEX_SANDBOX_NETWORK_DISABLED=1`（`AGENTS.md:9`）。这份开发规范的读者包括 Codex 自己，仓库的 `.codex/skills/` 也是为它准备的。

另外说一句版本：发布工作流 `.github/workflows/rust-release.yml` 只认 `rust-v*.*.*` 形式的 tag，`CHANGELOG.md` 第一句就把人指向 GitHub Releases 页面。本专栏的行号都固定在 `rust-v0.158.0` 上，你手上的版本若更新，细节可能已经变了。

## 和《Codex 中文手册》的分工

两本书读同一个版本，分工不同：

- [《Codex 中文手册》](https://daiw.net/manual/codex)依据官方文档整理，讲**怎么用**：命令、参数、配置项、斜杠命令、沙箱与审批的选项；
- 本专栏读 `rust-v0.158.0` 的源码，讲**怎么实现**：一个功能经过哪些 crate、数据怎么流、边界契约是什么。

所以每一篇都先用一两段交代“用户看到的样子”，并链接到手册的对应页面，然后翻进源码。遇到手册与代码对不上的地方，以代码为准并在文中点明。

## 和《从 LLM 到 Coding Agent》对照

[《从 LLM 到 Coding Agent》](https://daiw.net/manual/llm-to-agent)从[裸 API 调用](https://daiw.net/manual/llm-to-agent/raw-llm-api)起步，手搓了一个最小的 [agent 循环](https://daiw.net/manual/llm-to-agent/agent-loop)：问模型、执行工具、把结果喂回去、再问。Codex 的内核做的是同一件事，只是外面多了几层：一个所有前端共用的 app-server，三个操作系统各自的沙箱，一套审批与执行策略，以及会话持久化、上下文压缩和扩展机制。读完这一部分的[消息生命周期](https://daiw.net/manual/codex-source/message-lifecycle)，你会在代码里认出那个最小循环的每一步。

---

上一篇：[专栏封面](https://daiw.net/manual/codex-source) · 下一篇：[从源码构建与运行 · Cargo、Bazel 与 npm 包装](https://daiw.net/manual/codex-source/build-and-run)
