1. openrig 到底是什么:从一个标题拆出来的真实需求
第一次看到 "openrig" 这个词,我脑子里蹦出来的不是某个具体产品,而是一类很典型的需求:把散落在各处的 AI 编码工具,用一个统一的、可配置的、开源的方式"装配"起来。rig 这个词在英文里有"装配、搭台子"的意思,open 则点明了它的开源属性。合在一起,openrig 想干的事情就很清楚了——给 Claude Code、Codex 这类命令行 AI 编码助手搭一个开放的配置骨架,让它们能被统一管理、统一切换、统一接入不同的模型后端。
为什么会有这种需求?因为现在用 AI 写代码的人,手里往往不止一个工具。Claude Code 擅长长上下文理解和复杂重构,Codex 系列在补全和快速生成上很顺手,本地还跑着 LM Studio 或者接入了 DeepSeek、Qwen、GLM 这些模型的第三方 API。工具一多,问题就来了:每个工具都有自己的配置文件、自己的环境变量、自己的模型映射规则。今天想用 Claude Code 调本地模型,明天想让 Codex 走 DeepSeek 的接口,后天又想在 VS Code 里同时用两个——如果没有一套统一的装配方案,光是改配置就能把人折腾疯。
openrig 要解决的就是这个"装配"问题。它大概率是一个基于 YAML 配置 + Node.js 运行时的工具集或者配置框架,核心思路是用一份声明式的配置文件,描述清楚"我要用哪些 AI 编码工具、每个工具走哪个模型端点、各自的参数是什么",然后由 openrig 负责把这些配置翻译成各个工具能识别的格式,完成注入和启动。这跟当年 Docker Compose 解决"多个容器怎么编排"是同一个思路——你不需要记住每个容器的启动参数,写一份 compose 文件就行。
适合谁来参考?三类人最需要。第一类是同时使用多个 AI 编码工具的开发者,尤其是那些在 Claude Code 和 Codex 之间来回切换的人。第二类是想把本地模型接入云端工具链的玩家,比如用 LM Studio 跑本地模型,然后让 Claude Code 去调用。第三类是团队里负责工具链统一的技术负责人,需要一套可复制、可版本管理的配置方案,而不是每个人各自为战。如果你只是偶尔用用一个工具,那 openrig 这套东西可能有点重;但只要你的工具超过两个,或者需要在不同模型后端之间频繁切换,这套装配思路就非常值得研究。
2. 核心设计思路:为什么是 YAML + Node.js 这套组合
2.1 声明式配置为什么比命令行参数更靠谱
openrig 选择 YAML 作为配置载体,这个决定背后有很实在的考量。你完全可以用命令行参数来启动 Claude Code 或者 Codex,比如指定模型、指定 API 端点、指定超时时间。但命令行参数的问题是:它是一次性的、不可追溯的、难以版本管理的。今天你敲了一长串参数启动成功,明天想复现同样的环境,得翻历史记录或者凭记忆重敲。团队协作时更麻烦,你没法把"我是怎么配的"这件事优雅地交给同事。
YAML 的好处在于它是声明式的。你描述的是"最终状态应该是什么样",而不是"一步步怎么操作"。一份典型的 openrig 配置大概长这样:
version: "1" tools: claude-code: enabled: true provider: local endpoint: http://127.0.0.1:1234/v1 model: qwen2.5-coder-32b env: ANTHROPIC_BASE_URL: http://127.0.0.1:1234 ANTHROPIC_API_KEY: local-key codex: enabled: true provider: deepseek endpoint: https://api.deepseek.com/v1 model: deepseek-coder env: OPENAI_BASE_URL: https://api.deepseek.com/v1 OPENAI_API_KEY: ${DEEPSEEK_KEY}这份配置把"用哪些工具、每个工具走哪个后端、模型叫什么、环境变量怎么设"全部说清楚了。它可以直接提交到 Git 仓库,可以 code review,可以按环境(开发/测试/生产)拆成不同的 profile。这就是声明式的价值——配置即文档,配置即契约。
提示:YAML 对缩进极其敏感,一律用空格,绝对不要用 Tab。我见过太多人因为编辑器自动把 Tab 转成空格或者反过来,导致配置解析失败,排查半天以为是工具的问题,其实是缩进。
2.2 Node.js 作为运行时的现实理由
为什么是 Node.js 而不是 Python 或者 Go?这里有几个很实际的原因。首先,Claude Code 和 Codex 这类工具本身就是 Node.js 生态的产物,它们的 CLI 是通过 npm 分发的,运行时依赖 Node.js。openrig 要做的核心工作是"读取配置、生成各工具需要的环境、拉起子进程",用 Node.js 来做这件事,跟被装配的工具处在同一个运行时里,进程管理、环境变量传递、路径解析都最顺。
其次,Node.js 的跨平台一致性比较好。同一份 openrig 配置和脚本,在 macOS、Linux、Windows 上行为基本一致,这对需要多人多机协作的场景很重要。第三,npm 生态里有大量现成的库可以处理 YAML 解析、进程管理、模板渲染,不需要自己造轮子。
版本选择上有个坑要提前说。热搜词里出现了 "error installing 24.21.0: node.js v24.21.0 is not yet released",这说明有人试图安装一个还不存在的版本。Node.js 的版本号是有规律的:偶数大版本是 LTS(长期支持),奇数大版本是 Current(尝鲜)。生产环境或者日常开发,建议用 LTS 版本,比如 20.x 或者 22.x。安装方式上,Ubuntu 用户不要直接用 apt 装,apt 源里的 Node.js 版本往往很旧,推荐用 NodeSource 的源或者 nvm 来管理。
# 用 nvm 安装并切换到 Node.js 20 LTS curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 20 nvm use 20 node -v # 应该输出 v20.x.x用 nvm 的好处是可以在多个 Node.js 版本之间切换。有些老项目依赖 Node 16,新工具要求 Node 20+,nvm 让你不用卸载重装就能来回切。这一点在同时维护多个 AI 编码工具时特别有用,因为不同工具对 Node.js 版本的要求可能不一样。
2.3 统一装配层要解决的三类冲突
openrig 这类工具真正要处理的,是三类配置冲突。第一类是环境变量冲突。Claude Code 读ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,Codex 读OPENAI_BASE_URL和OPENAI_API_KEY,如果你在同一个 shell 里同时导出这两组变量,它们本身不冲突,但一旦你想让两个工具走同一个本地端点,就得分别设置,容易漏。openrig 的做法是在配置里为每个工具单独声明 env 块,启动时按工具注入,互不干扰。
第二类是模型名称映射冲突。同一个本地模型,在 LM Studio 里可能叫qwen2.5-coder-32b,在 Claude Code 的语境里需要映射成它认识的模型名,在 Codex 里又是另一套命名。openrig 需要在配置层做一层映射,把"逻辑模型名"翻译成"各工具认识的模型名"。
第三类是端点协议冲突。Claude Code 走的是 Anthropic 的 Messages API 格式,Codex 走的是 OpenAI 的 Chat Completions 格式。本地模型服务(比如 LM Studio)通常只提供 OpenAI 兼容接口,这时候就需要一个协议转换层。热搜词里提到的 "cc switch local proxy failed while handling codex endpoint /responses" 就是这类问题的典型表现——代理在处理 Codex 的/responses端点时失败了,本质上是协议不匹配或者端点路径没配对。
3. 核心细节拆解:配置、端点与模型映射的实操要点
3.1 YAML 配置文件的结构设计
一份能用的 openrig 配置,结构上要分几层。最外层是版本和全局设置,中间层是工具列表,每个工具下面是该工具的具体参数。我建议的结构是这样:
version: "1" global: log_level: info proxy_port: 8787 profiles: local: description: "全部走本地 LM Studio" cloud: description: "走云端 API" tools: claude-code: profile: local endpoint: http://127.0.0.1:1234 model_map: default: qwen2.5-coder-32b fast: qwen2.5-coder-7b codex: profile: cloud endpoint: https://api.deepseek.com/v1 model_map: default: deepseek-coder这里引入了profiles的概念,是为了解决"同一套工具在不同场景下走不同后端"的问题。你在本地开发时用 local profile,全部指向本机跑的模型;到了需要更强能力的时候切到 cloud profile,走云端 API。切换只需要改一个 profile 引用,不用动每个工具的细节。
model_map则是解决模型名映射问题的。工具在调用时通常会说"我要 default 模型",openrig 根据 model_map 把它翻译成实际的后端模型名。这样上层工具不用关心后端到底叫什么,换后端时只改 model_map 就行。
注意:YAML 里的布尔值
true/false不要加引号,加了引号就变成字符串了。同理,端口号如果写成"8787"带引号,某些解析器会当成字符串处理,传给需要数字的地方可能报错。这类细节在配置量大的时候特别容易埋雷。
3.2 端点配置与协议适配的关键参数
端点配置是 openrig 最容易出问题的地方。核心要搞清楚三件事:base URL 要不要带/v1、路径怎么拼、认证头怎么传。
以 Claude Code 接本地 LM Studio 为例。LM Studio 默认在http://127.0.0.1:1234提供 OpenAI 兼容接口,完整的 chat 端点是http://127.0.0.1:1234/v1/chat/completions。但 Claude Code 期望的是 Anthropic 格式的端点。这时候有两种做法:一是让 LM Studio 直接支持 Anthropic 格式(部分版本支持),二是通过一个转换代理把 Anthropic 请求转成 OpenAI 请求。
配置里要明确区分"base URL"和"完整端点"。通常工具接受的是 base URL,然后自己拼路径。如果你把完整端点填进 base URL 的位置,就会出现路径重复,比如变成http://127.0.0.1:1234/v1/chat/completions/v1/messages,直接 404。热搜词里的 "cc switch local proxy failed while handling codex endpoint /responses" 很可能就是路径拼接出了问题——代理收到了/responses请求,但它的路由表里没有这个路径,或者它期望的是/v1/responses。
认证方面,本地模型通常不校验 API Key,但工具可能强制要求这个字段非空。这时候随便填一个占位值就行,比如local-key或者sk-local。但要注意,有些工具会校验 Key 的格式,比如必须以sk-开头,那就得按格式填。
| 配置项 | 本地 LM Studio | 云端 DeepSeek | 常见错误 |
|---|---|---|---|
| base URL | http://127.0.0.1:1234 | https://api.deepseek.com | 多写或少写 /v1 |
| API Key | 任意占位值 | 真实 Key | 本地填了空值导致校验失败 |
| 模型名 | qwen2.5-coder-32b | deepseek-coder | 名字拼错或大小写不符 |
| 协议 | OpenAI 兼容 | OpenAI 兼容 | Claude Code 需要转换层 |
3.3 模型映射与回退策略
模型映射不只是改个名字那么简单,还要考虑回退。什么叫回退?就是当首选模型不可用时,自动切到备用模型。比如你配置了default: qwen2.5-coder-32b,但这个模型太大,本地显存不够加载失败,这时候如果能自动回退到qwen2.5-coder-7b,体验会好很多。
在 YAML 里可以这样表达:
model_map: default: primary: qwen2.5-coder-32b fallback: qwen2.5-coder-7b fast: qwen2.5-coder-7bopenrig 在启动工具前,可以先探测 primary 模型是否可用(比如发一个轻量的健康检查请求),不可用就注入 fallback 的模型名。这个探测逻辑要做得轻,不能因为探测本身拖慢启动。我一般建议探测超时设 2 秒,超过就认为不可用直接回退。
另一个映射细节是上下文窗口。不同模型的上下文长度不一样,32b 的模型可能支持 128k,7b 的只支持 32k。如果工具按 128k 去发请求,小模型会直接报错。所以 model_map 里最好把上下文长度也带上,让 openrig 能据此调整工具的配置。
4. 完整实操流程:从零把 openrig 跑起来
4.1 环境准备:Node.js 与包管理器的正确安装姿势
第一步是把 Node.js 装对。前面说了用 nvm,这里把完整流程走一遍。Ubuntu 环境下,先装 nvm,再装 Node.js 20 LTS,然后验证。
# 安装 nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 让 nvm 在当前 shell 生效 export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # 安装 Node.js 20 LTS nvm install 20 nvm alias default 20 # 验证 node -v npm -v装完之后,建议把 npm 的源换成国内镜像,不然装包会很慢。但要注意,有些企业内网有自己的私有源,换之前先确认。
npm config set registry https://registry.npmmirror.com包管理器方面,npm 够用,但如果你经常装全局包,pnpm 会更省空间也更快。openrig 本身如果是通过 npm 分发的,用哪个包管理器装都行,关键是全局 bin 目录要在 PATH 里。
提示:如果你在 Windows 上,nvm 的 Windows 版本叫 nvm-windows,用法略有不同,安装包直接去 GitHub release 页面下载。装完之后同样用
nvm install 20和nvm use 20。Windows 上还要注意,某些工具对路径中的空格和中文敏感,尽量把项目放在纯英文无空格的路径下。
4.2 安装与初始化 openrig
假设 openrig 通过 npm 分发,安装命令大概是:
npm install -g openrig openrig initopenrig init会在当前目录生成一份默认的openrig.yaml配置文件,以及一个.openrig目录用来存放运行时状态。初始化之后,第一件事是检查生成的配置模板,把里面的占位符换成你自己的实际值。
如果 openrig 不是通过 npm 分发,而是需要从源码构建,那流程通常是:
git clone <openrig-repo> cd openrig npm install npm run build npm link # 把本地构建的版本链接到全局npm link这一步很关键,它让你能在任意目录下用openrig命令,同时用的是你本地构建的版本,方便调试和改代码。
初始化完成后,用openrig doctor之类的诊断命令检查环境。这类命令通常会检查 Node.js 版本、配置文件语法、端点连通性、各工具是否已安装。如果 doctor 报错,按提示逐个解决,不要跳过。
4.3 配置 Claude Code 走本地模型
Claude Code 接本地模型是很多人最关心的场景。核心是设置两个环境变量:ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY。在 openrig 配置里这样写:
tools: claude-code: enabled: true env: ANTHROPIC_BASE_URL: http://127.0.0.1:1234 ANTHROPIC_API_KEY: local-key ANTHROPIC_MODEL: qwen2.5-coder-32b然后在 LM Studio 里加载好模型,启动本地服务,确认http://127.0.0.1:1234/v1/models能返回模型列表。这一步是排查问题的基准——如果这个端点都不通,后面全是白搭。
启动 Claude Code 时,openrig 会把这些环境变量注入到子进程里。你可以用openrig run claude-code这样的命令来启动,而不是直接敲claude。这样做的意义在于,环境变量是 openrig 管理的,不会污染你当前的 shell 会话。
实测下来,Claude Code 接本地模型最大的坑是上下文长度和工具调用能力。本地小模型在工具调用(tool use)上经常不稳定,表现为该调用工具的时候不调用,或者调用格式不对。这不是 openrig 的问题,是模型能力的问题。解决办法是换更大的模型,或者在配置里降低对工具调用的依赖。
4.4 配置 Codex 接入第三方 API
Codex 接第三方 API 相对直接,因为它本身就是 OpenAI 兼容的。以接入 DeepSeek 为例:
tools: codex: enabled: true env: OPENAI_BASE_URL: https://api.deepseek.com/v1 OPENAI_API_KEY: ${DEEPSEEK_API_KEY} OPENAI_MODEL: deepseek-coder这里用了${DEEPSEEK_API_KEY}这种变量引用语法,意思是这个值从环境变量里读,不直接写在配置文件里。这样做是为了安全——配置文件可以提交到 Git,但 API Key 不能。openrig 在加载配置时会做变量替换,把${...}替换成实际的环境变量值。
如果环境变量没设置,openrig 应该报一个清晰的错误,而不是带着空 Key 去请求然后收到 401。这一点在配置校验阶段就要做掉。
Codex 接入时常见的报错是 "your organization has disabled..." 或者 "the model is not supported"。前者通常是账号权限问题,后者是模型名不对。DeepSeek 的模型名要写准确,比如deepseek-coder和deepseek-chat是两个不同的模型,用途不一样。
4.5 在 VS Code 里同时使用多个工具
VS Code 里用 Claude Code 和 Codex,通常是通过各自的扩展。openrig 在这里的作用是保证扩展读到的环境变量是一致的、正确的。VS Code 扩展读环境变量的方式有两种:一种是读系统环境变量,一种是读工作区的.env文件。
我建议的做法是让 openrig 生成一个.env文件放在工作区根目录,VS Code 的扩展配置里指向这个文件。这样配置的源头还是 openrig.yaml,.env只是生成物,不手动改。
openrig export --format dotenv --output .env这个命令把当前 profile 下的所有环境变量导出成.env格式。VS Code 的 Claude Code 扩展和 Codex 扩展如果支持指定 env 文件路径,就指向它。如果不支持,那就得在 VS Code 的 settings.json 里手动配,或者用 openrig 的 VS Code 集成(如果有的话)。
注意:VS Code 扩展和终端里跑的 CLI 可能读的是不同的环境。你在终端里
export的变量,VS Code 扩展不一定能读到,尤其是从图形界面启动的 VS Code。这种情况下,要么重启 VS Code 让它继承新的环境变量,要么用.env文件的方式显式指定。
5. 常见问题与排查技巧实录
5.1 端点连接类问题速查
端点问题是最高频的。下面这张表是我踩坑总结出来的,按报错现象倒查原因。
| 报错现象 | 可能原因 | 排查方法 |
|---|---|---|
| Connection refused | 本地服务没启动 | curl 一下端点看是否通 |
| 404 Not Found | 路径拼接错误 | 检查 base URL 是否多写/少写 /v1 |
| 401 Unauthorized | API Key 缺失或错误 | 检查环境变量是否注入成功 |
| 400 Bad Request | 模型名不对或参数不兼容 | 看返回体里的具体错误信息 |
| 超时 | 端点不可达或模型加载慢 | 先用 curl 测延迟,再调超时参数 |
| 代理处理 /responses 失败 | 协议或路径不匹配 | 确认代理支持该端点路径 |
排查顺序建议从下往上:先确认网络通不通(curl 端点),再确认认证过不过(带 Key 请求),再确认模型名对不对(请求模型列表),最后才怀疑工具本身的配置。这个顺序能帮你快速定位问题在哪一层。
5.2 配置解析类问题
YAML 解析错误往往报得很模糊,比如 "did not find expected key" 或者 "mapping values are not allowed here"。这类错误九成是缩进问题。我的经验是:统一用 2 个空格缩进,编辑器里把 Tab 显示出来,看到 Tab 就替换成空格。另外,YAML 里的冒号后面必须跟一个空格,key:value是错的,key: value才对。
还有一个隐蔽的坑是特殊字符。如果 API Key 或者模型名里包含:、#、@这些字符,在 YAML 里可能需要加引号。比如model: qwen:32b会被解析成两个键值对,必须写成model: "qwen:32b"。这种问题在配置看起来"明明没错"但就是解析失败时,优先怀疑。
5.3 模型调用类问题
模型调用失败的表现很多样。最常见的是"模型不存在",这通常是模型名拼写问题。本地模型的名称大小写敏感,Qwen2.5-Coder和qwen2.5-coder可能被当成两个不同的模型。建议直接从模型列表接口复制名称,不要手敲。
另一个问题是上下文超限。当你给一个只支持 32k 上下文的模型发了一个 100k 的请求,服务端会直接拒绝。openrig 如果能在配置里声明每个模型的上下文长度,就可以在发送前做截断或者报错提示,而不是让请求白白失败。
工具调用(tool use)失败也很常见。本地模型对 tool use 的支持参差不齐,有些模型根本不支持,有些支持但格式不对。判断方法是看请求日志里有没有 tool 相关的字段,以及模型返回里有没有正确格式的 tool call。如果模型不支持,那就只能关掉工具调用功能,退化成纯对话模式。
5.4 进程与环境隔离类问题
openrig 管理多个工具时,进程隔离很重要。如果两个工具共享同一个环境变量空间,一个工具改了变量可能影响另一个。解决办法是每个工具启动时用独立的子进程,环境变量在子进程级别注入,而不是在父进程里全局 export。
在 Node.js 里,用child_process.spawn时通过env选项传入环境变量,就是子进程级别的:
const { spawn } = require('child_process'); const child = spawn('claude', [], { env: { ...process.env, ANTHROPIC_BASE_URL: 'http://127.0.0.1:1234', ANTHROPIC_API_KEY: 'local-key' }, stdio: 'inherit' });这样 Claude Code 拿到的环境变量是独立的,不会影响同时运行的其他工具。stdio: 'inherit'让子进程的输入输出直接连到当前终端,交互体验跟直接运行一样。
提示:Windows 上
spawn调用.cmd或.bat文件时需要加shell: true,否则会报 ENOENT。但加了shell: true之后,环境变量里的特殊字符可能被 shell 解释,要注意转义。这是跨平台开发的一个经典坑。
6. 我个人的一些实操体会
用这套东西有一段时间了,有几个体会比较深。第一,配置文件一定要进版本控制,但 Key 一定要用变量引用。我见过有人把 Key 直接写在 YAML 里然后提交到公开仓库,结果 Key 被扫走,账单爆炸。openrig 的${VAR}语法就是干这个的,用起来。
第二,本地模型和云端模型的能力差距是客观存在的。本地 7b 的模型做代码补全还行,做复杂重构就力不从心。所以我的配置里通常保留两套 profile,简单的活走本地省钱省延迟,复杂的活切云端。openrig 的 profile 机制让这个切换很顺滑。
第三,端点探测这个功能值得自己加。openrig 如果没内置,可以在启动脚本里加一段健康检查,端点不通就提前报错,而不是等工具跑到一半才失败。这个提前量能省很多排查时间。
最后分享一个小技巧:把常用的 openrig 命令做成 shell alias,比如alias or='openrig'、alias orc='openrig run claude-code'、alias orx='openrig run codex'。每天敲几十遍的命令,省下的时间积少成多。配置这东西,用着顺手才会坚持用,坚持用才能体现出统一管理的价值。