opencodex 解锁 Codex 任意模型,一个本地代理打通 Claude/Kimi/GLM/DeepSeek

大家好,我是若风。

你大概有过这种憋屈,打开 OpenAI 的 Codex CLI 或者 Claude Code,界面很顺手,Agent 跑任务也很流畅,但你就是想换个脑子试试。手里明明有 Claude 的 Max 订阅、有 Gemini 的 API、本地还跑着一个 DeepSeek,可 Codex 就是认死了它自己的后端,你 codex -m deepseek-chat 它理都不理你。

官方没支持,你只能等。等 OpenAI 哪天心情好把别的模型接进来,或者等 Anthropic 哪天松口。

opencodex 干的事就这么直接,不等了,它在你本地起一个代理,把 Codex 说的话翻译成任何模型听得懂的话,再把回答翻译回去。听起来像个普通的 LLM 网关,但你真去翻它的源码会发现,这玩意儿根本不是「转发器」那么简单。

一个项目,一个月,2553 颗星

先交代下背景。opencodex 仓库 2026 年 6 月 18 日才创建,到现在刚满一个月,2553 个 star,175 个 fork,TypeScript 写的,MIT 协议。一个人(lidge-jun)主导,17 个贡献者。

迭代速度有点吓人。我去拉 release 记录,7 月 20 号到 21 号两天发了 v2.7.27、v2.7.28、v2.7.29、v2.7.30、v2.7.31 五个正式版,外加好几个 preview tag。一天两三个版本是常态。你从 commit 频率能感觉到作者几乎住在代码里。

这种项目有个特点,功能堆得快,但稳定性需要时间检验。后面我会讲到它的几个已知坑,都是这种快速迭代留下的痕迹。

它到底解决什么

一句话,opencodex 让你能用 Codex CLI、Codex App、Codex SDK,甚至 Claude Code,去调用任何后端的模型,Claude、Gemini、Grok、GLM、DeepSeek、Kimi、Qwen、Ollama 都行,还有 40 多个内置 provider。

它的工作原理画出来很清楚。

bash 复制代码
Codex CLI / App / SDK ──/v1/responses──▶ opencodex ──▶ Any provider
                                              │
              Anthropic · Google · xAI · Kimi · Ollama Cloud · Groq
              OpenRouter · Azure · DeepSeek · GLM · ...以及 OpenAI 自己

关键在于那句「use any LLM with Codex --- and with Claude Code too」。它不只是给 Codex 当代理,还能反过来给 Claude Code 当后端,让你在 Claude Code 里用 GPT 或者 Gemini。双向都通。

翻译官的核心,是七个适配器

很多人把这类工具理解成「请求转发」,就像 Nginx 反向代理一样,原封不动把请求搬过去。但 Codex 说的是 OpenAI 的 Responses API,而 Claude 说的是 Messages API,Gemini 有自己的一套 generateContent,Ollama 又是 OpenAI 兼容的 Chat Completions。这四种协议根本不是一回事。

opencodex 的核心设计是适配器模式 。每个 provider 对应一个适配器,适配器实现 ProviderAdapter 接口(定义在 src/adapters/base.ts),接口里最关键的是两个方法,buildRequest 把内部请求格式翻译成上游的 HTTP 请求,parseStream 把上游的流式回答翻译回内部事件。

ts 复制代码
interface ProviderAdapter {
  name: string;
  buildRequest(parsed, incoming?): AdapterRequest | Promise<AdapterRequest>;
  parseStream(response): AsyncGenerator<AdapterEvent>;
  // ...
}

有意思的是数量。README 顶部写的是「5 protocol adapters cover Anthropic Messages, Google Gemini, Azure, OpenAI Responses passthrough, and every OpenAI-compatible Chat Completions endpoint」。但你翻它的 docs-site 适配器参考文档,第一行写的是「The seven provider adapters」。我去 src/adapters/ 目录数了一遍,openai-chat.tsopenai-responses.tsanthropic.tsgoogle.tsazure.tscursor.tskiro.ts,确实七个。README 没跟上迭代,少算了 Cursor 和 Kiro 两个实验性适配器。

这种文档和代码的轻微错位,在一个一个月发 30 多个版本的项目里太正常了。

整条管线是怎么跑的

适配器只是其中一环。一个请求从 Codex 出来到上游 provider,要经过一条完整的管线。官方文档画得很清楚,我把它简化成这样。

scss 复制代码
Codex ──▶ parser ──▶ router ──▶ [vision] ──▶ adapter ──▶ provider ──▶ Codex
          解析        路由        视觉旁路     翻译         上游        (SSE)

第一步是 Parseresponses/parser.ts 用 Zod schema(responses/schema.ts)校验请求,把它降级成内部的 OcxParsedRequest。我看了那个 schema 文件,定义得非常细,input_image 块支持 auto|low|high|original 四种 detail 级别,reasoning item 带了 encrypted_content 字段------这是 Codex 协议里那种不透明的加密载荷,后面会讲到它带来的麻烦。

第二步是 Route,这是整条管线里设计最讲究的一环。

router.ts 的七层优先级

src/router.ts 里的 routeModel 函数,负责把一个模型 id 映射到具体的 provider。它不是简单的 if-else,而是一个有明确优先级的七层决策。我从源码里读出来的顺序是这样的。

  1. Combo 模型,先查是不是组合模型(多个 provider 聚合的虚拟模型)
  2. 显式命名空间 ,形如 provider/model 的,比如 anthropic/claude-opus-4-8,只有当前缀匹配到已配置的 provider 才命中
  3. 裸 OpenAI 家族gpt-o1-o3-o4- 开头的,走 Codex 登录的 OpenAI provider
  4. defaultModel 精确匹配 ,遍历所有 provider 看谁把 defaultModel 设成了这个 id
  5. 前缀模式匹配routeByKnownModelPattern,比如 claude- 开头的路由到 anthropic,llama-/mixtral-/gemma- 路由到 groq
  6. models 数组匹配 ,遍历 provider 的 models[] 列表
  7. defaultProvider 兜底

这个设计有个很妙的细节。第 2 层显式命名空间里,它不是无脑 split,而是先判断前缀是不是真的对应一个已配置的 provider。源码注释写得很直白,「Only triggers when the prefix matches a CONFIGURED provider, so genuine slash-containing model ids fall through」。也就是说 anthropic/claude-... 这种天然的 slash id 不会误触发,只有当你真的配了一个叫 anthropic 的 provider,它才会按命名空间解析。

这种边界处理看着不起眼,但它决定了一个代理在复杂配置下会不会路由错乱。很多同类工具在这层就是一锅粥。

Design B,不 re-tag 你的历史

opencodex 有个让我比较意外的设计决策,藏在 src/codex/inject.ts 里。

它要把 Codex 的请求导向自己,最直接的办法是改 Codex 的配置,把 model_provider 换成 opencodex。但这样有个后果,你之前所有的对话历史都被打上了 opencodex 的 provider 标签,一旦你卸载 opencodex,这些历史会因为找不到 provider 而出错。

作者的解法叫 Design B (源码注释原话,2026-07-06 定稿)。本地回环安装时,opencodex 不再替换 model_provider,而是只改一个字段,openai_base_url,让 Codex 自己的 openai provider 指向代理。这样对话历史的 provider 标签始终是原生的 openai,永远不需要迁移或恢复。

注释里还提到了一个被修掉的 bug,「Appending the bare key at EOF was the original bug,it nested under whatever table happened to be open last」。早期版本因为 TOML 追加位置不对,导致 model_provider 被塞进了最后一个打开的 table 里,Codex 根本读不到,悄悄回退到了 ChatGPT provider。这种 bug 的隐蔽性,用过 Codex 配置的人都懂。

非本地回环的绑定(比如 LAN 暴露)还是得用传统的 table 注入,因为原生 provider 没法带自定义的鉴权 header。这是个务实的取舍。

流式传输里的失败合成

代理最难处理的不是正常请求,是异常。尤其是流式请求,SSE 已经开始吐 token 了,上游突然断了,客户端看到的是什么?一个光秃秃的 socket 断开,没有任何结束事件。

src/server/relay.ts 里有个函数 relaySseWithFailedTail,专门处理这种情况。它的逻辑是,一旦上游在流到一半时 reset,它不会傻乎乎地直接重发(注释里明确写了「Deliberately NOT a resend,the upstream already committed the request」),而是合成一个干净的终结,先关闭可能残缺的 SSE block,再注入一个 response.failed 事件和 data: [DONE],让客户端收到一个结构完整的失败响应。

ts 复制代码
controller.enqueue(encoder.encode(
  `\n\nevent: response.failed\ndata: ${payload}\n\ndata: [DONE]\n\n`
));

这个设计很克制。它知道上游已经「committed」了这个请求(可能已经计费),所以宁可告诉客户端「失败了」,也不去冒重复请求的风险。这种对幂等性的敬畏,在代理类工具里不多见。

还有一个细节,sanitizePassthroughHeaders 函数。Bun 的 fetch 会自动解压响应体,但把 content-encoding 和过期的 content-length 留在响应头里。如果代理原样转发这些头,Codex 会按头里的编码再解压一次,结果是每个 gpt 直通请求都报「stream error」。这个函数专门把这些 hop-by-hop 头剥掉。注释写得很到位,「Relaying those makes the caller double-decode / truncate」。

ChatGPT 账号池,一个有点野的功能

opencodex 不止做协议翻译,它还管 ChatGPT 账号池。你可以加多个 ChatGPT/Codex 账号,代理帮你自动轮换。

这个功能的核心在 src/codex/quota.ts。它会追踪每个账号在三个时间窗口的配额使用率,5 小时、每周、30 天。每个窗口对应 OpenAI 那套 primary_window/secondary_window/tertiary_window 的配额机制。

轮换规则分两种情况。已有的会话保持「亲和性」,一个 thread 绑死在启动它的那个账号上,这样你 SSH 或者 tmux 挂着的长会话不会被中途换号。新的会话可以自动路由,代理会对比当前账号在最热那个窗口的使用率,超过阈值就挑一个用量更低、健康的账号顶上。

失败处理也很明确。token 失败标记为「需要重新认证」,而不是悄悄降级到别的凭证。429 配额超限把账号扔进冷却期,后续请求可以 fail-over 到池里其他账号。

坦白讲,这个功能技术上不复杂,但它踩在了一个灰色地带。README 顶部的 Disclaimer 写得很直,opencodex 和 OpenAI、Anthropic 没有任何关系,而且「some providers may suspend or restrict accounts that route API traffic through third-party proxies,Use at your own risk」。把多个订阅账号池化轮换,到底算不算违反 ToS,这个得你自己掂量。

一条没修好的跨模型 sub-agent 链路

说完亮点,必须讲一个实打实的坑。这是 issue #92,9 个点赞,是作者自己开出来标记的已知限制。

场景是这样的,你用 v2 多 Agent 模式,父 Agent 跑在原生的 gpt-5.6-sol 上,调用 spawn_agent 派一个子 Agent 去跑 xai/grok-4.5。模型覆盖是成功的,子 Agent 确实用上了 grok,但问题是子 Agent 收不到任务内容。

子 Agent 的 NEW_TASK 消息里,明文 payload 是空的,后面跟着一个 Fernet 加密的 encrypted_content 块。路由到非 OpenAI 模型的子 Agent 解不开这个加密块,于是报告「没有具体任务」,或者从上下文里瞎猜一个任务来跑。

根因在于前面提到的那个 encrypted_content 字段。Codex 原生协议里,reasoning item 可以携带这种不透明的加密载荷,只有 OpenAI 自己的后端能解开。一旦跨 provider 委派,这个加密块就成了死信。

README 里这个限制写得挺诚实,「when a native parent spawns a routed child, the task body can currently arrive backend-encrypted and be lost,use the v1 surface for reliable cross-provider delegation」。翻译过来就是,想跨模型委派任务,现在老老实实用 v1 接口,别碰 v2。

我之所以单独拎出来讲,是因为这个 bug 暴露了「协议翻译」类工具的根本困境。你能翻译消息格式,能翻译工具调用,但你翻译不了别人加密的载荷。加密是个信任边界,代理站在边界外面,天然进不去。这不是 opencodex 写得不好,是这个品类注定要面对的限制。

作者在追着三个对手跑

最后一件事,挺有意思的。我在仓库里发现一个 devlog/_chase/ 目录,是作者用韩语写的竞品追踪笔记。它明确把三个项目当成「upstream」在追赶。

jawcode,一个同类代理,opencodex 大量代码是从它 port 过来的。cli-proxy-api,另一个代理,作者认为它在协议和认证层处理得更深。litellm,那个老牌的 LLM 网关,长尾 provider 覆盖最全。

作者把能力差距分成四类。G1 是 jawcode 新增的 provider/模型自己还没跟上,G2 是 cli-proxy-api 在 wire/auth/replay 上更硬核,G3 是 litellm 的长尾 provider 覆盖,G4 是 opencodex 独有的(Kiro、Codex WebSocket、订阅 IDE 后端)。

这能解释它为什么迭代这么疯。它不是在闭门造车,是在一场明确的多方军备竞赛里抢位置。2553 颗星一个月拿下来,背后是这种追赶压力。

这个项目该不该用

聊到这你大概也看出来了,opencodex 是那种「方向很对、执行很猛、但还很年轻」的项目。

它的适配器架构和路由设计是真有东西的,七层路由优先级、Design B 的历史安全注入、流式失败合成、账号池配额管理,这些都不是玩具代码能写出来的。如果你受够了 Codex 锁死单一后端,想用自己手里的模型订阅,它是目前最完整的解法之一。

但你也得清楚它的状态。一个月的项目,文档和代码还在错位,跨模型 sub-agent 这条链路有硬伤,账号池化功能踩在 ToS 灰区。它适合愿意折腾、能接受快速迭代(和偶尔被新版本带坑)的人。如果你要的是开箱即用、稳定到能上生产的网关,LiteLLM 这种沉淀了更久的项目可能更稳妥。

我自己从这套适配器设计里学到最多的是那个翻译边界的认知。协议可以翻译,消息可以翻译,工具调用可以翻译,但加密载荷翻译不了。做任何中间层------不管是 LLM 代理、API 网关还是消息队列桥接------都要想清楚,你的翻译能力在哪个边界戛然而止。opencodex 把这个边界诚实地写进了 issue 区,这种工程坦诚比功能数量更值得信赖。

相关推荐
wangruofeng1 小时前
姚顺雨长谈:在 Anthropic 和 Gemini 训练模型,英雄主义已经过时
llm·aigc
一点一木3 小时前
从60首歌到1个网站:输入你的故事,还你一首歌
前端·github
机器之心4 小时前
WAIC现场,这家公司让一群不同的机器人共用一个大脑
人工智能·openai
赵康6 小时前
AI 写代码之后,Code Review 会议怎么开
ai·llm·skill
莫逸风6 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
刘较瘦_7 小时前
AI 开发中的 Git Submodule 父子仓库模式:前后端分仓管理与协作实践
前端·github
DeMinds10 小时前
内容没有丢,我为什么总在重新整理?|DeMinds 如何让工作接着继续
ios·github·markdown
寒水馨10 小时前
macOS下载、安装openclaw-v2026.7.1(附安装包OpenClaw-2026.7.1.dmg)
macos·大模型·github·开源软件·ai助手·openclaw·gpt-5.6