
我先说一个很反直觉的事实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-usecc-switch use echo --- codex config --- cat ~/.codex/config.toml4. 云端与本地混搭把 Codex 切到 DeepSeek把 Claude Code 指向 LM Studio4.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 foundapi_key决定鉴权方式本地服务填 dummy 即可云端必须真实密钥我自己混搭的经验是先找一个最简单的槽位跑通再逐渐加复杂供应商。比如先在 Codex 里把官方 OpenAI 的槽位跑通再加 DeepSeek最后加本地模型。每加一个切一次用一句话提问验证再继续下一个。5. 我在切换途中踩过的三个坑跳闪、/responses 404 和未知配置项5.1 切换模型后原对话不停跳闪有不少人遇到过“切换模型后原对话不停跳闪”的现象界面里光标疯狂闪烁但就是不输出内容看起来像卡死。我最早也以为是工具坏了后来定位到原因切换发生在旧会话仍然存活的时候。你的 CLI 进程还在运行仍然持有旧的模型上下文和旧的 API 地址。你切了配置旧进程并不知情它可能还在向旧地址发请求或者疯狂重试导致界面表现异常。解决办法有三个层次切换前先退出正在运行的 Codex / Claude Code 会话再执行cc-switch use。如果已经出现跳闪直接 CtrlC 终止会话新开终端重新进入。不要在同一终端里反复横跳尽量做到“一个终端窗口只服务一种模型环境”。这个坑本质上不是工具的 bug而是使用习惯问题。切配置和开新会话必须是连续动作中间不要隔着一个还在跑的进程。后来我把切换命令和启动命令合并成了一个别名alias cdx-docc-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 URLcodex --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-openaiOpenAI 官方 Codex 模型用于日常主力 coding。work-deepseekDeepSeek 模型用于需要舔 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 切来切去”这件事烦恼我建议你花十分钟把供应商槽位配好接下来的时间它会替你把所有配置混乱都挡在门外。