我先说一个很反直觉的事实:Codex 和 Claude Code 装好之后,默认情况下你几乎没法“快速试另一个模型”。白天用 Codex 写方案,晚上用 Claude Code 改代码,中间想切到 DeepSeek 或者本地模型跑一轮测试,都得翻配置文件、改环境变量、重启会话,整个过程轻松吃掉十几分钟。直到我把这套切换逻辑打包成一个 15MB 的小工具,这种折磨才算结束。
这个小工具做的事情其实很朴素:把散落在~/.codex和~/.claude底下的模型配置统一管起来,一条命令切换供应商、模型、API 地址和密钥来源。它不拦请求、不转发流量、不替代任何 CLI,只是一个“配置编排器”。如果你跟我一样,日常要在多个模型供应商之间横跳,或者经常在云端模型和本地模型之间试效果,这篇文章值得你花几分钟看完。我会把原理、实操步骤和踩过的坑一并讲清楚。
1. 为什么换个模型能把我逼疯:两个 CLI 的配置各自为政
1.1 Codex 和 Claude Code 的“模型入口”根本不是同一个地方
先看 Codex。OpenAI 的 Codex CLI 默认读取~/.codex/config.toml,里面写模型名、供应商、API Base URL,登录态则另外存在~/.codex/auth.json。你可以把它指向 OpenAI 官方接口,也可以指向任何 OpenAI 兼容的服务,比如 DeepSeek、Moonshot,或者本地起一个 LM Studio。
Claude Code 又是另一套逻辑。它默认走 Anthropic 的 API,模型相关配置分散在~/.claude/settings.json、环境变量ANTHROPIC_MODEL、ANTHROPIC_BASE_URL,以及会话内/model命令里。两个工具的配置格式完全不一样,一个是 TOML,一个是 JSON,字段名也各叫各的。
问题就在这里:我在同一个终端里,昨天刚把codex指向 DeepSeek,今天用claude的时候,发现某个环境变量还残留着上一轮的设置,莫名其妙就把请求发到了错误地址。这类状态污染,比配置本身不对更烦人。
1.2 手动改配置文件的三大致命伤
我最早是纯手动切配置,三个痛点非常典型。
第一是容易改错。config.toml里一个键名拼错,Codex 不会立刻报错,它会忽略掉这个未知字段,然后你看到的行为却是“模型没变”或者“用了默认模型”。热词里那个“codex is ignoring 1 unrecognized configuration setting”就是这么来的。这类问题用肉眼很难排查。
第二是状态残留。终端里的OPENAI_API_KEY、ANTHROPIC_BASE_URL这些变量是全局共享的。你上午给 Codex 设了环境变量,下午 Claude Code 可能照样读到,表现就是“明明我已经切回官方模型了,为什么请求还是打到上一个地址”。实际上你只改了命令行窗口里的变量,另一个工具没重启,配置根本不生效。
第三是切换成本高到让人放弃。一天之内我可能要切换五六次,每次都要想清楚“这次要改哪个文件、哪个键、要不要重启终端”。人的意志力是有限的,当切换动作本身比写代码还费劲的时候,人就会倾向于不切换,然后被迫在一个模型上硬扛。
1.3 15MB 工具的定位:配置编排器,不是模型网关
网上很多方案会引导你搭一个“模型网关”,比如用 LiteLLM、one-api 这类服务统一转发所有模型的请求。这种方案很强,但也很重,需要维护一个常驻服务、做并发控制、管理一个后台面板,对小团队和个人开发者来说完全是杀鸡用牛刀。
15MB 这个量级的小工具走的是另一条路:它直接替你改本机配置。你只需要维护一份自己的“供应商列表”,告诉它“DeepSeek 的地址是什么、模型叫什么、密钥从哪里读”,切换的时候它把你选中的供应商写入 Codex 和 Claude Code 各自的配置文件,然后你重启对应 CLI 就能用。
所以它的定位非常清楚:不碰网络流量,不做请求转发,只做配置写入和备份。这也是为什么它能做到 15MB——一个编译好的二进制文件,没有运行时依赖,没有 Node 环境,没有 Electron 外壳。你把它放进~/bin就能用,删掉也不留垃圾。
2. 15MB 的原理:它不搞推理,只做配置编排
2.1 Codex 和 Claude Code 本质上是“读配置的瘦客户端”
要理解为什么 15MB 够用,得先认清一个事实:Codex 和 Claude Code 本身并不绑定某个特定模型厂商,它们只是“读配置的客户端”。
你给 Codex 一个 OpenAI 兼容的 Base URL,再给它一个模型名,它就拿这套参数去发请求。你给 Claude Code 设一个ANTHROPIC_BASE_URL,它也会乖乖地把请求发到那个地址,哪怕那个地址背后跑的是一个本地模型。
真正麻烦的,是怎么把这套参数“稳定、无残留、可回滚”地切来切去。小工具的核心工作就是三件事:
- 维护一份供应商清单:比如 OpenAI、DeepSeek、本地 LM Studio、某个中转服务。
- 根据当前选择,改写目标配置文件:Codex 的
config.toml、Claude Code 的settings.json,必要时导出一组环境变量。 - 保留上一份配置作为回滚点:切换出错时一条命令回到之前的可用状态。
2.2 供应商清单的数据结构:一个典型的配置长什么样
市面上的同类工具命令方式各有差异,有的叫cc-switch,有的叫codex-switch,但核心都离不开一个“槽位”概念。我自己常用的一种配置格式是这样的:
providers: - name: openai type: codex base_url: https://api.openai.com/v1 api_key_env: OPENAI_API_KEY model: gpt-5-codex - name: deepseek type: codex base_url: https://api.deepseek.com/v1 api_key_env: DEEPSEEK_API_KEY model: deepseek-chat - name: local-lm type: codex base_url: http://127.0.0.1:1234/v1 api_key: lm-studio model: qwen2.5-coder-7b - name: claude-official type: claude base_url: https://api.anthropic.com/v1 api_key_env: ANTHROPIC_API_KEY model: claude-sonnet-4-5 - name: claude-local type: claude base_url: http://127.0.0.1:8080/v1 api_key: dummy-key model: local-coder-model这里每个“槽位”都声明了该用哪个类型的客户端、请求发到哪里、密钥从哪里取。工具拿到槽位之后,做的事情非常机械:
- 读取当前 Codex / Claude Code 的配置文件,做一次备份。
- 把槽位里的字段翻译成目标文件格式。
- 写入文件,必要时同步写一份环境变量导出脚本。
- 打印修改后的关键字段,让你一眼确认。
整个过程不超过 100 毫秒,但避免了所有“手改出错”的可能性。
2.3 为什么 15MB 不是偷工减料,反而是优势
有人一看 15MB 就觉得“这么小,功能怕是残缺吧”。实际恰恰相反。一个 Go 或 Rust 写的二进制,自带 TUI 界面、配置解析、文件读写、备份轮转,体积也就 10~20MB。这正说明它把“事情做少了”。
对比一下,如果你为了切换模型去装一个 Electron 桌面应用,动辄几百 MB,还要常驻内存,这本身就是一个巨大的资源浪费。CLI 工具的职责是“改配置”,不是“展示配置”。没有 GUI、没有后台服务、没有自动更新守护进程,反而意味着它更容易被审计、更容易嵌入脚本、更不容易出安全幺蛾子。
而且 15MB 还有一个隐藏好处:可以放在 U 盘里,或者直接塞进 dotfiles 仓库,新机器 clone 下来跑一条初始化命令就能恢复整套模型切换环境。我在两台 Mac 和一台 Linux 机器之间同步配置,靠的就是 git 管理一份供应商清单,配合这个二进制工具。
3. 上手三板斧:安装、建槽位、切换
3.1 安装与初始化的实际操作
先把工具装好。以常见的cc-switch类工具为例,安装方式通常是下载编译好的二进制放到~/bin,或者用包管理器直接装:
# 下载对应平台的压缩包 wget https://example.com/cc-switch-linux-amd64.tar.gz tar -xzf cc-switch-linux-amd64.tar.gz mv cc-switch ~/.local/bin/ chmod +x ~/.local/bin/cc-switch # 初始化配置目录 cc-switch initinit命令会帮你在~/.config/cc-switch/下生成一个providers.yaml,同时自动扫描本机已有的 Codex 和 Claude Code 配置,把当前默认状态先存一份快照。这一步很关键,它相当于“先存档再开始玩”,避免你之后不小心把唯一可用的配置覆盖掉。
3.2 添加你的常用供应商槽位
接下来把你常用的模型供应商加进去。不同工具命令参数略有差别,但思路一致,无非是“指定类型、指定地址、指定模型”。我自己一般是写配置文件,因为可视化编辑更容易管理多个槽位:
cc-switch add --name deepseek --type codex --base-url https://api.deepseek.com/v1 --model deepseek-chat cc-switch add --name lm-studio --type codex --base-url http://127.0.0.1:1234/v1 --model qwen2.5-coder-7b cc-switch add --name claude-sonnet --type claude --model claude-sonnet-4-5值得一提的细节是 API Key。好的工具不会把密钥直接写进 YAML 明文存储,而是记录一个环境变量名,比如api_key_env: DEEPSEEK_API_KEY。切换时它把对应的变量名写进你的 shell 配置,或者让 Codex / Claude Code 从环境里读取密钥。这样你仍然可以享受.env文件或者密钥管理器的安全性,不至于在配置文件里裸奔。
3.3 切换一条命令,但要记得重启客户端
配置好槽位之后,切换就变成一条命令的事了:
cc-switch use deepseek codex或者切到 Claude Code 的某个槽位:
cc-switch use claude-sonnet claude工具执行切换时,会把~/.codex/config.toml、~/.claude/settings.json以及当前 shell 的导出脚本一起改掉。你打开新终端,新会话自然就是目标模型。
这里有个习惯我花了很久才养成:切换之后一定要开新会话,最好连终端窗口一起新开,不要让正在跑的 Codex 或者 Claude Code 进程去“热加载”新配置。它们启动时已经把配置读进内存了,你切了配置文件,它并不会感知到,反而会出现你人以为已经切换、实际还在用旧模型的情况。
3.4 切换后如何确认真的生效
切换完成之后,不要急着开聊,先花十秒钟验证。
最简单的办法是让 CLI 自己报配置。Codex 可以用:
codex --versionClaude Code 则直接问它当前用的什么模型:
claude > /status/status会明确列出当前会话使用的模型和 API 端点。如果你嫌麻烦,也可以直接检查配置文件内容,确认model和base_url两个字段已经变成了目标值。我自己的习惯是加一个 shell 别名,切换完自动打印关键配置:
alias cdx-use='cc-switch use && echo "--- codex config ---" && cat ~/.codex/config.toml'4. 云端与本地混搭:把 Codex 切到 DeepSeek,把 Claude Code 指向 LM Studio
4.1 Codex 接入 DeepSeek 的关键:URL 与模型名一个都不能错
Codex 接入 DeepSeek,本质上就是把它当成一个“OpenAI 兼容供应商”。DeepSeek 提供了兼容 OpenAI 格式的 API,所以切换槽位时只要注意两点。
第一,Base URL 要写对。一般需要写成https://api.deepseek.com/v1或者 DeepSeek 官方文档里给出的兼容地址,不要把/chat/completions这种路径拼进去,那是端点路径,不是 Base URL。
第二,模型名要用对方定义的名称。Codex 自己可能习惯叫gpt-5-codex,但 DeepSeek 那边认的是deepseek-chat、deepseek-reasoner。模型名错了,报错信息通常含糊不清,有时候是 404,有时候是 “model not found”,还有时候干脆是 “400 Bad Request”。
我建议在槽位配置里显式加上model字段,同时保留环境变量DEEPSEEK_API_KEY。用的时候这样切:
cc-switch use deepseek codexCodex 启动之后,你还可以在它的配置里看到当前 provider 是 deepseek,模型是deepseek-chat。实测下来,DeepSeek 的响应速度在代码补全场景下表现不错,和官方 Codex 模型相比,各有胜负,但“能随时切回去”这件事本身价值很大。
4.2 Claude Code 调用 LM Studio 本地模型:中间会多一层兼容转换
Claude Code 默认走 Anthropic Message API,而 LM Studio 暴露的是 OpenAI Chat Completions 格式。这两个格式的请求体、响应结构都不一样,所以如果你只是把ANTHROPIC_BASE_URL改成http://127.0.0.1:1234/v1,通常不会直接通,会看到一堆奇奇怪怪的解析错误。
热词里有一句“claude code 调用lmstudio的本地模型”,说明大家确实有强烈的本地化需求。常见做法是加一层协议转换,比如用 LiteLLM 或者一些专门做 Anthropic 到 OpenAI 转换的本地路由器,把 Claude Code 的请求翻译成 LM Studio 能理解的格式。
这时候小工具的价值就体现出来了:它不关心转换层怎么实现,它只管把 Claude Code 的 Base URL 指到转换层地址上。你可以先在本地跑一个转换服务,监听127.0.0.1:8080,然后建一个 Claude Code 槽位:
providers: - name: claude-local type: claude base_url: http://127.0.0.1:8080/v1 api_key: dummy-key model: qwen2.5-coder-7b切换之后,Claude Code 把请求发给转换层,转换层再转给 LM Studio。整个过程里,工具负责的是“把 Anthropic 官方地址换成 127.0.0.1:8080”,至于背后转换层的死活,它不管,也不该管。
4.3 混搭时要盯住三个字段
无论你把 Codex 切到什么供应商,还是把 Claude Code 指向什么本地服务,混搭最容易翻车的就三个字段:
| 字段 | 作用 | 踩坑表现 |
|---|---|---|
base_url | 决定请求发到哪里 | 多拼了路径导致 404,少写了协议导致握手失败 |
model | 决定对方识别哪个模型 | 模型名不匹配,报 model not found |
api_key | 决定鉴权方式 | 本地服务填 dummy 即可,云端必须真实密钥 |
我自己混搭的经验是,先找一个最简单的槽位跑通,再逐渐加复杂供应商。比如先在 Codex 里把官方 OpenAI 的槽位跑通,再加 DeepSeek,最后加本地模型。每加一个,切一次,用一句话提问验证,再继续下一个。
5. 我在切换途中踩过的三个坑:跳闪、/responses 404 和未知配置项
5.1 切换模型后原对话不停跳闪
有不少人遇到过“切换模型后原对话不停跳闪”的现象,界面里光标疯狂闪烁,但就是不输出内容,看起来像卡死。我最早也以为是工具坏了,后来定位到原因:切换发生在旧会话仍然存活的时候。
你的 CLI 进程还在运行,仍然持有旧的模型上下文和旧的 API 地址。你切了配置,旧进程并不知情,它可能还在向旧地址发请求,或者疯狂重试,导致界面表现异常。
解决办法有三个层次:
- 切换前先退出正在运行的 Codex / Claude Code 会话,再执行
cc-switch use。 - 如果已经出现跳闪,直接 Ctrl+C 终止会话,新开终端重新进入。
- 不要在同一终端里反复横跳,尽量做到“一个终端窗口只服务一种模型环境”。
这个坑本质上不是工具的 bug,而是使用习惯问题。切配置和开新会话必须是连续动作,中间不要隔着一个还在跑的进程。后来我把切换命令和启动命令合并成了一个别名:
alias cdx-do='cc-switch use "$1" && codex'曾经有一次,Codex 报错信息大概是 “cc switch local proxy failed while handling codex endpoint /responses.”。这里先澄清一下,报错里的 “local proxy” 指的是本地 API 转发服务,比如 LM Studio、Ollama 或者其他兼容层,不是网络工具。这个报错的本质是:Codex 正试图把请求发到本地端点.../responses,但本地服务处理失败了。
为什么 Codex 会去找/responses?因为较新的 Codex CLI 默认走的是 OpenAI 的 Responses API,端点路径是/v1/responses。很多本地推理服务只实现了老的/v1/chat/completions,根本没有/v1/responses这个路由。你的 cc-switch 把 Base URL 指到了本地服务,本地服务一看请求路径不认识,直接返回错误,Codex 就把这个错误归因为 “local proxy failed while handling codex endpoint /responses”。
排查链路是这样:
- 先确认本地服务本身在运行:
curl http://127.0.0.1:1234/v1/models,能返回模型列表说明服务活着。 - 再确认 Codex 启动时实际用的 Base URL:
codex --version或者检查~/.codex/config.toml。 - 然后确认端点路径:手动 curl 一下
/v1/responses,如果返回 404 或 “not found”,说明本地服务不支持 Responses API。 - 解决方法是加一层兼容网关,或者换一个支持
/v1/responses的本地服务版本,再或者把 Codex 配置成走 Chat Completions 兼容模式。
我在实际项目里,最省心的做法是给本地模型套一层转换层,让转换层同时暴露/v1/responses和/v1/chat/completions两个端点,转发到真实的本地服务。这样无论是新版 Codex 还是旧版客户端,都能正常工作。
5.3 Codex 忽略未知配置项
另一个高频问题是 Codex 突然提示 “ignoring 1 unrecognized configuration setting”。这个报错说明你的config.toml里有个字段是 Codex 不认识的。最常见的来源是:手改配置时把别的工具的字段写进去了。
比如你给 Codex 写了一个model_provider键,Codex 当前版本并不认识,它就会忽略,然后默默用默认 provider。表面现象是:你明明配置了 DeepSeek,请求却还是打到 OpenAI 官方,非常迷惑。
cc-switch 这类工具也会踩这个坑,尤其是老版本生成配置文件时,字段名跟 Codex 新版本对不上。解决思路有两个:
- 升级工具版本,新版会跟进 Codex 的配置格式变化。
- 用工具重新生成配置文件,不要在一个旧的
config.toml上手动增删字段。
我自己吃了一次亏之后,就把config.toml交给工具全量管理了,有定制需求只写在工具自己的供应商清单里,不再手动碰 Codex 的原始配置。
5.4 通用排查链路总结
这三类问题看起来各不相同,但底层思路是一致的。我每次排查都会按这个顺序走:
- 看状态:
cc-switch status,确认当前激活的槽位。 - 看文件:
cat ~/.codex/config.toml或者cat ~/.claude/settings.json,确认实际写入内容。 - 看端点:用 curl 手动请求目标服务的健康地址,排除服务本身问题。
- 看版本:确认 Codex、Claude Code 和工具版本之间是否存在配置格式差异。
- 重新生成:如果文件已经被改得乱七八糟,就用工具重新生成一份基础配置,再逐个加槽位。
这套链路帮我解决过至少十次看起来“莫名其妙”的切换问题,大部分最终都能归因到上面五类原因之一。
6. 把这个动作变成肌肉记忆:工作流与取舍
6.1 给常用模型建“槽位”而不是反复改字段
我强烈建议按照场景建槽位,而不是按照模型厂商建槽位。比如:
work-openai:OpenAI 官方 Codex 模型,用于日常主力 coding。work-deepseek:DeepSeek 模型,用于需要舔 token 成本的长任务。local-fast:本地小模型,用于快速验证 prompt 思路。local-big:本地大模型,用于离线环境。
每个槽位都是完整的一套 base_url + model + api_key 组合,切换只需要记一个名字。比起临时想起来“今天用 deepseek-chat”,不如提前把deepseek-chat这个配置固化成槽位,用的时候:
cc-switch use work-deepseek codex加槽位只花一分钟,长期来看节省的是每次切换时“回忆参数”的脑力。
6.2 把切换写进 Shell 函数,避免两张皮
手动敲两条命令虽然不难,但总会有偷懒漏掉某一步的时候。我在~/.zshrc里放了几个函数:
function cdx() { local profile="${1:-work-openai}" cc-switch use "$profile" && exec codex } function cld() { local profile="${1:-claude-official}" cc-switch use "$profile" && exec claude }这样我可以直接输入cdx work-deepseek或者cld claude-local,不用想“先切换再启动”的先后顺序。exec保证新进程完全继承新配置,不会出现旧 shell 环境残留。
6.3 什么时候不要用这个工具
工具虽然方便,但也不是银弹。有这么几类情况,我不建议用它:
- 你只有一个供应商,且三个月内没有换过模型。没有切换需求,就不需要配置编排层,多一层就多一个故障点。
- 你已经在用成熟的模型网关,并且团队统一走网关流量。网关本身已经在做路由,本地再切配置反而容易跟网关路由打架。
- 你在调试供应商原生 API 参数,需要保留手工修改的灵活性。工具的全量覆盖模式可能会破坏你的实验环境。
换句话说,工具解决的是“频繁切换”的痛点。如果你切换频率一周不到一次,那手动改配置完全够用,不用为了“看起来很酷”引入额外依赖。
我在实际项目里的体会是,这类小工具的定位很像一个“桌面快捷方式管理器”——它不生产模型,也不消费模型,只是让你点击一下就打开正确的那扇门。15MB 的体积、单文件部署、无后台进程,换来的是一整个工作流的顺滑体验。如果你正在为“Codex 和 Claude Code 切来切去”这件事烦恼,我建议你花十分钟把供应商槽位配好,接下来的时间,它会替你把所有配置混乱都挡在门外。