1. 从openrig这个名字说起它到底想解决什么问题第一次看到openrig这个词我下意识把它拆成了两半open和rig。rig在工程语境里通常指装配好的成套装置比如一台调试好的机器、一套搭好的工作台。放到 AI 编程工具这个场景里openrig想做的事情就很清楚了——把散落各处的 AI 编码助手Claude Code、Codex 这类命令行工具装配成一套统一、可切换、可复用的工作台。为什么会有这个需求只要你同时用过 Claude Code 和 Codex就一定经历过这种混乱两个工具各有各的配置文件、各有各的认证方式、各有各的启动命令。今天想用 Claude Code 写业务逻辑明天想用 Codex 跑重构结果每次切换都要重新翻文档、改环境变量、确认 API 端点有没有配对。更麻烦的是当你在一个终端里同时开着好几个会话tmux窗口切来切去根本记不清哪个 pane 跑的是哪个工具、连的是哪个模型。openrig的核心价值就是把这些各自为政的 AI 编码工具收敛到一套统一的配置层里。它用YAML作为配置载体把模型接入、端点地址、认证信息、启动参数全部抽象成声明式的配置项再配合tmux做会话管理让你在一个统一的入口下切换不同的 AI 后端。说白了它想当的是 AI 编码工具的配电箱——上游接各种模型和工具下游输出统一的操作体验。这篇文章适合谁看如果你已经在用 Claude Code 或 Codex但被多工具切换、多模型接入、配置散乱这些问题折磨过那这篇就是写给你的。如果你还没上手只是想搞清楚这套东西的运作逻辑也能从里面拿到一套可复现的配置思路。我不会只给你一堆命令而是把每个设计决策背后的为什么讲透让你能根据自己的环境改出一套顺手的方案。2. 为什么是 YAML tmux 这套组合拳2.1 YAML 承担的是配置即文档的角色很多人第一次接触openrig这类工具时会问为什么不用 JSON不用 TOML偏偏用 YAML这个问题值得认真回答因为它直接关系到你后续维护配置的成本。JSON 的问题在于不支持注释而且括号嵌套一多人眼很难快速定位层级。TOML 虽然可读性好但在表达嵌套结构比如一个工具下有多个模型 profile每个 profile 又有自己的参数时写起来会变得很啰嗦。YAML 的优势恰好卡在中间它用缩进表达层级视觉上就是一棵树同时支持注释你可以直接在配置里写这行是给 DeepSeek 用的那行是给本地模型用的。举个实际的配置片段你能直观感受到 YAML 的表达力profiles: claude-deepseek: tool: claude-code endpoint: https://api.deepseek.com/v1 model: deepseek-chat env: ANTHROPIC_BASE_URL: https://api.deepseek.com/anthropic notes: 走 DeepSeek 的 Anthropic 兼容端点成本低适合日常写代码 codex-local: tool: codex endpoint: http://127.0.0.1:1234/v1 model: local-coder-7b env: OPENAI_API_KEY: sk-local-placeholder notes: 接本地 LM Studio断网也能跑适合敏感代码这段配置里profiles是顶层键下面每个 profile 是一个独立的工具配置。notes字段就是 YAML 相对 JSON 的杀手锏——你可以把为什么这么配直接写在配置旁边三个月后回来看也不会一脸懵。提示YAML 对缩进极其敏感绝对不能用 Tab必须用空格。建议统一用 2 个空格并且在编辑器里开启显示空白字符否则一个看不见的 Tab 就能让你排查半小时。2.2 tmux 解决的是多会话并存的物理问题配置统一了但还有个现实问题你不可能同时只跑一个 AI 工具。写代码的时候你可能一边让 Claude Code 帮你分析一个模块一边让 Codex 生成单元测试同时还想留一个窗口看日志。这时候如果没有会话管理你的终端就会变成一团乱麻。tmux在这里扮演的是窗口管理器的角色。它把每个 AI 工具的运行实例放进独立的 pane 或 window你可以随时切过去看进度也可以让它们在后台跑着自己去做别的事。openrig把 tmux 的会话创建逻辑也纳入了配置体系这意味着你可以定义启动 claude-deepseek 这个 profile 时自动开一个名为ai-claude的 tmux 会话左边跑工具右边跑日志。这套组合的妙处在于职责分离YAML 管配什么tmux 管怎么跑。配置和运行时解耦之后你想换模型只需要改 YAML想换布局只需要改 tmux 参数互不干扰。2.3 一个容易被忽略的细节端点兼容性热词里反复出现cc switch local proxy failed while handling codex endpoint /responses这类报错本质上是端点协议不匹配。Claude Code 走的是 Anthropic 的 Messages API 格式Codex 走的是 OpenAI 的 Responses/Chat Completions 格式两者不能直接互换。openrig在配置层把tool和endpoint分开声明就是为了让你明确知道这个 profile 是给哪个工具用的、连的是哪种协议的端点。如果你把 Claude Code 指向一个只支持 OpenAI 格式的端点就会看到类似failed while handling endpoint的错误。这不是工具坏了是协议对不上。解决办法要么是找一个同时提供两种兼容格式的服务商要么在中间加一层协议转换。配置里把tool字段写清楚就是为了在启动前就能发现这类不匹配。3. 把 openrig 的配置骨架搭起来3.1 目录结构先定规矩再动手在写任何配置之前先把目录结构定下来。我踩过的坑是一开始随手把配置文件丢在 home 目录结果 profile 一多~下面全是xxx.yaml找起来要命。后来我固定成这套结构清爽很多~/.openrig/ ├── config.yaml # 主配置定义全局默认值 ├── profiles/ # 每个工具/模型组合一个文件 │ ├── claude-deepseek.yaml │ ├── claude-official.yaml │ ├── codex-local.yaml │ └── codex-remote.yaml ├── sessions/ # tmux 会话布局定义 │ └── default-layout.yaml └── logs/ # 运行日志方便排查把 profile 拆成独立文件的好处是改一个不会影响其他也方便用 git 管理。你可以给不同的项目建不同的 profile 集合需要时软链接过去就行。3.2 主配置里该放什么、不该放什么主配置config.yaml只放全局默认值和路径约定不要把具体的模型参数塞进来。我的原则是能在 profile 里覆盖的就不要写死在主配置。这样主配置保持稳定profile 可以随便折腾。# ~/.openrig/config.yaml defaults: shell: /bin/bash tmux_prefix: ai- log_dir: ~/.openrig/logs timeout: 300 tools: claude-code: binary: claude config_dir: ~/.claude codex: binary: codex config_dir: ~/.codex active_profile: claude-deepseek这里active_profile是当前默认使用的 profile切换时改这一行就行。tools段声明了每个工具的可执行文件路径和配置目录openrig启动时会去这些目录里读取工具自身的配置避免重复维护。注意binary字段填的是命令名还是绝对路径取决于你的安装方式。如果是全局安装比如通过包管理器填命令名即可如果是手动解压的建议填绝对路径避免 PATH 问题导致找不到命令。3.3 profile 文件的字段设计逻辑一个完整的 profile 需要回答四个问题用哪个工具、连哪个端点、用什么模型、带哪些环境变量。我把它设计成下面这样# ~/.openrig/profiles/claude-deepseek.yaml name: claude-deepseek tool: claude-code endpoint: https://api.deepseek.com/anthropic model: deepseek-chat env: ANTHROPIC_BASE_URL: https://api.deepseek.com/anthropic ANTHROPIC_API_KEY: ${DEEPSEEK_API_KEY} ANTHROPIC_MODEL: deepseek-chat tmux: session: ai-claude layout: default-layout几个关键点值得展开说。第一env里的 API Key 用${DEEPSEEK_API_KEY}这种占位符实际值从系统环境变量读取绝对不要把明文密钥写进配置文件。第二ANTHROPIC_BASE_URL和endpoint看起来重复但前者是给 Claude Code 进程读的后者是给openrig自己判断用的职责不同。第三tmux.session指定了会话名方便你用tmux attach -t ai-claude直接连上去。3.4 tmux 布局配置让会话开箱即用default-layout.yaml定义的是会话打开后的窗口和 pane 划分。我常用的布局是左边主工作区、右边日志区# ~/.openrig/sessions/default-layout.yaml windows: - name: main panes: - command: {{tool_command}} size: 70 - command: tail -f {{log_dir}}/{{profile_name}}.log size: 30{{tool_command}}和{{profile_name}}是模板变量openrig启动时会替换成实际值。这样一套布局可以复用到所有 profile不用每个都重写。4. 多工具切换的实战Claude Code 与 Codex 并存4.1 两个工具的配置目录差异Claude Code 和 Codex 各自维护自己的配置目录这是切换时最容易出问题的地方。Claude Code 默认读~/.claudeCodex 默认读~/.codex。如果你在openrig里改了端点但工具自身的配置文件里还留着旧值就会出现配置改了但没生效的诡异现象。我的做法是让 openrig 成为唯一的配置入口工具自身的配置文件只保留最小必要内容。具体来说Claude Code 的~/.claude/settings.json里只留认证相关的字段端点、模型这些全部通过环境变量注入。Codex 同理~/.codex/config.toml里只留基础设置模型和端点走环境变量。这样做的理由是环境变量的优先级通常高于配置文件而且openrig可以在启动时动态设置不需要反复改文件。切换 profile 时环境变量一变工具读到的就是新配置。4.2 切换时的环境变量注入顺序环境变量的注入顺序会直接影响最终生效的值。openrig的处理逻辑是先加载系统环境变量再加载主配置里的defaults最后加载 profile 里的env。后面的覆盖前面的。这个顺序很重要因为它决定了你能不能用一个全局默认值兜底再用 profile 覆盖特殊情况。举个例子假设你系统里已经设了ANTHROPIC_API_KEY但某个 profile 想用另一个 key。只要在 profile 的env里重新声明就会覆盖系统的值。反过来如果 profile 里没声明就自动用系统的不用重复写。提示排查配置没生效时第一件事是在启动后的 shell 里执行env | grep ANTHROPIC看看实际注入的值是什么。十次有八次是环境变量被别的地方覆盖了。4.3 用 tmux 会话隔离不同工具同时跑 Claude Code 和 Codex 时我强烈建议用不同的 tmux 会话隔离而不是在同一个会话里开多个 pane。原因是这两个工具都会占用终端输入混在一起容易误操作。用独立会话Ctrlb加s就能在会话间切换互不干扰。会话命名我遵循ai-工具名的约定比如ai-claude、ai-codex。这样tmux ls一眼就能看出哪些会话在跑 AI 工具。如果你跑了很多实例还可以加项目后缀比如ai-claude-projectA。4.4 常见报错的定位路径热词里那串cc switch local proxy failed while handling codex endpoint /responses是典型的端点协议错误。定位路径是这样的先确认tool字段和endpoint是否匹配——Codex 必须连支持/responses或/chat/completions的端点Claude Code 必须连支持/v1/messages的端点。如果端点只支持一种协议另一个工具连上去必然报错。第二类常见错误是认证失败表现为auth token is unavailable。这通常是环境变量没注入成功或者 key 过期了。检查方法是手动curl一下端点带上 key 看能不能通。第三类是模型名写错报model not found这个最直接对着服务商的文档核对模型名即可。5. 接入本地模型与第三方端点的配置要点5.1 本地模型的端点格式陷阱把 Claude Code 或 Codex 接到本地模型比如通过 LM Studio 起的服务时最大的坑是端点格式。本地服务通常只提供 OpenAI 兼容格式而 Claude Code 需要 Anthropic 格式。这时候要么用支持双格式的本地服务要么在中间加转换层。配置本地模型时endpoint一般填http://127.0.0.1:1234/v1这种形式model填本地加载的模型标识。API Key 随便填一个非空字符串即可本地服务通常不校验。但要注意有些本地服务对model字段的匹配很严格必须和加载时的名称完全一致。5.2 第三方端点的兼容性核对清单接第三方端点前先核对这几项端点是否支持目标工具所需的协议格式、模型名是否和服务商文档一致、是否需要额外的 header比如某些服务商要求anthropic-version、是否有速率限制。我一般会先用curl手动测一遍确认通了再写进配置。curl -s https://api.example.com/v1/messages \ -H x-api-key: $API_KEY \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d {model:model-name,max_tokens:10,messages:[{role:user,content:hi}]}这个命令能通说明端点和认证都没问题再写进openrig配置就稳了。5.3 密钥管理别把 key 写进 YAML这是必须强调的一点。YAML 文件很容易被误提交到 git一旦密钥泄露后果很严重。正确做法是配置文件里只写${VAR_NAME}占位符实际值放在 shell 的 profile 文件如~/.bashrc或专门的密钥管理工具里。openrig启动时从环境变量读取配置文件本身不含敏感信息。如果你用 git 管理配置建议加一个.gitignore排除所有含密钥的文件并且定期用git log -p检查有没有误提交。6. 我在实际使用中踩过的坑和总结的经验第一个坑是 YAML 缩进。我一开始用编辑器自动格式化结果它把 Tab 和空格混用openrig解析时报了一堆莫名其妙的错。后来我强制自己用 2 空格缩进并且在编辑器里开了渲染空白字符这个问题就再没出现过。第二个坑是 tmux 会话残留。有时候工具崩了但 tmux 会话还在下次启动时因为会话名冲突起不来。我的解决办法是在启动脚本里加一句tmux kill-session -t name 2/dev/null || true先清理再创建保证每次都是干净的环境。第三个坑是环境变量污染。我在一个终端里切了 profile忘了新开终端结果旧的环境变量还在导致新 profile 的行为和预期不符。现在我养成了习惯切换 profile 后一定新开一个 shell或者用env -i起一个干净环境。最后一个经验是关于日志的。openrig把每个 profile 的运行日志写到logs/目录我建议你定期看一眼。很多问题在报错之前日志里已经有警告了。比如端点响应变慢、认证即将过期这些都能提前发现避免写到一半突然断掉。这套配置搭好之后我现在的日常是早上开一个ai-claude会话写业务代码下午开ai-codex会话跑重构和测试需要本地模型时切到ai-local。三个会话用 tmux 管理配置全在 YAML 里改起来就是编辑一个文件的事。比起以前每个工具单独折腾效率提升是实打实的。