1. 从 openrig 说起:一个把 Claude Code 和 Codex 装进统一工作流的开源脚手架
第一次看到openrig这个名字,我下意识把它拆成了 "open" + "rig"——在工程语境里,rig 指的是把一堆零散部件搭成一套能稳定运转的装置。放到 AI 编程助手这个场景里,这个命名其实非常贴切:它要解决的就是把 Claude Code、Codex 这类命令行 AI 编程工具,和 YAML 配置、npm 生态、本地模型服务这几样东西,组装成一套可复用、可迁移、可版本管理的开发环境。
如果你最近在折腾 Claude Code 或者 Codex,大概率踩过下面这些坑:npm 全局包装完了,PowerShell 里一跑就报"无法加载文件 npm.ps1,因为在此系统上禁止运行脚本";Claude Code 装好了,但不知道怎么让它调用 LM Studio 里的本地模型;Codex 登录之后提示组织设置加载失败,或者切到某个 endpoint 就报cc switch local proxy failed while handling codex endpoint /responses;想给项目加一份 YAML 配置,结果 YOLOv10 的 yaml 和 RStudio 的 yaml 搜出来一堆,根本对不上号。
openrig这类脚手架的价值,就在于把这些散落在各个教程、CSDN 博客、issue 区里的碎片经验,收敛成一套结构化的配置。它不是一个官方产品,更像是一个"约定俗成的工程实践集合"——用 YAML 描述你的工具链,用 npm 管理依赖和脚本入口,用统一的目录结构把 Claude Code、Codex、本地模型服务的配置各归各位。这篇文章我会从设计思路、核心配置、实操落地、问题排查四个层面,把 openrig 这套东西讲透,适合已经装过 Claude Code 或 Codex、但被环境问题反复折磨的中级用户,也适合想一次性把环境搭干净的新手。
2. openrig 的整体设计思路与方案选型
2.1 为什么是 YAML + npm 这套组合
先说结论:openrig 选择 YAML 作为配置载体、npm 作为分发和脚本入口,不是随便挑的,而是被 Claude Code 和 Codex 这两个工具本身的生态倒逼出来的。
Claude Code 和 Codex 都是命令行优先的工具,它们的配置天然倾向于"文件即配置"。JSON 写起来太啰嗦,不允许注释,改一个参数要小心翼翼数括号;TOML 虽然友好,但在前端和 Node 生态里普及度不如 YAML;YAML 缩进敏感、支持注释、支持锚点和引用,非常适合描述"多环境、多模型、多工具"这种嵌套结构。你在 openrig 里看到的models.yaml、tools.yaml、profiles.yaml,本质上是把"我要用哪个模型、走哪个 endpoint、用哪个工具链"这件事声明式地写下来。
npm 的角色则更微妙。很多人以为 npm 只是装包用的,但在 openrig 里它承担了三件事:第一,作为依赖分发渠道,把 Claude Code、Codex 的 CLI 包装进devDependencies或全局;第二,作为脚本入口,用npm run统一封装启动命令,避免每个人记一长串参数;第三,作为版本锁,package-lock.json保证团队里每个人装到的 CLI 版本一致。我见过太多团队因为 A 装了 Claude Code 0.2.x、B 装了 0.3.x,导致同一个 prompt 行为不一致,排查半天才发现是版本问题。
提示:openrig 不是某个具体的 npm 包名,而是一类"用 npm + YAML 组织 AI 编程工具链"的实践模式。你在 GitHub 上搜到的同名仓库,大概率是个人或小团队维护的模板,使用前务必读一遍它的
package.json和脚本,确认没有可疑的 postinstall 行为。
2.2 目录结构怎么划分才不混乱
一套能长期维护的 openrig 结构,核心原则是"配置与密钥分离、工具与模型分离、个人与团队分离"。我实际用下来比较顺手的一种划分是这样的:
openrig/ ├── config/ │ ├── models.yaml # 模型定义:本地 LM Studio、远端 API 等 │ ├── tools.yaml # 工具定义:claude-code、codex 的启动参数 │ └── profiles.yaml # 环境组合:dev / staging / personal ├── scripts/ │ ├── bootstrap.mjs # 环境自检与初始化 │ └── switch.mjs # 切换 profile ├── .env.local # 密钥,绝不入库 ├── .env.example # 密钥模板,入库 ├── package.json └── README.md这个结构的关键在于profiles.yaml。它把"模型 + 工具 + 参数"打包成一个命名组合,比如local-dev指向 LM Studio 的本地模型,cloud-prod指向远端服务。切换环境只需要改一个 profile 名,而不是满世界找配置。这一点在 Claude Code 调用本地模型时尤其重要——你不可能每次都手动敲 endpoint 和模型名。
2.3 和直接手写配置相比,openrig 到底省了什么
有人会问:我直接改 Claude Code 的配置文件不就行了,为什么要套一层 openrig?我的实测体会是,单工具、单模型、单人开发时,直接改配置确实更快。但只要满足下面任意一条,openrig 的收益就立刻显现:
- 你同时用 Claude Code 和 Codex,两者的配置格式和路径不一样;
- 你在本地模型和远端模型之间来回切;
- 团队里超过两个人,需要保证环境一致;
- 你需要把配置纳入 Git 管理,但又不能把密钥提交上去。
这四条里,第三条和第四条是硬需求。我踩过的坑是:早期把 API key 直接写进models.yaml提交了,虽然事后删了 commit,但 key 已经泄露,只能作废重发。openrig 用.env.local+.env.example的模式,从结构上就杜绝了这个问题。
3. 核心配置细节与实操要点拆解
3.1 models.yaml:把本地模型和远端模型统一描述
models.yaml是 openrig 的心脏。它的核心任务是回答一个问题:当我调用某个模型名时,请求应该发到哪里、用什么协议、带什么参数。下面是我实际在用的一个精简版本:
version: 1 models: local-qwen: provider: openai-compatible base_url: http://127.0.0.1:1234/v1 model: qwen2.5-coder-7b-instruct context_window: 32768 max_tokens: 4096 temperature: 0.2 remote-sonnet: provider: anthropic base_url: https://api.anthropic.com model: claude-sonnet-4-5 context_window: 200000 max_tokens: 8192 temperature: 0.3这里有几个细节值得展开。第一,provider字段决定了用哪套 SDK 去发请求。openai-compatible是个万能协议,LM Studio、Ollama、vLLM 都支持,所以本地模型统一走这个。第二,context_window不是随便填的,它直接影响 Claude Code 什么时候触发上下文压缩。填大了会导致请求超限报错,填小了会让模型过早丢弃历史。我一般按模型实际能力打八折填,留出安全余量。
第三,base_url里的127.0.0.1而不是localhost,这是个经验之谈。在某些 Node 版本和系统配置下,localhost会优先解析到 IPv6 的::1,而 LM Studio 默认只监听 IPv4,结果就是连接被拒。改成127.0.0.1能绕开这个坑,我至少帮三个人解决过这个"明明服务开着却连不上"的问题。
注意:
max_tokens和context_window是两个概念。前者是单次回复的上限,后者是输入加输出的总窗口。很多人把max_tokens填成和context_window一样大,结果一请求就报超限,因为输入已经占了一部分。
3.2 tools.yaml:Claude Code 与 Codex 的启动参数收敛
tools.yaml负责描述每个 CLI 工具怎么启动。Claude Code 和 Codex 的参数体系不一样,把它们抽象成统一结构,是 openrig 最实用的部分之一:
tools: claude-code: bin: claude env: ANTHROPIC_BASE_URL: "${MODEL_BASE_URL}" ANTHROPIC_API_KEY: "${MODEL_API_KEY}" args: - "--model" - "${MODEL_NAME}" codex: bin: codex env: OPENAI_BASE_URL: "${MODEL_BASE_URL}" OPENAI_API_KEY: "${MODEL_API_KEY}" args: - "--model" - "${MODEL_NAME}"${...}是环境变量占位符,运行时由scripts/switch.mjs替换。这样做的最大好处是:密钥永远不落在 YAML 文件里,YAML 可以放心提交。Claude Code 认ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,Codex 认OPENAI_BASE_URL和OPENAI_API_KEY,虽然变量名不同,但指向的是同一个模型服务——这就是为什么 openrig 能用一套models.yaml同时喂饱两个工具。
这里有个容易忽略的点:Claude Code 走的是 Anthropic 的消息协议,而 LM Studio 这类本地服务通常只提供 OpenAI 兼容协议。如果你直接把 Claude Code 指向 LM Studio,大概率会失败。解决办法是在中间加一层协议转换,或者干脆用支持 Anthropic 协议的本地服务。我在实测中发现,最省事的做法是让 Claude Code 走远端,Codex 走本地,各取所长,而不是强行让两个工具都指向同一个 endpoint。
3.3 profiles.yaml:一键切换开发环境
profiles.yaml把模型和工具组合起来,形成可切换的环境:
profiles: local-dev: model: local-qwen tools: [codex] cloud-dev: model: remote-sonnet tools: [claude-code, codex] offline: model: local-qwen tools: [codex] args_override: codex: ["--sandbox", "read-only"]args_override是个很实用的设计。比如offline环境里,我希望 Codex 只读不写,避免在没网、没法回滚的情况下误改代码。这种细粒度的控制,如果每次都手敲参数,迟早会忘。写进 profile 里,npm run switch offline一条命令搞定。
3.4 环境变量与密钥管理
.env.example入库,.env.local进.gitignore,这是铁律。.env.example里只放键名和占位值:
MODEL_BASE_URL=http://127.0.0.1:1234/v1 MODEL_API_KEY=sk-replace-me MODEL_NAME=qwen2.5-coder-7b-instruct新人 clone 下来,cp .env.example .env.local,填上自己的值就能跑。我见过有团队把.env.local也提交了,理由是"方便协作",结果密钥泄露,只能全员轮换。这种便宜千万别占。
4. 从零搭建 openrig 的完整实操流程
4.1 环境自检:先确认 Node 和 npm 是干净的
在动手之前,先跑一遍自检。这一步能帮你提前发现 80% 的后续问题:
node -v npm -v npm config get registrynode -v建议在 18 以上,Claude Code 和 Codex 对 Node 版本都有要求,太低会报各种奇怪的语法错误。npm config get registry如果返回的是官方源,在国内环境下装包会很慢,建议换成国内镜像:
npm config set registry https://registry.npmmirror.com换完之后再npm config get registry确认一下。这里要提醒一句:镜像源只影响下载速度,不影响包的内容,但极少数包在镜像上同步有延迟,如果遇到"版本对不上"的情况,临时切回官方源试试。
4.2 解决 PowerShell 禁止运行脚本的问题
这是 Windows 用户最高频的拦路虎。报错长这样:
npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本根因是 PowerShell 的执行策略默认是Restricted,不允许运行.ps1脚本。解决办法是改执行策略,但要注意作用域:
Get-ExecutionPolicy -List Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned用-Scope CurrentUser而不是全局,避免影响系统其他用户,也不需要管理员权限。RemoteSigned的含义是:本地脚本可以跑,从网上下载的脚本需要签名。这比Unrestricted安全,比Restricted实用。改完重开一个 PowerShell 窗口,npm -v应该就正常了。
提示:如果你在公司的受管电脑上,执行策略可能被组策略锁死,
Set-ExecutionPolicy会报"被覆盖"。这种情况下改用 CMD 或者 Git Bash 跑 npm 命令,绕开 PowerShell 即可,不要去动组策略。
4.3 安装 Claude Code 与 Codex
安装本身不复杂,关键是装在哪、怎么装:
npm install -g @anthropic-ai/claude-code npm install -g @openai/codex全局安装的好处是任何目录都能调用,坏处是版本管理麻烦。如果你同时维护多个项目、需要不同版本,建议改成项目内安装:
npm install -D @anthropic-ai/claude-code @openai/codex然后用npx claude和npx codex调用。openrig 的package.json里通常会把这两个放进devDependencies,配合scripts字段:
{ "scripts": { "claude": "claude", "codex": "codex", "switch": "node scripts/switch.mjs" } }这样npm run claude就等于claude,团队里每个人跑的命令完全一致。
4.4 接入本地模型:以 LM Studio 为例
本地模型的价值在于隐私和零成本。LM Studio 装好后,在它的开发者面板里启动本地服务,默认端口 1234。然后验证服务是否可达:
curl http://127.0.0.1:1234/v1/models能返回模型列表,说明服务正常。接着把models.yaml里的local-qwen指向它,运行npm run switch local-dev,再启动 Codex。如果 Codex 报model is not supported,多半是模型名写错了——LM Studio 里的模型名要和models.yaml里的model字段完全一致,包括大小写和后缀。
我实测下来,7B 级别的代码模型在补全和简单重构上够用,但涉及跨文件推理就容易力不从心。所以我的策略是:日常补全用本地,复杂任务切远端。openrig 的 profile 机制让这个切换成本降到一条命令。
4.5 验证整条链路是否打通
搭完之后别急着写代码,先做一次端到端验证。我的验证清单是这样的:
| 检查项 | 命令 | 预期结果 |
|---|---|---|
| Node 版本 | node -v | v18 以上 |
| npm 源 | npm config get registry | 返回配置的源 |
| 本地模型服务 | curl http://127.0.0.1:1234/v1/models | 返回模型列表 |
| Claude Code | claude --version | 返回版本号 |
| Codex | codex --version | 返回版本号 |
| profile 切换 | npm run switch local-dev | 无报错,环境变量生效 |
六项全过,基本可以放心用。任何一项失败,回到对应章节排查。
5. 常见问题与排查技巧实录
5.1 Codex endpoint 报错怎么定位
cc switch local proxy failed while handling codex endpoint /responses这个报错,字面意思是本地代理在处理 Codex 的/responses请求时失败了。根因通常有三个:一是本地模型服务没起来,代理转发时连接被拒;二是模型名不匹配,服务端返回 404;三是协议不兼容,Codex 期望的请求格式本地服务不认。
排查顺序我建议从外到内:先curl直接打本地服务的/v1/models,确认服务活着;再curl打一次/v1/chat/completions,确认能正常对话;最后才怀疑代理层。很多人一上来就改代理配置,结果折腾半天发现是 LM Studio 没启动。
5.2 npm 相关的高频故障速查
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
npm.ps1 禁止运行脚本 | PowerShell 执行策略 | Set-ExecutionPolicy -Scope CurrentUser RemoteSigned |
ERESOLVE overriding peer dependency | 依赖版本冲突 | 加--legacy-peer-deps或统一版本 |
| 装包极慢或超时 | 默认源在国外 | 换国内镜像源 |
| 全局包找不到命令 | PATH 未配置 | 检查 npm 全局 bin 目录是否在 PATH |
| 卸载不干净 | 残留缓存 | npm uninstall -g后清npm cache |
ERESOLVE这个警告特别常见,尤其是 Claude Code 和 Codex 依赖的某些库版本不一致时。--legacy-peer-deps能绕过,但只是权宜之计。更稳妥的做法是在package.json里用overrides字段强制统一版本,从根上解决。
5.3 组织设置加载失败与登录问题
Codex 报无法加载组织设置或者 Claude Code 提示订阅访问被禁用,这类问题八成和账号状态、网络环境有关,而不是本地配置。我的处理原则是:先确认账号本身能正常登录官方网页端,如果网页端都不行,那本地怎么改都没用;如果网页端正常,再检查本地是不是有代理配置残留,把HTTP_PROXY、HTTPS_PROXY这类环境变量清掉再试。
5.4 我踩过的三个真实坑
第一个坑:把context_window填成模型的理论最大值。结果长对话一上来就报超限,因为实际可用窗口要扣掉系统提示词和工具定义占用的部分。后来我统一按理论值的 80% 填,再没出过问题。
第二个坑:在.env.local里用了带空格的值,比如MODEL_NAME=qwen 2.5,结果解析时被截断。YAML 和 shell 对空格都敏感,值里带空格要么加引号,要么干脆别用空格。
第三个坑:profile 切换后没重启 CLI。环境变量是在进程启动时读取的,切换 profile 只改了文件,已经跑着的 Claude Code 或 Codex 不会自动感知。养成"切完 profile 重开终端"的习惯,能省下大量"为什么配置没生效"的困惑。
6. 把 openrig 用成习惯之后的几点体会
搭好这套东西之后,我最大的感受是:AI 编程工具的瓶颈往往不在模型本身,而在环境的一致性。同一个模型,配置对了如虎添翼,配置错了寸步难行。openrig 这类脚手架的意义,就是把"配置正确"这件事从依赖个人记忆,变成依赖版本化的文件。
我现在的工作流是这样的:早上到工位,npm run switch cloud-dev处理需要强推理的任务;下午网络不稳或者要处理敏感代码,切到local-dev用本地模型;晚上跑批处理,用offlineprofile 限制成只读。整个过程不需要记任何 endpoint 和密钥,全在 YAML 里。
如果你刚开始搭,我的建议是别追求一步到位。先把models.yaml和.env.local跑通,能用一个模型启动一个工具,再逐步加 profile、加工具、加 override。配置这东西,能跑通的最小版本永远比设计完美的空架子有价值。等你用顺了,自然会知道哪些字段该抽出来、哪些该合并——那时候你的 openrig 才真正长成了适合你自己的样子。