☰
openrig:本地AI编码环境编排器,YAML+Node.js统一管理Claude Code与Codex
2026/10/4 7:38:48 网站建设 项目流程

1. 从 openrig 说起:一个被名字耽误的本地 AI 编码环境编排器

第一次看到openrig这个词,我下意识以为是某个硬件测试台架的项目——rig 在工程圈里常指“台架、装置”,open 又暗示开源。结果翻了一圈社区讨论和仓库结构才反应过来,这玩意儿跟硬件没半点关系,它解决的是一个特别具体的痛点:把 Claude Code、Codex 这类命令行 AI 编码工具,和本地模型、第三方 API、YAML 配置、Node.js 运行时这一堆东西,编排成一个可复用、可切换、可版本管理的开发环境。

说白了,openrig干的事情,类似于给 AI 编码工具搭一个“配电箱”。你家里电器多了,不可能每台都单独拉一根线到电表,得有个配电箱统一管理。Claude Code 要连本地 LM Studio,Codex 要接 DeepSeek,明天你又想换成 Qwen 或者 GLM,如果每次都手动改环境变量、改配置文件、重启终端,那效率低得让人抓狂。openrig的思路就是把这些连接关系、模型参数、工具链版本全部写进 YAML,用一个统一的入口去加载和切换。

这个项目适合谁?三类人最需要它。第一类是同时用多个 AI 编码工具的开发者,比如白天用 Claude Code 写业务代码,晚上用 Codex 跑实验脚本,两边模型配置完全不同。第二类是喜欢折腾本地模型的玩家,手里有 LM Studio 或者 Ollama,想让 Claude Code 调用本地模型而不是走云端。第三类是团队里负责统一开发环境的人,需要把一套配置固化下来,让新同事 clone 下来就能跑,而不是花半天装 Node.js、配 YAML、调 API 地址。

我实测下来,openrig的核心价值不在于它自己有多复杂,而在于它把那些散落在各处的配置碎片——Node.js 版本、YAML 文件路径、API endpoint、模型名称、代理设置——收拢到一个地方。你不需要记住 Claude Code 的配置文件在~/.claude/settings.json还是~/.config/claude/,也不需要知道 Codex 的config.toml到底该放哪。openrig用一层抽象把这些差异抹平了。

提示:如果你只是偶尔用一下 Claude Code,没有多模型切换需求,那openrig可能有点重。但只要你开始同时维护两套以上的 AI 编码配置,它省下的时间会非常可观。

2. 核心设计思路拆解:为什么是 YAML + Node.js 这套组合

2.1 为什么选 YAML 而不是 JSON 或 TOML

openrig把配置层放在 YAML 上,这个选择很值得聊。JSON 的问题是不能写注释,你没法在配置里标注“这行是给 DeepSeek 用的,别删”。TOML 虽然支持注释,但嵌套结构一深,写起来就变得很啰嗦,尤其是当你要描述多个模型、多个 endpoint、多个工具链版本的时候,TOML 的[section.subsection.subsubsection]会让人眼花。

YAML 的优势在于层级直观、支持注释、支持锚点和引用。举个例子,你有三个模型配置,它们共享同一个 API base URL,只是模型名不同。用 YAML 的锚点可以这样写:

defaults: &defaults api_base: "http://localhost:1234/v1" timeout: 30 max_retries: 3 models: local_qwen: <<: *defaults model_name: "qwen2.5-coder-7b" local_deepseek: <<: *defaults model_name: "deepseek-coder-v2"

这种复用能力在 JSON 里要靠工具生成,在 TOML 里要靠重复写。YAML 原生支持,改一处就全改。openrig正是利用了这个特性,把公共配置抽出来,让每个模型的差异化配置尽量短。

但 YAML 也有坑,最大的坑就是缩进敏感。我见过太多人因为 tab 和空格混用导致解析失败,报错信息还特别模糊,只告诉你“mapping values are not allowed here”,根本不告诉你哪一行出了问题。openrig在加载 YAML 的时候做了一层校验,会尽量给出更友好的错误提示,但你自己写的时候还是得注意:统一用两个空格缩进,绝对不要用 tab。

2.2 Node.js 在这里扮演什么角色

很多人看到 Node.js 就头大,觉得“我只是想用个 AI 编码工具,为什么还要装 Node.js”。这个问题在 Claude Code 和 Codex 的安装教程里被问烂了。答案很简单:这两个工具本身就是用 Node.js 写的,它们的 CLI 入口是 JavaScript 文件,靠 Node 运行时执行。

openrig依赖 Node.js 还有一层原因:它需要动态生成配置文件。Claude Code 读的是 JSON,Codex 读的是 TOML,而openrig的源配置是 YAML。中间需要一个转换层,Node.js 的js-yaml和toml包正好干这个事。你改 YAML,openrig在启动时把它转成对应工具认识的格式,写到正确的位置,然后拉起进程。

Node.js 版本的选择也有讲究。Claude Code 官方要求 Node 18 以上,Codex 要求 Node 20 以上。如果你系统里只有一个 Node 16,两个都跑不起来。openrig的做法是在项目级别锁定 Node 版本,通过.nvmrc或者package.json的engines字段声明,配合 nvm 或者 fnm 自动切换。这样你全局 Node 版本再乱,进到openrig目录里自动切到正确版本。

注意:如果你在 Windows 上用 nvm-windows,它和 Unix 上的 nvm 行为不完全一样,.nvmrc不会自动生效,需要手动nvm use。这是很多人踩过的坑。

2.3 编排层与执行层的分离

openrig的架构可以分成两层:编排层和执行层。编排层负责读 YAML、解析配置、生成目标工具的配置文件、设置环境变量。执行层就是 Claude Code 或 Codex 本身的进程。

这种分离的好处是编排层可以独立测试。你可以先跑openrig dry-run,看看它生成的配置文件长什么样,确认无误再真正启动工具。我强烈建议第一次配置的时候一定要用 dry-run,因为 Claude Code 和 Codex 的配置格式差异很大,直接启动如果配错了,报错信息往往指向不明。

另一个好处是切换成本极低。你想从 Claude Code 切到 Codex,不需要重新配置任何东西,只需要在 YAML 里改一个active_tool字段,或者用命令行参数指定。openrig会重新生成对应工具的配置,然后启动。整个过程你不需要碰任何工具原生的配置文件。

3. 核心细节解析:YAML 配置文件的完整结构与参数含义

3.1 顶层结构设计

一个典型的openrigYAML 配置文件长这样:

version: "1.0" runtime: node_version: "20.11.0" package_manager: "pnpm" tools: claude_code: enabled: true config_path: "~/.claude/settings.json" env: ANTHROPIC_BASE_URL: "${models.active.api_base}" ANTHROPIC_API_KEY: "${secrets.anthropic_key}" codex: enabled: true config_path: "~/.codex/config.toml" env: OPENAI_BASE_URL: "${models.active.api_base}" OPENAI_API_KEY: "${secrets.openai_key}" models: active: "local_qwen" local_qwen: api_base: "http://localhost:1234/v1" model_name: "qwen2.5-coder-7b" timeout: 60 max_retries: 3 remote_deepseek: api_base: "https://api.deepseek.com/v1" model_name: "deepseek-coder" timeout: 120 max_retries: 2 secrets: anthropic_key: "${env:ANTHROPIC_API_KEY}" openai_key: "${env:OPENAI_API_KEY}"

这个结构里,runtime管 Node 版本和包管理器,tools管每个 AI 编码工具的配置路径和环境变量,models管模型连接信息,secrets管密钥引用。关键设计是models.active这个字段,它指向当前激活的模型配置,其他所有引用都通过${models.active.xxx}动态解析。

这种设计的精妙之处在于:切换模型只需要改一行。你把active从local_qwen改成remote_deepseek,所有工具的 endpoint 和模型名自动跟着变。不需要去 Claude Code 的配置文件里改一遍,再去 Codex 的配置文件里改一遍。

3.2 环境变量插值的实现细节

${}这种插值语法看起来简单,实现起来有几个坑。首先是解析顺序:openrig需要先解析secrets,因为tools里引用了secrets;然后解析models,因为tools也引用了models;最后解析tools。如果顺序错了,就会遇到“变量未定义”的错误。

其次是循环引用检测。如果有人写了a: ${b}和b: ${a},解析器会陷入死循环。openrig在解析时会维护一个已解析变量的集合,遇到重复就报错。这个细节在文档里通常不会写,但你如果自己改配置改出循环引用了,报错信息会告诉你哪个变量形成了环。

第三个坑是环境变量与配置文件变量的优先级。${env:ANTHROPIC_API_KEY}表示从系统环境变量读取,${secrets.anthropic_key}表示从配置文件的secrets段读取。如果两者同时存在,openrig的默认行为是配置文件优先,但可以通过--env-override参数反转。这个设计是为了让 CI/CD 环境可以用环境变量覆盖本地配置,而不需要改文件。

提示:密钥千万不要直接写在 YAML 里。用${env:XXX}引用系统环境变量,或者用.env文件配合dotenv加载。YAML 文件如果提交到 git,密钥就泄露了。

3.3 工具配置路径的跨平台处理

Claude Code 在 macOS/Linux 上的配置路径是~/.claude/settings.json,在 Windows 上是%USERPROFILE%\.claude\settings.json。Codex 类似,但目录名是.codex。openrig需要处理这些差异,否则你在 Windows 上写的配置拿到 Linux 上就跑不了。

处理方式是用~表示用户主目录,由openrig在运行时展开。Node.js 的os.homedir()在三个平台上都能正确返回用户主目录。路径分隔符统一用/,Node.js 的path模块会自动处理 Windows 的反斜杠转换。

但有一个例外:如果配置路径里包含空格,比如 Windows 用户名是 “John Doe”,那C:\Users\John Doe\.claude\这个路径在传给某些命令行工具时会被截断。openrig在生成配置和启动进程时会对路径做引号包裹,但如果你自己写脚本调用,记得手动加引号。

4. 实操过程:从零搭建 openrig 环境的完整步骤

4.1 环境准备与 Node.js 安装

第一步永远是 Node.js。我推荐用fnm而不是 nvm,因为 fnm 是 Rust 写的,启动速度快很多,而且 Windows 支持更好。安装 fnm 之后,装 Node 20 LTS:

# macOS/Linux 安装 fnm curl -fsSL https://fnm.vercel.app/install | bash # 安装 Node 20 fnm install 20 fnm use 20 node -v # 应该输出 v20.x.x

Windows 用户可以用 winget 或者 scoop:

winget install Schniz.fnm fnm install 20 fnm use 20

装完 Node 之后,确认 npm 也能用。openrig本身可以通过 npm 全局安装,也可以 clone 仓库本地运行。我建议本地运行,因为你需要改 YAML 配置,全局安装的话配置文件位置不好找。

git clone https://github.com/your-org/openrig.git cd openrig npm install

npm install会装几个关键依赖:js-yaml解析 YAML,toml生成 Codex 配置,dotenv加载.env文件,commander处理命令行参数。装完之后跑npm link,就可以在任意目录用openrig命令了。

注意:如果你在安装 Node.js 时遇到 “error installing 24.21.0: node.js v24.21.0 is not yet released” 这种报错,说明你指定的版本号不存在。Node.js 的版本号是偶数开头为 LTS,奇数开头为 Current。24 还没发布,用 20 或者 22。

4.2 YAML 配置文件的编写与校验

环境准备好之后,复制示例配置:

cp openrig.example.yaml openrig.yaml

然后编辑openrig.yaml。第一次配置建议只启用一个工具、一个模型,跑通之后再扩展。比如先只配 Claude Code + 本地 LM Studio:

version: "1.0" runtime: node_version: "20.11.0" tools: claude_code: enabled: true config_path: "~/.claude/settings.json" env: ANTHROPIC_BASE_URL: "http://localhost:1234/v1" ANTHROPIC_API_KEY: "lm-studio" models: active: "local" local: api_base: "http://localhost:1234/v1" model_name: "qwen2.5-coder-7b" timeout: 60

这里ANTHROPIC_API_KEY填lm-studio是因为 LM Studio 不校验密钥,但 Claude Code 要求这个环境变量必须存在,随便填一个非空值就行。

写完配置后,一定要先校验:

openrig validate

这个命令会做几件事:检查 YAML 语法是否正确,检查必填字段是否缺失,检查引用的变量是否存在,检查配置路径是否可写。如果一切正常,输出 “Configuration valid”。如果有问题,会指出具体哪一行哪个字段。

我踩过的一个坑是:YAML 里用了 tab 缩进,validate报错说 “found character '\t' that cannot start any token”。这个报错还算友好,但如果你用的是某些编辑器自动把 tab 转成空格,可能看不出来。建议在编辑器里开启“显示空白字符”,确保缩进全是空格。

4.3 启动 Claude Code 并验证连接

校验通过后,启动:

openrig start claude_code

openrig会做以下动作:读取 YAML,解析变量,生成~/.claude/settings.json,设置环境变量,然后 exec Claude Code 的入口脚本。你会看到 Claude Code 的交互界面出现。

验证是否连上了本地模型,最简单的方法是问一个只有本地模型才知道的问题,比如“你是什么模型”。如果返回的是 Qwen 或者 DeepSeek 的标识,说明连接成功。如果返回的是 Claude 的标识,说明配置没生效,Claude Code 还在走默认的云端 endpoint。

另一个验证方法是看 LM Studio 的日志。LM Studio 在收到请求时会打印日志,如果 Claude Code 的请求打到了 LM Studio,日志里会有记录。如果日志是空的,说明请求根本没发到本地。

提示:Claude Code 有时候会缓存配置,改了settings.json之后需要重启才生效。openrig在启动前会强制覆盖配置文件,但如果你手动改了配置又没通过openrig启动,可能会遇到缓存问题。

4.4 切换到 Codex 并接入 DeepSeek

Claude Code 跑通之后,加 Codex 就简单了。在 YAML 里加一段:

tools: codex: enabled: true config_path: "~/.codex/config.toml" env: OPENAI_BASE_URL: "${models.active.api_base}" OPENAI_API_KEY: "${secrets.deepseek_key}" secrets: deepseek_key: "${env:DEEPSEEK_API_KEY}"

然后在系统里设置DEEPSEEK_API_KEY环境变量。启动 Codex:

openrig start codex

openrig会生成~/.codex/config.toml,内容大致是:

[model] provider = "openai" name = "deepseek-coder" [provider.openai] base_url = "https://api.deepseek.com/v1" api_key = "sk-xxxxx"

Codex 的配置格式和 Claude Code 完全不同,但openrig帮你屏蔽了这些差异。你只需要在 YAML 里描述“我要用什么模型、endpoint 是什么”,剩下的转换由openrig处理。

5. 常见问题与排查技巧实录

5.1 连接失败类问题速查

现象可能原因排查方法
Claude Code 启动后无响应endpoint 地址错误用curl手动请求 endpoint 看是否通
报错 “organization has disabled claude subscription access”走了云端认证而非本地检查ANTHROPIC_BASE_URL是否被覆盖
Codex 报 “model is not supported”模型名拼写错误对照 LM Studio 或 API 提供商的模型列表
请求超时timeout 设置太短本地模型首次加载慢,调到 120 秒以上
401 错误API key 无效检查环境变量是否设置,echo $DEEPSEEK_API_KEY

这个表里最常遇到的是第一行和第三行。Claude Code 无响应很多时候不是配置问题,而是 LM Studio 的模型还没加载完。LM Studio 加载一个 7B 模型大概需要 10-30 秒,如果 Claude Code 在这期间发请求,就会超时。解决办法是先在 LM Studio 里手动加载模型,确认能对话了,再启动 Claude Code。

5.2 YAML 解析错误的典型场景

YAML 报错信息有时候很让人抓狂。我整理了几个最常见的:

场景一:冒号后面没空格。api_base:http://localhost会报错,必须是api_base: http://localhost。冒号后面必须有一个空格,这是 YAML 的语法要求。

场景二:字符串里有特殊字符没加引号。比如model_name: qwen:2.5会报错,因为冒号被解析成键值分隔符。必须写成model_name: "qwen:2.5"。

场景三:多行字符串缩进不对。如果你用|写多行字符串,后续行的缩进必须比|所在行多至少一个空格。少一个空格就会解析失败。

场景四:布尔值歧义。YAML 里yes、no、on、off都会被解析成布尔值。如果你想把它们当字符串用,必须加引号。比如model_name: "no"而不是model_name: no。

提示:写完 YAML 之后,可以用在线的 YAML 校验工具先过一遍,比直接跑openrig validate更快定位语法错误。

5.3 Node.js 版本冲突的处理

如果你系统里已经有一个 Node 版本,openrig又要求另一个版本,可能会冲突。表现是openrig start时报错 “The engine node is incompatible with this module”。

解决办法是用 fnm 或 nvm 切换到正确版本。openrig在启动时会检查runtime.node_version和当前node -v是否匹配,不匹配会给出明确提示。如果你用 fnm,可以在项目目录放一个.node-version文件,内容就是版本号,fnm 进入目录时自动切换。

另一个坑是全局安装的 npm 包和当前 Node 版本不匹配。比如你用 Node 18 全局装了openrig,然后切到 Node 20,openrig可能跑不起来。解决办法是不要全局安装,用npx或者本地npm link。

5.4 代理与网络问题的排查

有些第三方 API 在国内访问不稳定,需要走代理。openrig支持在 YAML 里配置代理:

network: proxy: http: "http://127.0.0.1:7890" https: "http://127.0.0.1:7890" no_proxy: "localhost,127.0.0.1"

no_proxy很重要,因为本地 LM Studio 的请求不应该走代理。如果本地请求走了代理,会出现“连接被拒绝”或者“超时”的错误。openrig在设置环境变量时会同时设置HTTP_PROXY、HTTPS_PROXY和NO_PROXY,确保本地请求直连。

排查代理问题时,可以用curl -v看请求到底走了哪条路。如果curl直连能通但openrig启动的工具不通,大概率是代理环境变量没设置对。

6. 进阶玩法:多环境配置与团队协作

6.1 用 profile 管理多套配置

openrig支持 profile 机制,你可以在一个 YAML 文件里定义多套配置,用--profile参数切换:

profiles: local: models: active: "local_qwen" remote: models: active: "remote_deepseek" team: models: active: "team_gateway"

启动时指定 profile:

openrig start claude_code --profile remote

这个功能在同一台机器上服务多个项目时特别有用。比如 A 项目要求用本地模型保证代码不出内网,B 项目可以用云端模型追求效果。你不需要维护两份 YAML,只需要在同一个文件里定义两个 profile。

6.2 团队共享配置的注意事项

团队协作场景下,YAML 文件应该提交到 git,但密钥绝对不能提交。做法是把密钥部分抽到.env文件,.env加入.gitignore,然后提供一个.env.example作为模板:

# .env.example ANTHROPIC_API_KEY=your_key_here DEEPSEEK_API_KEY=your_key_here

新同事 clone 之后,复制.env.example为.env,填入自己的密钥,然后openrig validate确认配置完整。这样既保证了配置的一致性,又避免了密钥泄露。

另一个团队协作的坑是配置路径的差异。macOS 和 Linux 的路径基本一致,但 Windows 的路径分隔符和主目录位置不同。openrig用~和/统一处理,但如果你在 YAML 里写了绝对路径,比如/Users/john/.claude/,那在别人的机器上就跑不了。永远用~开头,不要写绝对路径。

6.3 与 VS Code 的集成

Claude Code 和 Codex 都有 VS Code 扩展,openrig生成的配置对扩展同样生效,因为扩展底层调用的还是同一个 CLI。但有一个细节:VS Code 扩展可能不会读取你 shell 里的环境变量,它有自己的环境变量加载机制。

解决办法是在 VS Code 的settings.json里显式指定:

{ "claude-code.environment": { "ANTHROPIC_BASE_URL": "http://localhost:1234/v1", "ANTHROPIC_API_KEY": "lm-studio" } }

或者用openrig生成一个 VS Code 的 workspace 配置,把环境变量写进去。openrig有一个--vscode参数,会在当前目录生成.vscode/settings.json,包含所有必要的环境变量。

提示:VS Code 扩展和 CLI 的配置有时候会打架。如果你在 CLI 里跑通了但扩展不行,先检查扩展的设置里有没有覆盖环境变量。

7. 我踩过的坑与实操心得

第一个坑是YAML 锚点引用在跨文件时失效。openrig支持!include语法引入其他 YAML 文件,但锚点不能跨文件引用。如果你在models.yaml里定义了锚点,在tools.yaml里用*anchor引用,会报错。解决办法是把锚点定义和引用放在同一个文件里,或者用openrig的变量插值代替锚点。

第二个坑是Claude Code 的配置缓存。Claude Code 启动后会把配置读进内存,如果你在运行期间改了settings.json,不重启不会生效。openrig在每次start时都会重新生成配置,但如果你手动改了配置又没通过openrig启动,就会遇到“改了没效果”的情况。我的习惯是永远通过openrig启动,不直接跑claude命令。

第三个坑是本地模型的上下文长度限制。Claude Code 默认假设模型有 200K 上下文,但本地跑的 7B 模型通常只有 8K 或 32K。当对话变长时,Claude Code 会把整个历史发给模型,超出上下文限制就会报错。解决办法是在 YAML 里设置max_context_tokens,openrig会把这个值传给 Claude Code,让它提前截断历史。

models: local_qwen: api_base: "http://localhost:1234/v1" model_name: "qwen2.5-coder-7b" max_context_tokens: 8192

这个参数在官方文档里不太显眼,但没有它,长对话基本没法用。

第四个坑是Codex 的 TOML 配置里数组和表的区别。Codex 的某些配置项要求是数组,比如[model.providers]下面可以定义多个 provider。如果你写成了表而不是数组,Codex 会静默忽略,不报错但也不生效。openrig在生成 TOML 时会根据 schema 校验类型,但如果你手动改生成的 TOML,就容易踩这个坑。

最后分享一个提高效率的小技巧:用openrig env命令导出当前环境变量。这个命令会打印出所有openrig设置的环境变量,你可以source它,然后在当前 shell 里直接跑claude或codex,不需要每次都通过openrig start。这在调试的时候特别方便,因为你可以看到工具实际拿到的环境变量是什么。

eval $(openrig env --profile local) claude # 直接跑,环境变量已经设置好了

这个用法在排查“为什么 openrig 能跑但直接跑不行”这类问题时非常有用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询