1. openrig 到底想解决什么问题
第一次看到 openrig 这个名字,多数人脑子里蹦出来的画面大概是某种硬件支架或者机械臂的配件。但把 Claude Code、Codex、YAML、tmux 这几个词摆在一起,方向就清楚了——这是一个围绕 AI 编程助手做多工具编排与配置管理的开源项目。说白了,它要处理的是这样一个现实困境:你手头同时装着 Claude Code 和 Codex 两套命令行助手,各自有独立的配置文件、独立的会话管理、独立的启动参数,切换一次要改一堆东西,时间全耗在环境折腾上,而不是写代码。
openrig 的核心价值在于把"工具链的装配"这件事标准化。它用 YAML 作为唯一的配置入口,把 Claude Code 和 Codex 的启动参数、模型端点、工作目录、会话策略全部收拢到一份声明式文件里,再借助 tmux 做进程编排和会话保持。你改一次配置,两个工具的行为同步生效;你开一个 tmux 会话,多个助手可以并行跑在同一个终端窗口的不同 pane 里,互不干扰。
这套东西适合谁?三类人最需要。第一类是同时使用多个 AI 编程助手的开发者,尤其是那些在 Claude Code 和 Codex 之间反复横跳的人。第二类是需要把助手行为固化下来的团队,比如统一模型端点、统一超时策略、统一日志路径,靠口头约定不靠谱,得靠配置文件。第三类是喜欢在终端里完成一切的重度用户,tmux 对他们来说是肌肉记忆,openrig 正好顺着这个习惯做编排。
我自己的使用场景比较典型:白天用 Claude Code 处理重构和代码审查,晚上用 Codex 跑批量生成和测试补全,两套工具的配置项加起来几十个,手动维护迟早出错。openrig 出现之后,我把所有参数写进一份 YAML,启动脚本从三行变成一行,切换成本几乎归零。下面就把这套东西从设计思路到落地细节完整拆一遍。
2. 整体设计思路与方案选型拆解
2.1 为什么是 YAML 而不是 JSON 或 TOML
配置格式的选择看着是小事,实际决定了这个项目好不好用。openrig 选 YAML,理由很实在。JSON 不支持注释,而 AI 助手的配置里有大量需要说明的地方,比如某个端点为什么指向本地服务、某个超时值为什么设成 120 秒,这些上下文不写下来,三个月后自己都看不懂。TOML 虽然支持注释,但嵌套结构表达起来啰嗦,尤其是当你要描述"多个助手、每个助手多个模型、每个模型多个参数"这种三层结构时,TOML 的方括号会堆得满屏都是。
YAML 的缩进式结构天然适合表达层级关系,而且支持锚点和引用,这一点在 openrig 里特别关键。比如你定义了一组通用的模型参数,Claude Code 和 Codex 都要用,用锚点定义一次,两处引用即可,改一处全生效。这种复用能力在 JSON 里要靠工具层实现,在 YAML 里是语言原生支持的。
提示:YAML 对缩进极其敏感,Tab 和空格混用会直接报解析错误。建议在编辑器里把 Tab 键映射为两个空格,并且开启 YAML 语法校验插件,写的时候就能发现缩进问题,不用等到运行时才报错。
2.2 tmux 在编排里扮演什么角色
很多人第一次接触 openrig 会疑惑:配置文件管理就管理配置,为什么要把 tmux 拉进来?答案在于会话生命周期。Claude Code 和 Codex 都是长时间运行的交互式进程,你不可能每次用的时候重新启动、重新加载上下文。tmux 提供的是持久化会话能力——你关掉终端窗口,会话还在后台跑;你重新连上来,之前的对话上下文原封不动。
更关键的是 tmux 的 pane 分割能力。openrig 的设计思路是:一个 tmux 会话里开多个 pane,每个 pane 跑一个助手实例,你可以左边让 Claude Code 分析代码结构,右边让 Codex 生成测试用例,中间再开一个 shell 跑构建命令。三个 pane 共享同一个工作目录,文件改动实时可见,协作效率比开三个终端窗口高得多。
从实现角度看,openrig 并不直接操作 tmux 的底层 socket,而是通过生成 tmux 命令序列来实现编排。这样做的好处是兼容性好,任何支持 tmux 的环境都能跑,不依赖特定版本的 tmux API。代价是启动时会有轻微的命令拼接开销,但相对于 AI 助手的响应时间,这点开销可以忽略。
2.3 配置分层:全局、项目、会话三级结构
openrig 的配置不是一坨,而是分成三层。全局层放在用户主目录下,定义所有项目通用的参数,比如默认模型端点、默认超时、日志级别。项目层放在项目根目录,覆盖全局层里需要针对本项目调整的项,比如工作目录、忽略文件规则、特定模型的温度参数。会话层是运行时通过命令行参数传入的临时覆盖,比如这次启动临时换个模型试试效果。
这种分层设计的好处是避免配置重复。假设你有十个项目都用同一个模型端点,全局层写一次就够了,项目层只需要写各自不同的部分。新人接手项目时,看项目层的配置文件就能知道这个项目的特殊之处,不用去翻全局配置猜哪些参数被覆盖了。
三层配置的合并规则是就近优先:会话层覆盖项目层,项目层覆盖全局层。合并粒度是键级别的,不是整个文件替换。也就是说,项目层只写了model.temperature,那全局层里的model.endpoint依然生效,不会被清空。这个规则在文档里要写清楚,否则用户容易误以为项目层配置会完全替换全局层。
3. 核心配置项与实操要点
3.1 助手定义块:一个助手一份配置
openrig 的 YAML 里,每个助手对应一个顶层键。Claude Code 的配置块和 Codex 的配置块结构相同,但字段取值可以完全不同。下面是一份最小可用的配置示例:
assistants: claude: command: claude args: - "--model" - "claude-sonnet-4-20250514" workdir: "." env: ANTHROPIC_API_KEY: "${CLAUDE_KEY}" tmux: pane_title: "claude-code" start_delay: 2 codex: command: codex args: - "--model" - "o4-mini" workdir: "." env: OPENAI_API_KEY: "${CODEX_KEY}" tmux: pane_title: "codex" start_delay: 3command字段指定可执行文件名,openrig 会从 PATH 里查找。args是启动参数数组,每个参数单独一行,避免空格转义问题。workdir是助手的工作目录,相对路径基于项目根目录解析。env定义环境变量,支持${VAR}语法引用系统环境变量,这样密钥不用写死在配置文件里。
tmux子块控制 pane 的行为。pane_title设置 pane 标题,方便在多个 pane 之间快速识别。start_delay是启动延迟,单位秒,作用是等前一个 pane 的助手完成初始化再启动下一个,避免同时启动时资源争抢导致某个助手启动失败。这个值设多少合适?我的经验是 Claude Code 给 2 秒,Codex 给 3 秒,如果机器负载高就再加 1 到 2 秒。
注意:
env里的密钥引用不要用明文。即使配置文件不提交到版本库,本地明文存储也有泄露风险。推荐的做法是把密钥放在系统的密钥管理工具里,通过 shell 的export注入环境变量,YAML 里只写引用。
3.2 模型端点配置:本地与远程的取舍
AI 编程助手能不能连本地模型,是很多人关心的点。openrig 在这块的设计是端点可配,你填什么地址它就连什么地址。远程官方端点、本地推理服务、公司内网网关,只要兼容对应的 API 协议,都能接。
配置端点时要注意协议差异。Claude Code 走的是 Anthropic 的消息格式,Codex 走的是 OpenAI 的对话格式,两者的请求体和响应体结构不同。openrig 不做协议转换,它只负责把端点地址传给对应的助手,协议适配由助手自己处理。这意味着你不能把 Claude Code 指向一个只支持 OpenAI 格式的端点,反之亦然。
本地模型接入时,常见的坑是上下文长度不匹配。远程模型动辄 128K 甚至 1M 上下文,本地模型可能只有 8K 或 32K。如果你在配置里写了超长上下文参数,本地服务会直接拒绝请求。解决办法是在项目层配置里针对本地模型单独设置上下文上限,不要沿用全局层的值。
| 端点类型 | 适用场景 | 延迟表现 | 配置要点 |
|---|---|---|---|
| 官方远程端点 | 追求模型能力上限 | 受网络影响,波动较大 | 密钥管理要严格 |
| 本地推理服务 | 数据不出本机、离线可用 | 稳定,取决于硬件 | 注意上下文长度和显存占用 |
| 内网网关 | 团队统一管理、审计需求 | 较稳定 | 确认网关支持的协议版本 |
3.3 会话保持与恢复策略
tmux 会话的命名规则在 openrig 里是可以配置的。默认规则是openrig-<项目名>-<时间戳>,这样多个项目的会话不会冲突。如果你希望固定会话名方便脚本引用,可以在配置里指定session_name字段,但要注意同一时间只能有一个同名会话存在,重复启动会报错。
会话恢复是 tmux 的强项。你detach之后,助手进程继续在后台跑,上下文不丢。重新attach回来,看到的还是离开时的界面。这个特性在跑长任务时特别有用——比如让 Codex 批量生成一百个测试文件,你 detach 去开会,回来接着看进度。
但会话恢复有个前提:助手进程本身要支持长时间运行不崩溃。Claude Code 和 Codex 在这一点上表现不同。Claude Code 的会话稳定性较好,跑几个小时没问题。Codex 在长时间空闲后可能会断开连接,需要重新认证。针对这种情况,openrig 的配置里可以加一个keepalive选项,定期向助手发送心跳,防止空闲断开。心跳间隔建议设成 60 秒,太频繁会增加不必要的请求,太稀疏起不到保活作用。
4. 完整实操流程与关键环节
4.1 环境准备:从零到可运行
先把基础工具装齐。openrig 本身是一个命令行工具,安装方式取决于你的系统。假设你在 Linux 或 macOS 上,用包管理器或者从源码构建都可以。从源码构建的话,需要 Go 或 Rust 工具链,具体看项目用的是哪个语言。构建完成后把二进制放到 PATH 里,运行openrig --version确认安装成功。
tmux 的安装相对简单,主流发行版的包管理器里都有。装完之后建议改一下默认配置,把base-index设成 1,pane-base-index设成 1,这样 pane 编号从 1 开始,符合直觉。另外把mouse打开,方便用鼠标切换 pane 和调整大小。这些配置写在~/.tmux.conf里,openrig 启动时会读取。
Claude Code 和 Codex 的安装各自独立。Claude Code 通过 npm 全局安装,装完之后运行一次认证流程,把凭证存到本地。Codex 的安装方式类似,但认证走的是另一套流程。两个工具都装好之后,分别手动跑一次,确认能正常对话,再交给 openrig 管理。这一步不能省,因为 openrig 只是编排层,底层工具本身有问题的话,编排层排查起来更麻烦。
4.2 编写第一份 openrig 配置
从最小配置开始,不要一上来就写全量。先定义两个助手,各给最基本的参数,跑通之后再逐步加东西。下面这份配置是我实际用的简化版:
version: "1" defaults: workdir: "." log_level: "info" timeout: 300 assistants: claude: command: claude args: ["--model", "claude-sonnet-4-20250514"] env: ANTHROPIC_API_KEY: "${CLAUDE_KEY}" tmux: pane_title: "claude" start_delay: 2 codex: command: codex args: ["--model", "o4-mini"] env: OPENAI_API_KEY: "${CODEX_KEY}" tmux: pane_title: "codex" start_delay: 3 layout: direction: "horizontal" panes: - assistant: "claude" size: "50%" - assistant: "codex" size: "50%"version字段用于配置格式版本管理,将来格式升级时可以据此做兼容处理。defaults块定义所有助手共享的默认值,助手块里没写的字段从这里继承。layout块定义 tmux 的 pane 布局,direction是分割方向,horizontal表示左右分,vertical表示上下分。panes列表里每一项指定用哪个助手、占多大比例。
写完配置后,运行openrig validate做语法和语义校验。这个命令会检查 YAML 格式、必填字段、命令是否存在、环境变量是否已定义。校验通过再启动,能省掉很多运行时排查的时间。
4.3 启动、切换与日常操作
启动命令是openrig up,它会读取配置、创建 tmux 会话、按布局启动各个助手。启动过程中终端会显示每个 pane 的初始化状态,全部就绪后自动 attach 到会话里。如果某个助手启动失败,openrig 会保留已成功的 pane,并在失败 pane 里显示错误信息,方便你排查。
日常操作围绕 tmux 的快捷键展开。Ctrl+b加方向键切换 pane,Ctrl+b加z放大当前 pane,Ctrl+b加ddetach 会话。这些是 tmux 原生操作,openrig 不做拦截。另外 openrig 提供了几个自定义命令:openrig status查看当前会话里各助手的状态,openrig restart <assistant>重启指定助手,openrig down关闭整个会话。
切换助手时有个细节要注意:Claude Code 和 Codex 的工作目录是独立的,但文件系统是共享的。如果你在 Claude Code 里改了文件,Codex 那边不会自动感知,需要它重新读取文件才能看到改动。这不是 openrig 的问题,是 AI 助手本身的工作机制决定的。实际操作中,我习惯在一个 pane 里改完文件后,切到另一个 pane 手动触发一次文件读取,确保两边看到的是同一份代码。
4.4 参数计算与资源规划
同时跑多个 AI 助手对系统资源有要求。每个助手进程本身占用的内存不大,通常在几百 MB 级别,但模型推理如果走本地服务,显存占用就是大头。以本地跑一个 7B 参数的模型为例,量化到 4bit 大约需要 4 到 6 GB 显存,加上 KV cache 和运行时开销,实际占用可能到 8 GB。如果你同时跑两个本地模型实例,显存需求翻倍。
CPU 方面,助手进程主要是网络 IO 和文本处理,CPU 占用不高。但如果本地推理服务跑在同一台机器上,CPU 会参与计算,负载会明显上升。我的建议是:本地推理服务和助手编排不要放在同一台资源紧张的机器上,要么用远程端点,要么给本地服务单独分配资源。
网络带宽在远程端点场景下是瓶颈。Claude Code 和 Codex 的请求体通常不大,但响应体可能很长,尤其是生成大段代码时。如果网络不稳定,响应会超时。openrig 的timeout默认值是 300 秒,对于大多数场景够用。如果你经常处理超大文件,可以调到 600 秒,但要注意 tmux pane 里的等待体验会变差。
5. 常见问题与排查技巧实录
5.1 启动失败类问题速查
启动阶段的问题最好排查,因为错误信息通常比较明确。下面这张表整理了我遇到过的高频问题:
| 现象 | 可能原因 | 排查方法 | 解决方式 |
|---|---|---|---|
| 提示命令不存在 | PATH 里没有该助手 | which claude确认 | 安装助手或修正 PATH |
| YAML 解析报错 | 缩进用了 Tab | 编辑器显示空白字符 | 统一改成空格 |
| 环境变量为空 | 变量未导出 | echo $CLAUDE_KEY | 在 shell 里 export |
| tmux 会话已存在 | 上次未正常关闭 | tmux ls查看 | openrig down清理 |
| pane 启动后立即退出 | 助手认证失效 | 手动跑一次助手 | 重新认证 |
环境变量为空这个问题特别常见。openrig 读取的是启动它的那个 shell 的环境变量,如果你在.bashrc里 export 了变量,但用sudo或者从桌面图标启动,环境变量可能不继承。解决办法是在 openrig 的配置里用绝对路径引用密钥文件,或者写一个包装脚本,在脚本里 source 环境变量再启动 openrig。
5.2 运行中异常的处理思路
运行中的问题比启动问题难排查,因为现象可能很模糊。最常见的现象是助手突然不响应了,输入没反应,也不报错。这时候先看 tmux pane 里的进程状态,用ps aux | grep claude确认进程还在不在。进程在但不响应,多半是网络请求卡住了,等超时或者手动中断重试。进程不在了,说明助手崩溃了,看日志找原因。
日志是排查运行问题的关键。openrig 默认把每个助手的输出重定向到~/.openrig/logs/下的独立文件,按助手名和时间戳命名。日志级别可以在配置里调,默认是info,排查问题时临时调到debug能看到更详细的请求和响应信息。但debug级别日志量很大,问题解决后记得调回去,否则磁盘很快被占满。
另一个高频问题是上下文丢失。你明明在会话里聊了很久,重新 attach 回来发现助手失忆了。这通常是因为助手进程在后台被系统回收了,tmux 会话还在,但里面的进程没了。预防办法是给助手进程设置较高的优先级,或者在 openrig 配置里开启auto_restart,进程退出后自动拉起。但自动重启会丢失上下文,所以更根本的解决办法是确保系统内存充足,不要让 OOM killer 盯上你的助手进程。
5.3 多助手协作时的冲突避免
两个助手同时操作同一个文件,冲突几乎必然发生。Claude Code 在改main.py,Codex 也在改main.py,后写的覆盖先写的,改动就丢了。openrig 本身不做文件锁,这需要你在工作流程上规避。
我的做法是按文件类型分工。Claude Code 负责重构和逻辑修改,主要动.py和.ts文件;Codex 负责生成测试和文档,主要动test_开头的文件和.md文件。两边的工作集不重叠,冲突自然就没了。如果确实需要改同一个文件,就在一个 pane 里改完,切到另一个 pane 让它重新读取,不要两边同时改。
还有一种冲突是端口占用。如果两个助手都启动了本地服务,比如预览服务器,默认端口可能撞车。解决办法是在各自的配置里指定不同的端口,或者让其中一个助手用随机端口。这个在配置的env块里设置,比如PORT: "3001"和PORT: "3002"。
提示:多助手协作时,建议在项目根目录放一个
COLLAB.md,写清楚哪个助手负责哪类文件、当前有哪些正在进行的任务。这看起来有点笨,但实际用起来能避免大量重复劳动和覆盖冲突。
5.4 性能调优的几个实操技巧
助手响应慢的时候,先分清是模型端慢还是本地环境慢。在 tmux pane 里直接curl一下模型端点,看响应时间。如果 curl 很快但助手很慢,问题在助手本身,可能是上下文太长导致处理变慢。如果 curl 就慢,那是端点的问题,换端点或者等网络恢复。
上下文长度对性能影响很大。Claude Code 在处理长上下文时,每次请求都要把整个上下文发给模型,上下文越长,请求体越大,响应越慢。定期清理不需要的上下文,或者开新会话处理新任务,能明显提升响应速度。openrig 的openrig restart <assistant>命令就是干这个的,重启后上下文清空,助手回到初始状态。
tmux 的渲染性能在 pane 很多的时候会下降。如果你开了四五个 pane,每个 pane 都在快速输出,终端可能会卡。解决办法是减少同时可见的 pane 数量,把不看的 pane 放到后台窗口里,需要时再切过来。tmux 的 window 机制就是为这个场景设计的,一个会话里开多个 window,每个 window 里再分 pane,层级管理比全挤在一个 window 里清晰得多。
6. 配置复用与团队协作的进阶玩法
6.1 用锚点和引用消除重复配置
YAML 的锚点功能在 openrig 配置里能省大量重复。假设你有三个助手,都用同一个模型端点,只是模型名不同。用锚点定义公共部分,三个助手引用即可:
common: &common workdir: "." timeout: 300 env: LOG_LEVEL: "info" assistants: claude: <<: *common command: claude args: ["--model", "claude-sonnet-4-20250514"] codex: <<: *common command: codex args: ["--model", "o4-mini"] helper: <<: *common command: some-helper args: ["--mode", "fast"]&common定义锚点,*common引用锚点,<<:是合并键,把锚点内容合并到当前块。这样公共配置只写一次,改一处全生效。注意合并是浅合并,如果助手块里也定义了env,会整个替换锚点里的env,而不是合并两个env的键。需要深合并的话,得用 YAML 的扩展语法或者工具层处理。
6.2 把配置纳入版本管理
openrig 的配置文件应该提交到版本库,但密钥不能提交。做法是把配置拆成两份:openrig.yaml提交,里面用${VAR}引用密钥;openrig.local.yaml不提交,里面写实际的密钥值,通过.gitignore排除。openrig 启动时先读主配置,再读本地配置做覆盖。
团队协作时,主配置由团队维护,本地配置由各人自己填。新人入职只需要复制一份openrig.local.yaml.example,填入自己的密钥即可。这样既保证了配置的一致性,又避免了密钥泄露。
配置变更要走代码审查流程。改openrig.yaml相当于改团队的工作环境,影响所有人。审查时重点关注:端点地址有没有改错、超时值有没有调得过大或过小、有没有引入不兼容的字段。这些改动在本地测试通过后再合并,避免影响其他人的工作。
6.3 跨平台适配的注意事项
openrig 在 Linux 和 macOS 上表现一致,Windows 上需要额外处理。Windows 原生不支持 tmux,得通过 WSL 或者类似的兼容层来跑。WSL 里的文件系统路径和 Windows 不一样,配置里的workdir要用 WSL 的路径格式,比如/mnt/c/Users/...而不是C:\Users\...。
路径分隔符也是坑。YAML 里写路径用正斜杠/最安全,Windows 和 Unix 都能识别。反斜杠\在 YAML 里是转义字符,写路径时容易出问题,能不用就不用。
换行符在跨平台时也要注意。配置文件的换行符统一用 LF,不要用 CRLF。Git 的core.autocrlf设置可能导致换行符被自动转换,建议在项目里加.gitattributes文件,强制 YAML 文件用 LF。
7. 我踩过的坑和最后分享的几个技巧
第一个坑是过度配置。刚开始用 openrig 的时候,我把所有能配的字段都配了一遍,结果配置文件两百多行,改一个参数要翻半天。后来精简到只配必要的字段,其余用默认值,配置文件缩到五十行以内,维护成本大幅下降。默认值之所以是默认值,就是因为它适用于大多数场景,不要为了配而配。
第二个坑是忽略启动延迟。早期配置里start_delay都设成 0,结果两个助手同时启动,偶尔有一个会因为资源争抢启动失败。加上延迟之后问题消失。延迟值不用很精确,宁可多等一两秒,也不要让启动失败浪费更多时间。
第三个坑是日志不清理。debug级别的日志一天能写几个 GB,磁盘满了才发现。现在我在配置里加了日志轮转,按大小切分,保留最近七天的日志,自动清理旧的。这个配置在defaults块里加log_rotate子块即可。
最后分享一个提高效率的小技巧:把常用的 openrig 命令做成 shell 别名。比如alias ou='openrig up'、alias od='openrig down'、alias os='openrig status'。每天敲几十次的命令,省下的按键次数累积起来很可观。另外在 tmux 配置里给 openrig 会话绑定一个快捷键,一键 attach 到当前项目的会话,不用每次敲完整的会话名。
这套东西用下来,最大的感受是配置即文档。一份写好的 openrig.yaml,新人看一眼就知道这个项目用了哪些助手、连的什么端点、怎么启动。比口头交接靠谱得多,也比写一堆 README 有效得多。工具链的标准化,最终受益的是整个团队的协作效率。