1. 从零认识 openrig:它到底解决什么问题
第一次看到 openrig 这个名字,很多人会以为是某个硬件项目,毕竟“rig”在英文里常指设备支架或矿机机架。但如果你最近在折腾 Claude Code、Codex 这类终端 AI 编程助手,就会明白它出现的背景:这些工具本身很强,但它们的会话管理、多模型切换、本地代理转发、终端复用等环节,官方并没有给你一套开箱即用的完整方案。openrig 就是在这个缝隙里长出来的东西——它把 Claude Code、Codex、Node.js 运行时、tmux 会话管理这几块拼在一起,形成一套可复用的本地开发工作台。
我最初接触 openrig 是因为一个很具体的痛点:我在 Ubuntu 服务器上跑 Claude Code 做代码审查,同时想用 Codex 处理另一条任务线,结果两个工具抢终端、抢环境变量、抢 API 端点,切换一次要重开好几个窗口。后来看到有人在讨论用 tmux 做会话隔离、用 Node.js 做中间层转发请求,再配合 openrig 的思路把配置统一管起来,才意识到这套组合的价值不在于某个单点工具,而在于“编排”。
openrig 适合谁?如果你只是偶尔在 VS Code 里用一下 Claude Code 补全代码,那可能不需要它。但如果你符合以下任意一条,它就值得你花时间:每天有大量终端 AI 编程任务、需要在多个模型供应商之间切换、要在远程服务器上保持长会话、或者受够了每次安装 Claude Code 和 Codex 时被 Node.js 版本问题折磨。这篇文章我会从设计思路讲到实操落地,把 openrig 相关的核心环节全部拆开,包括 Node.js 环境准备、Claude Code 与 Codex 的安装配置、tmux 会话编排、本地模型接入、以及那些官方文档不会告诉你的坑。
2. openrig 的整体设计思路与方案选型
2.1 为什么是“编排”而不是“集成”
openrig 的核心哲学不是把 Claude Code 和 Codex 合并成一个软件,而是让它们各自保持独立,通过外部编排层来协同。这个选择背后有很实际的考量。Claude Code 和 Codex 的更新频率都很高,如果你做一个深度集成的封装,每次上游更新你都要跟着改,维护成本极高。而编排层的思路是:我只管启动、隔离、转发、记录,具体工具内部怎么变,我不管。
这就像你家里同时有洗衣机和烘干机,你不会去买一台“洗烘一体机”然后把两个功能焊死,而是让它们各自独立,你用流程把它们串起来。openrig 在这一点上做得很克制,它依赖的是 Node.js 生态的通用能力加上 tmux 的会话隔离,而不是去改 Claude Code 或 Codex 的源码。
另一个关键选型是 tmux。很多人会问,为什么不用 screen,或者干脆用 systemd 管理进程?tmux 的优势在于它同时提供了会话持久化和窗口分屏,你可以在一个 SSH 连接里同时看到 Claude Code 的交互界面和 Codex 的日志输出,而且断开 SSH 后会话不丢。systemd 更适合守护进程,不适合交互式 AI 编程这种需要实时输入输出的场景。screen 虽然也能持久化,但它的分屏和脚本化能力比 tmux 弱不少,尤其是在自动化配置方面。
2.2 Node.js 在 openrig 里的角色定位
Claude Code 和 Codex 的 CLI 版本都是基于 Node.js 分发的,这意味着 Node.js 的版本管理直接决定了这两个工具能不能跑起来。我见过太多人卡在error installing 24.21.0: node.js v24.21.0 is not yet released or is not available这种报错上,本质上就是 Node.js 版本和工具要求的版本不匹配。
openrig 的思路是:不依赖系统自带的 Node.js,而是用版本管理器(nvm 或 fnm)来隔离。系统自带的 Node.js 往往版本老旧,而且你用 apt 升级会牵扯到一堆系统依赖。用 nvm 的好处是你可以为 Claude Code 和 Codex 分别指定不同的 Node.js 版本,互不干扰。比如 Claude Code 某个版本要求 Node 20.x,而 Codex 要求 Node 22.x,在 nvm 下就是两条命令的事。
这里有个细节值得展开:Node.js 的 LTS 版本和 Current 版本选择。很多人看到node.js lts下载就去下 LTS,这没错,但要注意 Claude Code 和 Codex 的 package.json 里 engines 字段的要求。我实测下来,Node.js 20 LTS 对这两个工具的兼容性最稳,22 LTS 也可以但偶尔会有依赖包报 warning。Current 版本(比如 23、24)不建议用于生产环境,因为很多 native 模块还没跟上。
2.3 本地代理与多模型接入的架构
openrig 另一个核心能力是本地代理转发。你可能会遇到cc switch local proxy failed while handling codex endpoint /responses这类报错,这通常是因为代理层没有正确区分 Claude Code 和 Codex 的端点路径。Claude Code 走的是 Anthropic 风格的 API,Codex 走的是 OpenAI 风格的/responses端点,如果你用一个统一的代理去转发,就必须做路径匹配和请求头改写。
openrig 在这块的设计是:代理层只做三件事——鉴权替换、路径重写、日志记录。鉴权替换是指把你本地的 API Key 注入到请求头里,这样 Claude Code 和 Codex 本身不需要知道 Key 的存在。路径重写是指根据请求的 endpoint 判断目标供应商,比如/v1/messages转发到 Anthropic,/responses转发到 OpenAI 或兼容端点。日志记录则是为了排查问题,尤其是当你接入 DeepSeek、Qwen、GLM 这类第三方模型时,请求格式的差异会导致各种奇怪报错。
这个架构的好处是你可以在 openrig 层面统一管理 API Key,而不是在每个工具里分别配置。坏处是代理层本身会成为单点,如果代理挂了,两个工具都用不了。所以我在实际部署时会加一个健康检查,代理进程异常时自动重启,并且把日志写到固定位置方便排查。
3. 核心环境搭建:Node.js 与 tmux 的实操配置
3.1 Node.js 版本管理的正确姿势
先说结论:不要用系统包管理器安装 Node.js。Ubuntu 上apt install nodejs装出来的版本往往落后好几个大版本,而且 npm 的全局路径会和系统路径打架。正确的做法是用 nvm。
安装 nvm 的命令很简单:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash装完之后记得source ~/.bashrc或者重开终端。然后安装 Node.js 20 LTS:
nvm install 20 nvm use 20 nvm alias default 20这里有个坑:如果你之前用 apt 装过 Node.js,nvm 的路径可能不会优先生效。用which node检查一下,如果指向/usr/bin/node而不是~/.nvm/versions/node/...,说明 PATH 顺序有问题。解决办法是在.bashrc里把 nvm 的初始化脚本放到 PATH 设置之后。
另一个常见问题是node.js v24.21.0 is not yet released or is not available。这个报错通常出现在你用 nvm 安装一个还不存在的版本时。Node.js 的版本号是严格递增的,24.21.0 如果还没发布,nvm 就会报这个错。解决办法是nvm ls-remote看一下当前可用的最新版本,然后装那个。
对于 Claude Code 和 Codex,我建议用同一个 Node.js 版本,减少变量。实测 Node.js 20.18.0 对两个工具的兼容性最好。如果你非要用不同版本,可以在 tmux 的不同窗口里分别nvm use,但这样会增加心智负担。
3.2 tmux 会话编排的实战配置
tmux 的默认配置比较简陋,openrig 场景下我建议做几项定制。首先是前缀键,默认是Ctrl+b,但如果你在 VS Code 的终端里用,这个键可能会冲突。改成Ctrl+a更顺手:
# ~/.tmux.conf set -g prefix C-a unbind C-b bind C-a send-prefix然后是窗口和面板的编号从 1 开始,而不是 0:
set -g base-index 1 setw -g pane-base-index 1最关键的是会话持久化配置。openrig 的核心价值之一就是 SSH 断开后 Claude Code 和 Codex 的会话不丢。tmux 默认就支持这个,但你需要确保服务器上的 tmux 版本不要太老。Ubuntu 20.04 自带的 tmux 3.0a 就够用,但如果你要用一些新特性比如popup,就需要 3.2 以上。
我通常会创建一个启动脚本,一键拉起整个工作台:
#!/bin/bash SESSION="openrig" tmux new-session -d -s $SESSION -n claude tmux send-keys -t $SESSION:claude "cd ~/projects && claude" C-m tmux new-window -t $SESSION -n codex tmux send-keys -t $SESSION:codex "cd ~/projects && codex" C-m tmux new-window -t $SESSION -n logs tmux send-keys -t $SESSION:logs "tail -f ~/.openrig/proxy.log" C-m tmux select-window -t $SESSION:claude tmux attach -t $SESSION这个脚本做了三件事:创建一个叫 openrig 的会话,开三个窗口分别跑 Claude Code、Codex 和日志监控,最后 attach 到 claude 窗口。你断开 SSH 后,这三个进程继续在后台跑,下次连上来tmux attach -t openrig就能恢复现场。
注意:tmux 会话里的进程不会因为你退出 SSH 而终止,但如果你重启服务器,所有会话都会丢。生产环境建议配合 systemd 做开机自启,或者至少把关键配置和日志持久化到磁盘。
3.3 环境变量与配置文件的隔离策略
Claude Code 和 Codex 都会读环境变量,比如ANTHROPIC_API_KEY和OPENAI_API_KEY。如果你在同一个 shell 里同时跑两个工具,环境变量会互相污染。openrig 的解法是在 tmux 的不同窗口里用不同的 env 文件。
具体做法是在项目目录下放两个文件:.env.claude和.env.codex。然后在 tmux 的 send-keys 里先 source 对应的文件:
tmux send-keys -t $SESSION:claude "source ~/.openrig/.env.claude && claude" C-m tmux send-keys -t $SESSION:codex "source ~/.openrig/.env.codex && codex" C-m这样 Claude Code 窗口里只有 Anthropic 相关的变量,Codex 窗口里只有 OpenAI 相关的变量,互不干扰。如果你用 cc switch 这类工具做模型切换,也要注意它的配置作用域,避免全局污染。
4. Claude Code 与 Codex 的安装配置全流程
4.1 Claude Code 安装与首次配置
Claude Code 的安装方式有几种,最推荐的是 npm 全局安装:
npm install -g @anthropic-ai/claude-code装完之后运行claude会进入首次配置流程,要求你登录或输入 API Key。如果你在 Ubuntu 服务器上没有浏览器,可以用claude login生成一个链接,在本地浏览器打开完成授权。但这里有个常见报错:your organization has disabled claude subscription access for claude code。这通常是因为你的账号类型不支持 Claude Code,需要用 API Key 方式而不是订阅方式。
API Key 方式的配置是在~/.claude/config.json里写入:
{ "apiKey": "sk-ant-xxxxxxxx", "model": "claude-sonnet-4-20250514" }如果你要接入本地模型(比如通过 LM Studio),需要把baseUrl指向本地端点:
{ "apiKey": "local", "baseUrl": "http://localhost:1234/v1", "model": "local-model" }这里要注意,Claude Code 对本地模型的支持是通过 OpenAI 兼容接口实现的,所以 LM Studio 那边要开启 OpenAI 兼容模式。实测下来,LM Studio 的/v1/chat/completions端点可以被 Claude Code 识别,但/v1/messages不行,因为那是 Anthropic 特有的格式。
VS Code 里配置 Claude Code 是另一个高频需求。安装 Claude Code 的 VS Code 扩展后,在 settings.json 里加:
{ "claude-code.apiKey": "sk-ant-xxxxxxxx", "claude-code.model": "claude-sonnet-4-20250514" }但 VS Code 扩展和 CLI 的配置是分开的,你在 CLI 里配的 API Key 不会自动同步到扩展。这是个容易踩的坑,很多人以为配一次就行,结果在 VS Code 里一直报鉴权失败。
4.2 Codex 安装与端点配置
Codex 的安装同样走 npm:
npm install -g @openai/codex首次运行codex会要求登录。如果你用 OpenAI 官方服务,直接codex login走浏览器授权。如果你要接入 DeepSeek 或其他第三方模型,需要配置自定义端点。
Codex 的配置文件在~/.codex/config.json:
{ "apiKey": "sk-xxxxxxxx", "baseUrl": "https://api.deepseek.com/v1", "model": "deepseek-chat" }这里有个关键点:Codex 走的是/responses端点,而不是/chat/completions。很多第三方模型供应商只支持/chat/completions,这时候你就需要一个代理层做路径转换。openrig 的代理就是干这个的:它接收 Codex 发来的/responses请求,转换成/chat/completions发给供应商,再把响应转回 Codex 能识别的格式。
如果你看到codex is ignoring 1 unrecognized configuration setting这个警告,说明你的 config.json 里有一个字段 Codex 不认识。这通常是因为你抄了旧版本的配置模板,而新版本改了字段名。解决办法是codex config --help看一下当前版本支持的字段,把不认识的删掉。
codex无法加载组织设置这个报错则通常和账号权限有关。如果你用的是 OpenAI 的团队账号,可能需要管理员在后台开启 Codex 权限。个人账号一般不会有这个问题。
4.3 用 cc switch 做多模型切换
cc switch 是一个社区工具,用来在 Claude Code 和 Codex 之间切换不同的模型供应商。它的核心功能是管理多套配置,然后根据你的选择把对应的配置写入 Claude Code 或 Codex 的配置文件。
安装 cc switch:
npm install -g cc-switch然后添加一个配置:
cc-switch add deepseek --provider deepseek --api-key sk-xxxxxxxx --model deepseek-chat切换到这个配置:
cc-switch use deepseekcc switch 会把 deepseek 的配置写入~/.claude/config.json或~/.codex/config.json,具体写哪个取决于你当前激活的是 Claude Code 还是 Codex。
但这里有个坑:cc switch local proxy failed while handling codex endpoint /responses这个报错就是 cc switch 的代理层在处理 Codex 请求时失败了。原因通常是 cc switch 的代理没有正确识别/responses端点,或者供应商不支持这个端点。解决办法是检查 cc switch 的版本,新版本一般修复了这个问题;如果还不行,就手动配 Codex 的 baseUrl,绕过 cc switch 的代理。
5. 本地模型接入与代理层调试
5.1 Claude Code 调用 LM Studio 本地模型的完整步骤
LM Studio 是一个本地模型运行工具,支持 OpenAI 兼容接口。要让 Claude Code 调用 LM Studio 的模型,需要几步配置。
第一步,在 LM Studio 里加载一个模型,比如 Qwen2.5-Coder-7B,然后启动本地服务器。默认端口是 1234,端点地址是http://localhost:1234/v1。
第二步,修改 Claude Code 的配置:
{ "apiKey": "lm-studio", "baseUrl": "http://localhost:1234/v1", "model": "qwen2.5-coder-7b-instruct" }第三步,测试连接:
curl http://localhost:1234/v1/models如果返回模型列表,说明 LM Studio 那边没问题。然后运行claude测试对话。
这里有个常见问题:Claude Code 默认走 Anthropic 的/v1/messages端点,而 LM Studio 只支持/v1/chat/completions。所以你需要一个代理做转换。openrig 的代理层可以配置路径映射:
{ "routes": [ { "from": "/v1/messages", "to": "/v1/chat/completions", "target": "http://localhost:1234" } ] }这样 Claude Code 发到/v1/messages的请求会被转发到 LM Studio 的/v1/chat/completions,响应再转回 Anthropic 格式。
实测下来,7B 级别的本地模型在代码补全场景下响应速度可以接受,但复杂推理任务还是建议用云端模型。另外 LM Studio 的上下文长度限制要注意,默认可能是 4096,对于长代码文件不够用,需要在加载模型时手动调到 8192 或更高。
5.2 代理层日志分析与故障定位
openrig 的代理层日志是排查问题的关键。我通常会把日志级别调到 debug,记录完整的请求和响应头。但要注意,debug 日志会包含 API Key,所以日志文件权限要设成 600。
一个典型的代理日志长这样:
[2025-01-15 10:23:45] REQ /v1/messages -> anthropic [2025-01-15 10:23:45] HEADERS: x-api-key=sk-ant-***, content-type=application/json [2025-01-15 10:23:46] RESP 200 (1.2s)如果看到RESP 401,说明鉴权失败,检查 API Key 是否正确注入。如果看到RESP 404,说明路径映射有问题,检查 routes 配置。如果看到RESP 429,说明触发了速率限制,需要降低请求频率或换供应商。
cc switch local proxy failed while handling codex endpoint /responses这个报错在日志里通常会显示为:
[ERROR] No route matched for /responses这说明代理层没有为/responses配置路由。解决办法是在 routes 里加一条:
{ "from": "/responses", "to": "/v1/chat/completions", "target": "https://api.deepseek.com" }但要注意,Codex 的/responses请求格式和 OpenAI 的/chat/completions不完全一样,直接转换可能会丢字段。更稳妥的做法是用一个专门的转换层,把 Codex 的请求体映射成标准 OpenAI 格式。
5.3 多供应商切换时的配置管理
当你同时接入 Anthropic、OpenAI、DeepSeek、Qwen、GLM 等多个供应商时,配置管理会变得复杂。我的做法是用一个统一的配置文件~/.openrig/providers.json:
{ "anthropic": { "baseUrl": "https://api.anthropic.com", "apiKey": "sk-ant-xxxxxxxx", "models": ["claude-sonnet-4-20250514"] }, "deepseek": { "baseUrl": "https://api.deepseek.com", "apiKey": "sk-xxxxxxxx", "models": ["deepseek-chat", "deepseek-coder"] }, "qwen": { "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1", "apiKey": "sk-xxxxxxxx", "models": ["qwen-max", "qwen-coder-plus"] } }然后写一个切换脚本,根据参数把对应供应商的配置写入 Claude Code 或 Codex 的配置文件。这样你只需要维护一份 providers.json,切换时跑一下脚本就行。
提示:不同供应商的 API 格式差异很大,尤其是请求头和响应结构。Anthropic 用
x-api-key,OpenAI 用Authorization: Bearer。代理层必须做请求头转换,否则会一直 401。
6. 常见问题排查与避坑经验实录
6.1 安装阶段的典型报错与解决
安装阶段最常见的问题集中在 Node.js 版本和网络环境上。我整理了一个速查表:
| 报错信息 | 根本原因 | 解决办法 |
|---|---|---|
error installing 24.21.0: node.js v24.21.0 is not yet released | 指定的 Node.js 版本不存在 | nvm ls-remote查看可用版本,装最新的 LTS |
npm ERR! code EACCES | npm 全局目录权限不足 | 用 nvm 管理 Node.js,不要用 sudo npm |
claude: command not found | npm 全局 bin 目录不在 PATH | 检查npm bin -g输出,加入 PATH |
codex is ignoring 1 unrecognized configuration setting | 配置文件字段名过时 | 对照官方文档更新 config.json |
your organization has disabled claude subscription access | 账号类型不支持 | 改用 API Key 方式配置 |
npm ERR! code EACCES这个坑我踩过好几次。根本原因是系统自带的 Node.js 把全局目录设成了/usr/lib/node_modules,普通用户没写权限。用 nvm 之后,全局目录变成~/.nvm/versions/node/v20.18.0/lib/node_modules,权限问题自然消失。所以如果你还在用sudo npm install -g,赶紧换成 nvm。
另一个高频问题是网络超时。npm 默认走官方源,在国内环境下可能会很慢。可以换成国内镜像源:
npm config set registry https://registry.npmmirror.com但要注意,有些包在镜像源上可能不是最新版本,如果你需要特定版本,可以临时切回官方源。
6.2 运行阶段的会话与端点问题
运行阶段的问题主要集中在会话管理和端点匹配上。cc switch local proxy failed while handling codex endpoint /responses这个报错我在前面提过,这里再补充一个排查思路:先确认 Codex 的 baseUrl 指向的是 cc switch 的代理端口,而不是直接指向供应商。如果 baseUrl 配错了,请求根本不会经过代理,自然也就不会有路由匹配。
codex无法加载组织设置这个问题通常出现在团队账号上。如果你确认账号权限没问题,可以试一下清除 Codex 的缓存:
rm -rf ~/.codex/cache codex login重新登录后一般能解决。如果还不行,检查一下系统时间是否准确,OAuth 流程对时间偏差很敏感,偏差超过几分钟就会失败。
Claude Code 在 VS Code 里不工作也是高频问题。首先确认扩展版本和 CLI 版本匹配,然后检查 VS Code 的终端环境变量是否包含了 Claude Code 的配置。VS Code 的集成终端有时候不会加载.bashrc,导致 nvm 的 PATH 没生效。解决办法是在 VS Code 的 settings.json 里加:
{ "terminal.integrated.env.linux": { "PATH": "${env:HOME}/.nvm/versions/node/v20.18.0/bin:${env:PATH}" } }6.3 多模型切换时的鉴权与格式陷阱
多模型切换最容易出问题的地方是鉴权和请求格式。不同供应商的鉴权方式不一样:
| 供应商 | 鉴权头 | 端点路径 | 请求格式 |
|---|---|---|---|
| Anthropic | x-api-key | /v1/messages | Anthropic 格式 |
| OpenAI | Authorization: Bearer | /v1/chat/completions | OpenAI 格式 |
| DeepSeek | Authorization: Bearer | /v1/chat/completions | OpenAI 格式 |
| Qwen | Authorization: Bearer | /compatible-mode/v1/chat/completions | OpenAI 格式 |
如果你用 cc switch 做切换,它会自动处理鉴权头的转换。但如果你手动配,就必须确保请求头正确。我见过有人把 Anthropic 的 Key 配到 OpenAI 的 baseUrl 上,结果一直 401,排查了半天才发现是鉴权头不匹配。
请求格式的差异更隐蔽。Anthropic 的messages格式里,system是一个独立字段,而 OpenAI 把它放在messages数组的第一条。如果你用代理做转换,必须处理这个差异,否则模型会忽略 system prompt,导致输出质量下降。
注意:切换供应商后一定要跑一个简单的测试对话,确认鉴权和格式都正确。不要等到跑了半天任务才发现输出不对,那时候已经浪费了很多 token。
7. 我个人的实操体会与后续扩展方向
这套 openrig 工作流我用了大概三个月,最大的体会是:编排层的价值在于“稳定压倒一切”。Claude Code 和 Codex 本身更新很频繁,有时候一个新版本就会改配置格式或者端点路径。如果你把配置散落在各处,每次更新都是一场灾难。而用 openrig 的思路把配置集中管理、用 tmux 做会话隔离、用代理层做格式转换,上游怎么变你只需要改一个地方。
另一个体会是日志的重要性。我一开始没在意代理日志,结果遇到cc switch local proxy failed while handling codex endpoint /responses的时候完全不知道从哪下手。后来把日志级别调到 debug,才发现是路由没匹配上。现在我养成了习惯,每次改配置后先看日志确认请求路径和响应状态,再跑正式任务。
后续我打算在这套基础上加两个东西:一是自动健康检查,代理进程挂了自动重启并通知;二是会话录制,把 Claude Code 和 Codex 的交互记录存下来,方便回溯和复用。这两个功能都不复杂,用 shell 脚本加 cron 就能实现,关键是先把基础工作流跑稳。
如果你也在折腾 Claude Code 和 Codex 的多模型工作流,我的建议是先从 Node.js 版本管理和 tmux 会话隔离做起,这两块稳了,后面的代理和切换都是水到渠成的事。不要一上来就搞复杂的代理层,先把单工具跑通,再逐步加编排。踩过的坑多了,自然就知道哪些环节需要加固。