codex-model-change
v1.0.11
Published
Switch OpenAI Codex (CLI / desktop app) between DeepSeek direct-connect and native ChatGPT. No proxy, no daemon.
Maintainers
Readme
cx — Codex 模型直连切换器
让 OpenAI Codex(桌面 App / CLI)直连 DeepSeek(或切回原生 ChatGPT),无需任何代理软件。
cx 是一个单文件 Python CLI,无常驻进程、无 launchd 服务依赖(仅一个可选的开机环境变量注入)。
工作原理
新版 Codex 已移除 wire_api = "chat",但其 model_provider 机制原生支持 Responses API。DeepSeek 官方 API(https://api.deepseek.com/v1)已支持 Responses 协议,因此:
Codex ──直连──> api.deepseek.com (cx 配置一条 model_provider)
Codex ──原生──> ChatGPT 登录态 (cx 注释掉 model_provider 即回落)中间没有任何协议翻译层,保持协议原生匹配。
安装
方式一:npm 安装(推荐)
npm install -g codex-model-change包内是零依赖的 Python 脚本(macOS 自带 python3),Node 只做入口转发,装完即可用 cx 命令。
方式二:源码安装
# 1. 下载或 clone 本仓库
git clone https://github.com/git-sgg/codex-model-change.git
cd codex-model-change
# 2. 运行安装脚本(复制到 PATH)
./install.sh # 默认装到 /usr/local/bin/cx
# 或指定位置: ./install.sh /opt/homebrew/bin/cx前置要求:已安装 OpenAI Codex CLI(brew install codex)。无 ChatGPT 账号也可以,见下节。
全新机器一键接入(无需 ChatGPT 账号/登录)
只在 DeepSeek 开放平台 申请一个 API key,然后:
cx setup sk-xxxxxxxx # 一条命令完成:存 key → 写 config → 生成模型目录 → CLI 冒烟测试适用场景:新机器只装了 Codex、从没用 ChatGPT 账号登录过(没有 ~/.codex/auth.json)。cx setup 会从零生成全部配置,实测无登录态也能正常对话。
之后:
- CLI 直接可用:
codex "你的问题" - 桌面 App:完全退出重开即可。若首次弹出登录页,选 Sign in another way;配置好自定义 provider 后通常可直接选项目开始使用(无需 ChatGPT 账号)。桌面 App 需要环境变量里的 key,
cx setup已通过launchctl注入并由 LaunchAgent 在重启后自动恢复 - 已有历史会话想一并切换:
cx fix-all deepseek(会自动退出并重开 App,无需手动操作)
命令
| 命令 | 作用 |
|---|---|
| cx setup <API_KEY> | 全新机器一键接入:存 key + 写配置 + 生成模型目录 + 冒烟测试(无需 ChatGPT 账号) |
| cx status | 查看默认模型 / provider / 最近会话各自用的模型 |
| cx fix-all deepseek\|gpt | 批量把所有老会话切换到目标模型(自动退出 App,完事自动重开);切到 gpt 时自动清理旧代理遗留的不兼容历史条目(reasoning.content 等),避免续聊报 Invalid 'input[..].content' |
| cx fix-all deepseek --limit 10 | 只处理最近 10 个会话(--limit 可按需调整,省略则处理全部) |
| cx use deepseek | 切换默认模型(只对新会话生效;改写 ~/.codex/config.toml,自动备份) |
| cx use gpt | 切回原生 ChatGPT(走 ChatGPT 登录态,无需 API key) |
| cx key <API_KEY> | 保存 DeepSeek key 并注入 GUI 环境(桌面 App 需要) |
| cx doctor | 体检:key 有效性 / 直连连通性 / 会话健康 |
| cx fix <会话ID> | 修复某个打不开/报 404 的会话(ID 取 cx status 里显示的前 8 位即可) |
| cx fix last | 修复最近一个会话 |
关于老会话:每个会话记录着自己创建时的模型,cx use 只影响新会话——老会话继续用原模型,互不干扰。想把老会话搬到新模型:单个用 cx fix,全部用 cx fix-all(会先备份数据库和会话文件,确认后执行)。
每次 cx use 都会自动备份 config.toml(config.toml.bak.cx-<时间戳>),随时可手动回滚。
从零添加 DeepSeek(Codex 里还没有 DeepSeek 时)
如果你的 Codex 从未配置过 DeepSeek(~/.codex/config.toml 里没有 [model_providers.deepseek]),按下面四步走,全程不需要手改任何配置文件:
第 1 步:获取 DeepSeek API key
到 platform.deepseek.com 注册/登录,在「API Keys」页面创建一个 key(sk- 开头),并确保账户有余额。
第 2 步:安装 cx(见上方「安装」)
第 3 步:保存 key 并切换
cx key sk-你的key
cx use deepseekcx key 会把 key 存到本机 ~/.cx/deepseek.key 并注入 GUI 环境;cx use deepseek 会自动在 ~/.codex/config.toml 末尾写入完整的 provider 配置:
# --- added by cx (direct deepseek) ---
[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com/v1"
env_key = "DEEPSEEK_API_KEY"
wire_api = "responses"并把顶部改为 model_provider = "deepseek" / model = "deepseek-flash",同时生成模型目录 ~/.codex/cx-catalog.json。
第 4 步:完成桌面 App 配置(见下方「桌面 App 的一次性配置」)。之后 cx use / cx fix / cx fix-all 都会自动退出并重开 App,无需手动 ⌘Q。
验证:跑 cx doctor,三项全 ✅ 即配置成功;或在 App 里发条消息试试。
如果
cx use deepseek报「找不到 config.toml」,说明你还没运行过 codex CLI——先随便跑一次codex "hello"让它生成配置文件,再执行上面的步骤。
桌面 App 的一次性配置
Codex 桌面 App 由 launchd 拉起,读不到 shell 里的环境变量,需要把 key 注入 GUI 环境:
launchctl setenv DEEPSEEK_API_KEY "$(cat ~/.cx/deepseek.key)"cx key 会自动装一个 LaunchAgent(~/Library/LaunchAgents/com.cx.codex-setenv.plist),下次重启登录时自动完成上述注入,所以手动只需执行一次。
之后 cx use deepseek 会自动退出并重开 Codex App(想手动操作也行:⌘Q 再打开)。App 的模型选择器里会出现 DeepSeek Flash / DeepSeek V4 Pro。
从其它代理工具迁移过来的用户:如果你的老会话记录的是代理别名(如
deepseek/deepseek-v4-flash),直连后无法续聊。直接执行cx fix-all deepseek,它会自动退出 App、迁移完毕后自动重开。
常见问题
Q: 切换/迁移后 App 里还是报错?
桌面 App 启动时读取配置,必须完全退出(⌘Q,不是关窗口)再打开。cx use / cx fix / cx fix-all 默认会代劳这件事;想自己控制加 --no-reopen(改完不重开)或 --keep-app(完全不动 App,在运行则报错)。
Q: 终端里 codex 能用,桌面 App 报 key 错误?
App 没读到 DEEPSEEK_API_KEY。执行上面「桌面 App 的一次性配置」后重启 App。
Q: 老会话续聊报 Model metadata not found 或 404?
会话自带的模型 id 与当前配置不一致。用 cx fix <会话UUID>(可在 cx status 里看到会话 UUID)。
Q: launchctl setenv 报 Not privileged to set domain environment?
必须在你自己登录会话的终端(Terminal.app)里执行,不能通过 ssh/部分自动化环境执行。
Q: 提示 deepseek 拒绝了 exec 自定义工具 之类的 400?
模型目录(~/.codex/cx-catalog.json)被改坏了,重跑一次 cx use deepseek 会重新生成。
Q: 跑完 cx fix-all 后,重开 App 某个会话“今天聊的内容不见了”?
1.0.5 之前确实存在这个坑:cx fix-all 清洗老会话时会删掉部分 reasoning 行,而会话文件(rollout)
里每条记录带一个必须从 0 起连续递增的 ordinal。删行不重编号就留下缺口,App 的投影缓存
(~/.codex/thread_history_1.sqlite)会永久卡在缺口处,于是之后的新内容再也进不了界面——
看起来就像“丢了”(其实原始 rollout 文件里还在,只是没被投影出来)。
1.0.5 已修复:fix-all 现在会在改写后自动重编号 ordinal 消除缺口,并清掉该会话的投影缓存,
让 App 下次打开时从会话文件完整重建。
若用的是 1.0.5 之前的版本且已中招:升级后完全退出 App,再重新打开该会话即可恢复;
仍不显示时,可手动删掉 ~/.codex/thread_history_1.sqlite 中对应 thread_id 的行,强制其重建。
Q: 切到 deepseek 后发消息报 No tool output found for tool call call_xxx(400,会话卡死)?
Codex 用 view_image 看图片时会连续发起多个调用,并在每条图片结果之后插入一条 role=developer
的 <image_resize_notice> 提示("Image N of N ... was resized ...")。DeepSeek 的 Responses API 在
「多个 tool call 连续出现 + 结果之间夹着 message」这种组合下会丢失配对,于是报
No tool output found for tool call ...,该会话从此发不出消息(与 cx 本身无关,是 Codex 的历史
组装方式在 DeepSeek 侧的兼容问题)。
1.0.9 已修复:cx fix <会话UUID> 与 cx fix-all deepseek 会先删掉这些纯提示性质的 notice 消息
(只删缩放提示,工具调用记录与对话内容全部保留),再重编号 ordinal 并重置投影缓存。
已中招的会话:升级到 1.0.9 → 完全退出 App → cx fix <会话UUID>(或 cx fix-all deepseek)→ 重开 App。
注意:之后若又在 deepseek 会话里让 Codex 看图(再次触发
view_image),会重新产生这类提示消息, 可能再次报同样的错——再跑一次cx fix即可。排查手法:把该会话的请求体抓下来,删除image_resize_notice消息后回放即 200。
隐私说明
- API key 仅保存在本机
~/.cx/deepseek.key(权限 600)和 launchd 环境中,不写入任何配置文件明文,不外发。 - 本工具不收集、不上报任何数据;唯一的网络请求是
cx doctor对api.deepseek.com的 key 有效性检查。 - 请求链路:Codex →
api.deepseek.com直连(或 Codex 原生链路),无中间人。
兼容性
- macOS(依赖
launchctl做 GUI 环境变量注入;纯 CLI 使用则不依赖) - Codex CLI / ChatGPT 桌面 App(内含 codex 的版本)
- DeepSeek
deepseek-flash(V4.1,默认)/deepseek-v4-pro(Responses API)
上下文:cx 生成的模型目录按官方 1M 窗口配置(
context_window = 1048576、auto-compact 阈值 900K、最大输出 384K),对应官方 DeepSeek-V4 系列。V3.1 时代的deepseek-chat/deepseek-reasoner只有 128K 级,且已被服务端当作兼容别名静默指向deepseek-flash;cx 1.0.8 起不再使用这两个旧名(如账号可用的模型名有变化,cx doctor会告警)。
License
MIT
