<p align="center"><strong>Codex CLI</strong> is a coding agent from OpenAI that runs locally on your computer.
<p align="center">
  <img src="https://github.com/openai/codex/blob/main/.github/codex-cli-splash.png" alt="Codex CLI splash" width="80%" />
</p>
</br>
If you want Codex in your code editor (VS Code, Cursor, Windsurf), <a href="https://developers.openai.com/codex/ide">install in your IDE.</a>
</br>If you want the desktop app experience, run <code>codex app</code> or visit <a href="https://chatgpt.com/codex?app-landing-page=true">the Codex App page</a>.
</br>If you are looking for the <em>cloud-based agent</em> from OpenAI, <strong>Codex Web</strong>, go to <a href="https://chatgpt.com/codex">chatgpt.com/codex</a>.</p>

社区维护分支版本的 [OpenAI Codex CLI](https://github.com/sohaha/zcodex)，由 [sohaha](https://github.com/sohaha) 维护。

## 配置入口

除了官方支持的 `~/.codex/config.toml`，还可以使用 `~/.codex/zconfig.toml` 追加社区分支配置。

启动时 Codex 会尝试加载 `$CODEX_HOME/.env`（默认 `~/.codex/.env`）并注入到 codex-cli 自身进程环境中；文件不存在时会静默跳过。出于安全边界控制，`.env` 中以 `CODEX_` 开头的变量会被忽略，不能用它覆盖 `CODEX_HOME`、`CODEX_API_KEY` 等 Codex 自身控制变量。

```dotenv
MY_PROVIDER_KEY=...
CUSTOM_BASE_URL=https://example.com/v1
# 不会生效：CODEX_API_KEY=...
```

### 进行环境初始化

在项目根目录下执行：

```bash
codex zinit
```

### 开启 ZDocs

ZDocs 是项目级文档知识库：

```toml
[features]
zdocs = true

[zdocs]
# 反射审查窗口天数，默认 7 天
reflection_review_window_days = 7
```

codex 启动之后，执行 `/zdocs` 初始化项目级文档知识库。

### 登录与 API 配置

`codex login` 提供多种认证方式：

- **交互式 API 配置向导**：`codex login --api` —— 打开 TUI 向导，交互式输入 API Key、Base URL，选择协议类型和默认模型，完成后自动写入 `config.toml`。
- **标准输入直写 API Key**：`printenv MY_API_KEY | codex login --with-api-key` —— 从 stdin 读取密钥，直接写入配置。
- **标准输入直写 Access Token**：`printenv CODEX_ACCESS_TOKEN | codex login --with-access-token` —— 用于 OAuth 场景。
- **设备码流程**：`codex login --device-auth` —— 通过设备码完成 OAuth 登录。

不带参数运行 `codex login` 会显示当前认证状态。

### 模型渠道

通过 `[model_providers.<名称>]` 配置自定义渠道，然后用 `model_provider` 或命令行 `-P <名称>` 选择。

#### Anthropic 兼容接口

```toml
[model_providers.cc]
# 使用方式：codex -P cc
api_key = "xxx"
# 接口地址，注意需要 /v1
base_url = "https://api.anthropic.com/v1"
# 默认模型
model = "claude-sonnet-4-20250514"
# 协议类型
wire_api = "anthropic"

# 如果上游没有 /models 接口，再手动填写模型列表。
# 不填写 model_catalog 时，/model 会尝试从远程 /models 获取模型。
# model_catalog = ["claude-sonnet-4-20250514", "claude-3-7-sonnet-20250219"]

# 最大重试次数（默认 4）
request_max_retries = 8
# 流式空闲超时
stream_idle_timeout_ms = 60000
# 重试基础延迟
retry_base_delay_ms = 500
# 覆盖模型真实上下文大小
model_context_window = 158000
# 达到此 token 数触发 compact
model_auto_compact_token_limit = 148000
# 最大输出 token 数
max_output_tokens = 16384
# 跳过推理弹窗
skip_reasoning_popup = true
# 不完全兼容 Anthropic thinking 的安全降级开关
# anthropic_explicit_disable_thinking = true
```

如果使用标准 Claude `.credentials.json`，可以把 `api_key` 指向凭据来源：

```toml
[model_providers.claude]
api_key = "http://xxx.com/.claude/.credentials.json"
model = "claude-sonnet-4-20250514"
wire_api = "anthropic"
```

本地文件也可以直接使用：

```toml
[model_providers.claude_local]
api_key = "file://../.claude/.credentials.json"
model = "claude-sonnet-4-20250514"
wire_api = "anthropic"
```

当 `api_key` 直接填写 `http://`、`https://` 或 `file://` 时，会被识别为 **Anthropic 专用** 的凭据来源语义，并且只能和 `wire_api = "anthropic"` 搭配使用。

其中 `file://` 支持相对路径：如果路径不是绝对路径，会按 `codex_home` 目录解析成绝对路径后再读取。

凭据文件应使用标准 Claude 结构：

```json
{
  "claudeAiOauth": {
    "accessToken": "...",
    "expiresAt": 1780457749965
  }
}
```

该模式的行为如下：

- 未配置 `base_url` 时，默认使用 `https://api.anthropic.com/v1`
- 未显式配置 `anthropic_compat` 时，默认开启 Claude Code 兼容伪装

#### Chat Completions 兼容接口

```toml
[model_providers.chat]
api_key = "sk-xxx"
base_url = "https://api.openai.com/v1"
model = "gpt-5.2"
wire_api = "chat"
```

### `/model` 模型列表

打开 `/model` 时，如果当前渠道没有配置 `model_catalog` / `model_catalog_json`，会自动请求该渠道的远程 `/models` 接口并展示返回的模型。

- 上游支持 `/models`：通常不需要手写模型列表。
- 上游不支持 `/models`：在对应 `[model_providers.xxx]` 里配置 `model_catalog`。
- 需要更详细的模型元数据：使用顶层 `model_catalog_json` 指向 JSON 文件。
- 手动配置的 `model_catalog` 优先作为静态模型列表。

#### `model_catalog` vs `model_catalog_json`

| 配置方式 | 位置 | 类型 | 适用场景 |
|---|---|---|---|
| `model_catalog` | `[model_providers.xxx]` 内 | `["slug1", "slug2"]` 字符串数组 | 仅列出可用模型 slug |
| `model_catalog_json` | `config.toml` 顶层 | 文件路径，指向 JSON | 为每个模型配完整元数据 |

#### `model_catalog_json` 完整模型配置

在 `config.toml` 顶层指定一个 JSON 文件路径：

```toml
model_catalog_json = "~/.codex/my-catalog.json"
```

JSON 格式为 `{"models": [ModelInfo, ...]}`，每个模型支持以下字段：

```json
{
  "models": [
    {
      "slug": "my-model-v1",
      "display_name": "My Model V1",
      "description": "自定义模型描述",
      "context_window": 128000,
      "max_context_window": 128000,
      "auto_compact_token_limit": 115200,
      "default_reasoning_level": "medium",
      "supported_reasoning_levels": [
        {"effort": "low", "description": "快速响应"},
        {"effort": "medium", "description": "平衡速度与深度"},
        {"effort": "high", "description": "深度推理"}
      ],
      "input_modalities": ["text", "image"],
      "shell_type": "default",
      "supports_parallel_tool_calls": false,
      "supports_search_tool": true,
      "base_instructions": "你是一个编程助手。",
      "service_tiers": [
        {"id": "priority", "name": "Fast", "description": "1.5x 速度"}
      ],
      "truncation_policy": {"mode": "tokens", "limit": 10000},
      "apply_patch_tool_type": "freeform",
      "web_search_tool_type": "text",
      "visibility": "list",
      "priority": 0,
      "supported_in_api": true
    }
  ]
}
```

**常用字段说明：**

- `slug` — 模型 ID，必须与 provider 返回的模型 ID 一致
- `display_name` — 模型选择器中显示的名称
- `description` — 模型描述，可选
- `context_window` / `max_context_window` — 上下文窗口 token 数
- `auto_compact_token_limit` — 自动压缩阈值（不设则默认 context_window 的 90%）
- `default_reasoning_level` — 默认推理级别：`none`、`low`、`medium`、`high`、`xhigh`
- `supported_reasoning_levels` — 可选推理级别列表
- `input_modalities` — 输入类型：`["text"]` 或 `["text", "image"]`
- `base_instructions` — 模型的 system prompt 模板
- `model_messages.instructions_template` — 支持 `{{ personality }}` 占位符的模板（用于 personality 功能）
- `service_tiers` — 服务层级配置（如 fast/priority）
- `apply_patch_tool_type` — `"freeform"` 启用自由格式 patch，`null` 使用标准函数工具
- `shell_type` — Shell 工具类型：`"default"`、`"shell_command"`
- `truncation_policy` — 输出截断策略，默认 `{"mode": "tokens", "limit": 10000}`
- `visibility` — `"list"` 在选择器中显示，`"hidden"` 隐藏
- `priority` — 排序优先级，数值越小越靠前

渠道 `[model_providers.xxx]` 上的以下字段也会应用到该渠道的模型：

- `model_context_window` — 覆盖上下文窗口大小
- `model_auto_compact_token_limit` — 覆盖自动压缩阈值
- `max_output_tokens` — 最大输出 token 数
- `skip_reasoning_popup` — 跳过推理级别选择弹窗

> 内置 catalog 示例参考 `codex-rs/models-manager/models.json`。

### 供应商回退

支持全局和渠道两级回退配置。请求失败时按优先级依次尝试下一个渠道，直到成功或全部失败。

#### 全局回退

在 `config.toml` 顶层配置，适用于当前选中的渠道失败后：

```toml
fallback_providers = [
    { provider = "cc" },
    { provider = "chat", model = "gpt-5.2" },
]
```

#### 渠道级回退

在 `[model_providers.xxx]` 内配置 `fallback_providers`，仅当该渠道作为主渠道失败时生效，且优先于全局回退链：

```toml
[model_providers.primary]
base_url = "https://api.primary.com/v1"
env_key = "PRIMARY_API_KEY"
model = "primary-model"
# 当前渠道失败时，先尝试 fallback-a，再尝试 fallback-b
fallback_providers = [
    { provider = "fallback-a", model = "model-a" },
    { provider = "fallback-b" },
]

[model_providers.fallback-a]
base_url = "https://api.fallback-a.com/v1"
env_key = "FALLBACK_A_API_KEY"

[model_providers.fallback-b]
base_url = "https://api.fallback-b.com/v1"
env_key = "FALLBACK_B_API_KEY"
```

**回退优先级**：渠道级 `fallback_providers` → 全局 `fallback_providers`。同一 provider 不会重复尝试。

#### 旧版单渠道回退

`fallback_provider` + `fallback_model` 是旧版配置，功能等价于 `fallback_providers` 的单条目形式，优先级最高：

```toml
fallback_provider = "cc"
fallback_model = "claude-sonnet-4-20250514"
```

#### 模型分流路由

`[model_routing]` 可以按每次请求的内容自动选择渠道、模型和推理强度。适合把简单说明、文档阅读分到快模型，把项目分析、常规编码分到日常模型，把 bug 修复和安全、权限、密钥等高风险任务分到强模型。

```toml
[model_routing]
enabled = true
# observe 只提示会如何分流；确认后再改成 enforce 正式启用。
mode = "observe"

[model_routing.profiles.fast]
model = "gpt-5.4-mini"
reasoning = "low"

[model_routing.profiles.daily]
model = "gpt-5.4"
reasoning = "medium"

[model_routing.profiles.safe]
model = "gpt-5.4"
reasoning = "high"

[[model_routing.rules]]
name = "docs-fast"
profile_ref = "fast"
priority = 10

[model_routing.rules.condition]
task_types = ["low_risk", "explorable"]
instruction_patterns = ["explain", "summarize", "解释", "总结"]
path_patterns = ["docs/**/*.md", "README.md"]

[[model_routing.rules]]
name = "project-analysis-daily"
profile_ref = "daily"
priority = 40

[model_routing.rules.condition]
instruction_patterns = ["analyze", "review", "inspect", "trace", "分析", "评审", "检查", "梳理"]
path_patterns = ["**/*.rs", "**/*.ts", "**/*.tsx", "**/*.js", "**/*.py", "**/*.go"]

[[model_routing.rules]]
name = "coding-daily"
profile_ref = "daily"
priority = 50

[model_routing.rules.condition]
task_type = "medium_risk"
instruction_patterns = ["implement", "change", "modify", "refactor", "编写", "实现", "修改", "重构"]

[[model_routing.rules]]
name = "bugfix-safe"
profile_ref = "safe"
priority = 90

[model_routing.rules.condition]
instruction_patterns = ["bug", "fix", "failure", "crash", "regression", "修复", "报错", "失败", "崩溃", "回归"]
path_patterns = ["**/tests/**", "**/*test*", "**/*spec*"]

[[model_routing.rules]]
name = "security-safe"
profile_ref = "safe"
priority = 100

[model_routing.rules.condition]
task_type = "high_risk"
instruction_patterns = ["auth", "permission", "secret", "认证", "权限", "密钥"]
path_patterns = ["**/auth/**", "**/security/**", "**/migrations/**"]
```

- `mode = "observe"`：只提示命中的路由，不切换模型。
- `mode = "enforce"`：命中后切换到对应 profile。
- `priority` 越大优先级越高；同优先级冲突时会保留当前模型并提示 warning。
- `task_type` / `task_types` 支持 `low_risk`、`medium_risk`、`high_risk`、`explorable`、`unknown`。
- `path_patterns` 是对 prompt 中提到的路径或 `@` 提及路径做 glob 匹配；例如提到 `README.md` 或 `docs/config.md` 时可以命中文档规则。
- 显式触发的技能模型路由优先于 `[model_routing]`。
- 不建议把 `[model_routing]` 放进项目本地配置，避免仓库内容静默改变用户的模型渠道。

### 技能模型路由

技能可以指定自己的渠道、模型和推理强度。只有显式触发该技能时生效。

在 `SKILL.md` 中声明：

```yaml
---
name: code-review
description: Review code changes.
metadata:
  codex:
    model_provider: cc
    model: claude-sonnet-4-20250514
    model_reasoning_effort: high
---

## Quickstart

### Installing and running Codex CLI

Run the following on Mac or Linux to install Codex CLI:

```shell
curl -fsSL https://chatgpt.com/codex/install.sh | sh
```

Run the following on Windows to install Codex CLI:

```
powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"
```

Codex CLI can also be installed via the following package managers:

```shell
# Install using npm
npm install -g @openai/codex
```

也可以在用户配置中覆盖：

```toml
[[skills.config]]
name = "code-review"
enabled = true
model_provider = "chat"
model = "gpt-5.2"
model_reasoning_effort = "medium"
```

如果渠道不存在、模型不可用或推理强度不支持，会保留当前会话配置并提示 warning。

### 子代理模型路由

子代理支持为单次 `spawn_agent` 指定模型和推理强度，也支持在自定义角色配置文件中固定默认值。

工具调用示例：

```json
{
  "message": "检查这次改动的风险点。",
  "agent_type": "reviewer",
  "model": "claude-sonnet-4-20250514",
  "reasoning_effort": "high",
  "fork_turns": "all"
}
```

自定义角色示例：

```toml
[agents.reviewer]
description = "代码审查子代理"
config_file = "./agents/reviewer.toml"
```

`./agents/reviewer.toml`：

```toml
model_provider = "cc"
model = "claude-sonnet-4-20250514"
model_reasoning_effort = "high"
developer_instructions = "重点审查正确性、兼容性和安全风险。"
```

## 会话管理命令

### `/zdelete` 或者 `codex zdelete`

打开删除会话选择器，选中会话后再次按回车执行永久删除；当前正在使用的会话不可删除。删除列表默认显示全部已保存会话，并提供“当前目录/全部”筛选；删除模式会额外展示项目路径，方便区分不同项目下同名或相近时间的会话。

### `/zexport`

将当前会话完整导出为 Markdown/HTML 文件。文件自动写入项目根目录，命名格式为 `codex-session-<时间戳>`，包含元信息和完整对话记录。导出完成后 TUI 内会显示文件路径。

## 图片粘贴压缩

在 TUI 中粘贴图片时会自动进行压缩处理，默认配置如下：

```toml
[tui]
# 是否自动压缩粘贴的图片（默认 true）
auto_compress_pasted_images = true
# 粘贴图片最大宽度（默认 1280）
pasted_image_max_width = 1280
# 粘贴图片最大高度（默认 720）
pasted_image_max_height = 720
# JPEG 编码质量 1-100（默认 85）
pasted_image_jpeg_quality = 85
```

**压缩逻辑**：
- 尺寸调整：如果图片宽/高超过配置的限制，会使用 Triangle filter 缩放到限制范围内
- 格式选择：
  - 对于不透明图片：自动比较 PNG 和 JPEG 编码大小，选择较小的格式
  - 对于有透明度图片：强制使用 PNG 格式（保留透明度）
- JPEG 质量：使用配置的质量值（默认 85）

## ACP 调用

使用 `npx -y -p @sohaha/zcodex codex-acp` 命令调用 ACP 服务。

具体配置请参考对应的工具文档。

## Codex Desktop 本地补强

`codex app` 在 macOS 和 Windows 上打开或安装 Codex Desktop。当前认证模式为 API Key 时，会在启动桌面端前执行本地能力补强：macOS 会确保桌面端内置 CLI 指向可用的 `zcodex-cli`，并修复已缓存的 Computer Use 插件签名；Windows 会定位 Codex Appx 安装目录，在管理员权限下备份并替换内置 `codex.exe`，随后重新校验 `zcodex-cli` 版本。

非 API Key 模式不会执行这些 API Key 专属补强。

## 更新日志

### v1.2.2

- **会话列表不再按供应商隔离**：`codex resume` 选择器和 `--last` 恢复现在返回所有供应商的会话，切换渠道（`-P`）后仍可看到并继续之前在其他渠道创建的会话。

### v1.3.1

- **支持 Claude Code 订阅模式**：配置 api_key = `.credentials.json` 文件路径 + wire_api = "anthropic" 即可开启。

- **支持 Devin 订阅模式**：配置 api_key = `devin key` + wire_api = "devin" 即可开启。

### v1.4.1

- **支持 ACP 调用**

### v1.4.2

- **ENV 文件加载**
