最近 Codex 这三个字在开发者圈子里出现频率非常高。和 GitHub Copilot、Cursor 这类“自动补全”工具不一样,Codex 是真正意义上的编程 Agent:你在终端里用自然语言描述一个需求,它会自己拆解任务、读项目代码、创建或修改文件、执行命令、根据报错继续调试,直到把活干完。这种体验第一次让很多开发者意识到,AI 编程的下一步不是“更聪明的补全”,而是“能独立干活的下属”。
但 Codex 的官方使用路径对不少人有门槛。OpenAI 账号、订阅费用、额度管理,每一项都足够让人犹豫。与此同时,越来越多的团队已经在把 DeepSeek 接入自己的工具链,DeepSeek 的 API 兼容 OpenAI 的 Chat Completions 协议,价格也更友好。一个很自然的想法就冒出来了:能不能让 Codex 的 Agent 工作流,跑在 DeepSeek 模型上?
答案是可以,而且实现方式并不神秘。核心思路是在中间加一层 API 适配代理:Codex CLI 把请求发给本地代理,代理把 OpenAI 的 Responses 协议转换成 DeepSeek 的 Chat Completions 协议,转发上去,再把响应转回来。社区喜欢管这叫“白嫖 Codex”,但从工程角度看,它真正解决的不是“省钱”这一个点,而是把“编程 Agent 前端”和“模型后端”解耦了。这篇文章我会从架构开始,完整演示 Codex + DeepSeek + CLIProxyAPI 的搭建过程,包括配置怎么写、请求怎么流转、常见报错怎么排查。
1. Codex 为什么值得关注:从自动补全到 Agent 式编程
如果你对 Codex 这个名字有印象,可能记起来 2021 年 OpenAI 发布过一个叫 Codex 的代码模型。现在这个名字被用于新的 AI 编程 Agent 产品,含义完全不同。Codex 不是一个“帮你补全下一行代码”的工具,而是一个能在终端里独立执行编程任务的 Agent。你给它一个目标,它会自己决定先看哪些文件、改哪些代码、跑哪些命令,然后根据结果继续迭代。
和传统补全工具相比,差异在工作模式上。Copilot 类工具是“人在回路里”:你写代码,它负责猜下一段。Codex 是“Agent 在回路里”:你提需求,它负责把活干完,你在旁边做检查和验收。比如你可以对它说:“帮我写一个脚本,把项目里所有 TODO 注释统计出来,按文件分组输出”,它会自己列出计划、创建脚本、运行给你看。如果运行报错,它还会读报错信息,修改代码再试一次。这种多步规划、工具调用、自我纠错的能力,才是 Agent 式编程的核心。
那它适合什么人?从当前社区的实践来看,最适合的场景有这么几类:
- 快速原型:把脑子里的想法直接描述出来,先跑通再人工优化。
- 代码重构:批量重命名、抽公共方法、改文件结构。
- 编写测试:让 Agent 根据已有代码生成单元测试和集成测试。
- 写一次性脚本:数据处理、日志分析、CI 脚本调试。
- 学习项目:快速读懂一个陌生仓库的结构和关键逻辑。
不适合的场景也有:大型系统的架构设计、对代码质量和稳定性要求极高的生产系统、完全不懂编程、无法判断 Agent 产出是否正确的用户。记住一个判断标准:Codex 是提高你编程效率的下属,不是代替你思考的架构师。你仍然需要对结果负责。
2. 为什么需要 CLIProxyAPI:协议差异与适配层原理
很多人第一次接触“Codex 接入 DeepSeek”时,第一反应是:Codex 配置里不是可以改 base_url 吗?直接把 base_url 改成 DeepSeek 的地址不就行了?
这里就是最容易踩的坑:Codex CLI 默认调用的是 OpenAI 的 Responses API,也就是 /v1/responses 这个端点,而 DeepSeek 对外提供的是 OpenAI 兼容的 Chat Completions API,也就是 /v1/chat/completions。两者在请求体结构、参数命名、工具调用格式、流式返回结构上都有差异。直接改 base_url,要么报错,要么模型不返回工具调用,Codex 无法执行命令和读写文件,整个 Agent 流程就废了。
CLIProxyAPI 这类工具解决的就是这个协议差异问题。它在你的本机起一个本地代理服务,Codex CLI 把请求发到本地代理,由代理完成三件事:
| 功能 | 说明 |
|---|---|
| 协议转换 | 把 OpenAI Responses API 请求转换成 Chat Completions 请求 |
| 模型名映射 | 把 Codex 请求的 gpt-5、o4-mini 映射成 deepseek-chat、deepseek-reasoner |
| API Key 注入 | 把 DeepSeek 的 Key 注入到转发到上游的请求中 |
打个比方,这就像电源转换头。Codex 是英式插头,DeepSeek 是美式插座,直接插是插不进去的,中间需要一个转换头。CLIProxyAPI 就是这个转换头。
这类工具在社区里的变体不少,有的叫 cliproxy,有的叫 cc-switch,有的叫 CLIProxyAPI,底层原理大同小异。它们通常都提供一条命令切换 Codex 的 Provider 配置,并自动启动本地代理。本文以社区里常见的 cc 命令为例做演示,具体安装包名和命令以你使用的项目 README 为准。
3. 整体架构与请求流转链路
在动手之前,先建立整体架构图景。整个链路由三个组件组成:
| 组件 | 角色 | 运行位置 |
|---|---|---|
| Codex CLI | 编程 Agent 前端,负责任务规划、命令执行、文件操作 | 用户终端 |
| CLIProxyAPI | 本地代理,负责协议转换、模型名映射、请求转发 | 用户本机 127.0.0.1:3456 |
| DeepSeek API | 模型推理服务,负责理解请求、生成代码 | 远端 |
一次完整请求的流转过程如下:
- 用户在 Codex 终端中输入需求,Codex 根据需求生成下一步动作,构造 API 请求。
- 请求的模型名通常是 Codex 默认的模型名,比如 gpt-5、o4-mini、codex-mini-latest,请求地址指向本地代理。
- 代理收到请求后,做模型名映射(例如把 gpt-5 替换为 deepseek-chat),把请求体从 Responses 格式转换成 Chat Completions 格式,再从环境变量读取 DeepSeek API Key 注入请求头。
- 代理把转换后的请求转发到 DeepSeek 的 https://api.deepseek.com/v1/chat/completions。
- DeepSeek 返回流式响应,代理把响应格式转换回 Codex 能理解的结构。
- Codex 解析响应,继续规划下一步,循环直到任务完成。
整个过程中,Codex 不知道也不关心上游是 DeepSeek 还是其他模型,它只知道自己在与一个兼容 Responses 协议的端点通信。这也是这个方案最优雅的地方:前端与后端完全解耦。今天你可以接 DeepSeek,明天可以换 Qwen,后天可以切换回 OpenAI,Codex 的交互体验和 Agent 工作流保持不变,只需要改代理配置。
模型名映射是整个链路里最容易出错的一环。DeepSeek 官方目前主要提供两个模型标识:deepseek-chat 和 deepseek-reasoner。前者适合常规代码生成和工具调用任务,后者偏推理增强,适合复杂分析和数学类问题。Codex 默认请求的模型名和这两个标识完全不同,如果不做映射,上游会直接返回 model not found。
4. 环境准备与前置条件
开始之前,先确认你的环境满足以下几个条件。这些条件并不苛刻,但缺一个后面都跑不通。
操作系统:macOS、Linux 都行。Windows 用户建议使用 WSL2,因为 Codex 在终端环境下的 Agent 工作流天然依赖类 Unix 的命令行工具链,比如 shell、grep、find 这些。在原生 Windows CMD 或 PowerShell 下运行,兼容性问题会多一些。
Node.js 环境:Codex CLI 的 npm 安装包需要 Node.js 18 及以上版本。CLIProxyAPI 类工具大概率也是 npm 包,同样依赖 Node.js。可以先在终端里检查:
node -v npm -v如果 node 命令不存在,先去 Node.js 官网下载 LTS 版本安装,装完重新开一个终端窗口再验证。
DeepSeek API Key:这是必须的。去 DeepSeek 开放平台注册账号,创建 API Key。创建后 Key 只会完整显示一次,记得立刻复制保存。平台通常有按量计费,新用户可能有一些赠送额度,具体规则以平台当前页面为准。把 Key 保存好,后面要写入环境变量。
基本的命令行能力:至少要知道 cd、ls、mkdir 这几个基础命令,理解环境变量的概念。如果你能熟练使用终端,整个流程很顺畅。如果之前一直用 IDE 自带的终端,也可以直接用它操作,区别不大。
5. 安装与配置:Codex CLI + CLIProxyAPI + DeepSeek
5.1 安装 Codex CLI
使用 npm 全局安装:
npm install -g @openai/codex安装完成后验证版本:
codex --version能输出版本号就说明安装成功。如果提示 command not found,说明 npm 的全局 bin 目录不在 PATH 里。可以先查看全局安装路径:
npm bin -g然后把这个目录加入 PATH,或者直接用完整路径调用。
这里另外提醒一句:Codex 还有通过 Rust 安装和源码构建的方式。如果你只是想在终端里快速跑通 Agent,npm 安装是最省事的路径。等到后面深入使用,再研究其他安装方式的差异也不迟。
5.2 配置 DeepSeek API Key
打开终端,把 Key 写入环境变量。为了后面多个进程都能读到,建议写进 shell 配置文件,比如 ~/.zshrc 或 ~/.bashrc:
export DEEPSEEK_API_KEY="sk-你的key"然后执行 source 使配置立即生效:
source ~/.zshrc # 或者 source ~/.bashrc验证是否写入成功:
echo $DEEPSEEK_API_KEY能显示出你的 Key 就说明环境变量配置完成。这里有个小细节:后面 Codex 会用这个环境变量向本地代理发送 Authorization 头,代理也会用它作为上游请求的鉴权。同一个变量,两处复用,所以命名要统一,不要写错。
5.3 安装 CLIProxyAPI 类代理工具
CLIProxyAPI 这类工具的更新速度非常快,安装命令在不同版本之间可能有差异。最稳妥的方式是去对应项目的 GitHub README 查看当前推荐的安装方式。社区里较常见的形态是 npm 全局包,安装后提供一个 cc 命令用于切换 Provider 配置:
npm install -g cliproxy-api cc --version如果你的工具不是这个包名,不要强行套用。请以项目文档为准。本文后面的命令演示基于“安装后提供 cc 命令”这个假设,其他命令变体只需要替换成对应的启动命令即可。
5.4 编写代理配置文件
代理工具通常会读取一份 YAML 或 JSON 配置文件。核心配置项分三块:监听地址、上游地址、模型名映射。下面是一份示例配置,文件路径建议放在你的用户目录下,比如 ~/.cliproxy/config.yaml:
# 本地代理监听地址,只监听本机,不暴露到局域网 listen_address: "127.0.0.1:3456" # 上游配置:DeepSeek API upstream: base_url: "https://api.deepseek.com/v1" api_key_env: "DEEPSEEK_API_KEY" timeout_seconds: 300 # 模型名映射:Codex 请求的模型 -> DeepSeek 模型 model_map: "gpt-5": "deepseek-chat" "gpt-5-codex": "deepseek-chat" "o4-mini": "deepseek-chat" "codex-mini-latest": "deepseek-chat" "deepseek-reasoner": "deepseek-reasoner" log_level: "info"这份配置的语义很清晰:
- listen_address 表示代理只监听本机的 3456 端口,这样外部机器无法访问,安全性更好。
- upstream.base_url 指向 DeepSeek 的接口地址,末尾带 /v1。
- upstream.api_key_env 告诉代理从哪个环境变量读取 Key 并注入到上游请求。
- timeout_seconds 设置上游请求超时时间。Agent 任务通常耗时长,300 秒是一个比较保守的初始值。
- model_map 里的每一项都是“Codex 请求的模型名 -> DeepSeek 的模型名”。gpt-5 这类是 Codex 可能请求的默认模型名,deepseek-reasoner 是 DeepSeek 侧的推理模型。
需要说明的是,不同代理工具对字段命名不一样。有些叫 endpoint,有些叫 providers,有些叫 models。关键是抓住三个语义:监听端口、上游地址、模型映射。只要这三个语义对得上,具体字段名差异可以对照项目文档快速调整。
5.5 配置 Codex CLI 指向本地代理
Codex CLI 的配置文件位于 ~/.codex/config.toml。如果 ~/.codex 目录不存在,先创建它:
mkdir -p ~/.codex然后编辑 ~/.codex/config.toml,写入如下内容:
model = "gpt-5" model_provider = "cliproxy" [model_providers.cliproxy] name = "CLIProxy DeepSeek" base_url = "http://127.0.0.1:3456/v1" env_key = "DEEPSEEK_API_KEY" wire_api = "responses"这里解释几个关键字段:
- model 是 Codex 默认使用的模型名。这里写 gpt-5 只是为了让 Codex 认识一个“默认模型”,真正生效的是代理里的 model_map。Codex 把这个模型名发到代理后,会被替换成 deepseek-chat。
- model_provider 指向下面定义的 provider 名称 cliproxy。
- base_url 是代理的地址。注意这里写的是 http://127.0.0.1:3456/v1,代理会在这个地址上接收 /v1/responses 请求。
- env_key 告诉 Codex 从环境变量 DEEPSEEK_API_KEY 中读取 Key,并在请求时自动带上 Authorization 头。对于本地代理来说,这个头可有可无,但保留它可以让代理在上游转发时直接复用,省去重复配置。
- wire_api 指定 Codex 与代理通信时使用的协议格式。这里用 responses,因为我们的代理接收的是 Responses 格式请求。如果你使用的代理只暴露 Chat Completions 格式的端点,那这里要改成 chat,同时代理就不需要做协议转换,只需要做模型名映射和转发。
5.6 启动代理并验证
启动代理前,确保 DEEPSEEK_API_KEY 已经设置。然后运行:
cc switch这条命令的作用是切换 Codex 当前使用的 Provider 配置,并启动本地代理。如果启动成功,你通常会在终端看到类似“local proxy started at 127.0.0.1:3456”的日志信息。不同工具的日志格式不一样,但只要是监听在本机 3456 端口,就说明代理已经就绪。
如果你的工具不是用 cc switch 启动,那就换成项目文档里对应的启动命令,比如 cliproxy start 或 cc proxy start。
为了确认代理确实在监听,可以执行:
curl -s http://127.0.0.1:3456/v1/models | head -n 20如果代理支持转发模型列表请求,你会看到 DeepSeek 的模型列表。如果返回空或者报错,也不要慌,很多代理只代理代码生成相关的端点,不支持 /v1/models 的转发。真正有意义的验证是下一步:直接用 Codex 跑一个任务。
6. 完整示例:让 Codex 用 DeepSeek 完成一个真实任务
现在我们来跑通一个最小示例,验证整条链路是否正常。
第一步,创建一个测试目录,放两个日志文件:
mkdir -p ~/codex-deepseek-demo && cd ~/codex-deepseek-demo printf "first line\nsecond line\nthird line\n" > a.log printf "only one line\n" > b.log第二步,调用 Codex 执行任务。用 codex exec 模式可以直接在命令行传入需求,适合脚本化和自动化测试:
codex exec "在当前目录编写一个 Python 脚本 stats_logs.py:统计所有 .log 文件的行数,按行数降序输出文件路径和行数"这里说明一下,codex exec 是 Codex CLI 的非交互式执行模式,适合一次性的明确任务。如果你想观察 Agent 的实时思考过程、文件改动和执行命令,可以不加 exec,直接运行 codex 进入交互式模式。第一次使用建议用交互模式,能看到更多细节。
Codex 拿到任务后,会经历一个“规划 -> 写文件 -> 执行 -> 验证”的过程。因为模型是 DeepSeek,它生成的具体代码每次可能不同。下面是一个可能生成的脚本示例:
#!/usr/bin/env python3 # 文件路径:~/codex-deepseek-demo/stats_logs.py import glob def main(): results = [] for path in glob.glob("*.log"): with open(path, encoding="utf-8", errors="ignore") as f: results.append((path, sum(1 for _ in f))) results.sort(key=lambda x: x[1], reverse=True) for path, count in results: print(f"{count}\t{path}") if __name__ == "__main__": main()这段脚本的逻辑很简单:用 glob 匹配当前目录下所有 .log 文件,逐行统计行数,装进列表后按行数降序排序,最后输出。errors="ignore" 是为了避免日志文件里出现非 UTF-8 编码导致程序崩溃,这是处理日志文件时的常见写法。
如果 Codex 没有自动执行脚本,可以手动验证:
python3 stats_logs.py预期输出如下:
3 /path/to/codex-deepseek-demo/a.log 1 /path/to/codex-deepseek-demo/b.log行数统计正确,说明整条链路已经打通:Codex 成功调用 DeepSeek 生成了代码,并且代码能正常运行。
7. 运行结果与验证:怎么确认请求真的走了 DeepSeek
很多人走到上一步,看到 Codex 能生成代码就以为大功告成。但这里还差一个关键动作:确认请求确实打到了 DeepSeek 上。因为如果代理配置有问题,Codex 可能仍然在用默认配置请求 OpenAI 端点,那样并不能达到你想要的成本效果。
验证方法有几层,从浅到深:
第一层,看代理日志。启动代理的终端窗口里通常会有请求日志,记录每次请求的目标上游地址和模型名。你应当能看到类似“POST https://api.deepseek.com/v1/chat/completions,model: deepseek-chat”的记录。如果日志里出现的是 openai.com 或 responses 字样,说明代理没有把请求转发到 DeepSeek。
第二层,看 DeepSeek 开放平台。登录 DeepSeek 开放平台的控制台,查看 API 用量页面。只要你刚才跑了任务,这里应该能看到对应的 token 消耗记录。这是最硬核的证据,因为只有请求真的到达 DeepSeek 服务端,才会产生用量记录。
第三层,让 Codex 开启详细日志。Codex CLI 支持输出更详细的请求信息:
codex exec --json "写一个 Python 脚本,输出 hello" 2>&1 | grep -i "model\|base_url" | head -n 20注意,不同版本的 Codex 参数可能不同,如果 --json 不生效,可以查看 codex exec --help 的输出,找到对应的 verbose 或 debug 参数。
第四层,侧面询问模型。你可以在任务描述里加上一句话:“请在第一行输出你当前使用的模型名称。”如果模型回答自己是 DeepSeek 或类似名称,说明请求确实走了 DeepSeek。不过这个方法只能作为辅助验证,因为模型并不知道自己的真实部署身份,回答可能存在偏差。
8. 常见问题与排查思路
接入过程中最耗时间的往往不是配置本身,而是各种报错。下面整理了几个高频问题,都是社区里最常见的情况:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 运行 codex 提示 command not found,或 IDE 插件报 unable to locate the codex cli binary | Codex CLI 未安装,或 npm 全局 bin 不在 PATH | 执行 which codex,确认安装路径 | 重新安装 Codex CLI,并把 npm 全局 bin 目录加入 PATH;在 IDE 插件设置里配置 codex_cli_path |
| 启动代理时提示 cc switch local proxy failed while handling codex endpoint /responses | 本地代理启动失败,或代理无法处理 /responses 端点 | 查看代理日志;检查 3456 端口是否被占用;用 curl 直接请求代理 |