ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

openrig:终端AI工作流编排实战,Claude Code与Codex环境搭建

openrig:终端AI工作流编排实战,Claude Code与Codex环境搭建

1. 从“openrig”说起:一个被低估的终端工作流编排思路

第一次看到“openrig”这个词,我下意识把它拆成了“open”和“rig”两部分。rig在工程语境里从来不是“钻机”这么简单,它更多指的是一整套搭起来能跑、能扛、能复用的装置或架子。放到开发场景里,openrig本质上就是一套开放的、可自由拼装的终端工作环境编排方案。它不绑定某个具体工具,而是把Claude Code、Codex这类命令行AI助手,连同Node.js运行时、tmux会话管理这些基础件,用一套轻量但稳固的方式串起来。

你可能会问,这跟直接开个终端敲命令有什么区别?区别大了。我见过太多人装完Claude Code或者Codex之后,每次用都要重新cd到项目目录、重新配环境变量、重新开一堆窗口,切来切去最后自己都乱了。openrig要解决的就是这个“乱”字。它把环境准备、会话保持、多模型切换、代理转发这些琐碎但关键的环节,收敛成一套可重复执行的流程。适合谁看?如果你正在Windows、Ubuntu或者VS Code里折腾Claude Code和Codex,被Node.js版本、tmux会话、本地模型接入这些事搞得头大,那这篇内容就是给你写的。

我自己的习惯是,任何工具只要一天之内要用超过三次,就必须把它“rig”起来。openrig这个思路最吸引我的地方在于,它不要求你放弃已有的工具链,而是让你在现有基础上加一层薄薄的编排。下面我会从整体设计、核心细节、实操过程、问题排查四个维度,把这套东西掰开揉碎讲清楚。

2. 整体设计与思路拆解:为什么是这套组合

2.1 核心需求:让AI命令行助手真正融入日常终端

Claude Code和Codex这类工具的本质,是把大模型的代码理解与生成能力塞进终端。但终端本身是个“易失”环境,关掉窗口,上下文就没了。你昨天调好的模型参数、切好的工作目录、配好的API端点,今天重开又得再来一遍。openrig的第一个设计目标就是对抗这种易失性。

我试过几种方案。最粗暴的是写个shell脚本,每次启动时source一下。但脚本只能解决环境变量的问题,解决不了会话保持和多任务并行。后来用tmux,发现它天然适合做这件事。tmux的session可以detach再attach,窗口和面板的布局也能保存。把Claude Code跑在tmux的某个window里,你随时可以断开,第二天回来接着用,上下文还在。

第二个设计目标是多模型共存。现在很多人手里不止一个模型端点,Claude Code官方订阅、Codex接入DeepSeek、本地LM Studio跑的模型,可能同时都在用。openrig的思路是用一个统一的入口来管理这些端点,而不是每换一个模型就改一次配置文件。cc switch这类工具就是干这个的,它让你在Claude Code和Codex之间快速切换,同时保持各自的配置独立。

第三个目标是降低环境依赖的摩擦。Node.js的版本问题坑了无数人,尤其是那个“node.js v24.21.0 is not yet released”的报错,本质上是nvm或者安装脚本去拉了一个不存在的版本。openrig在设计上会明确锁定LTS版本,避免追新带来的意外。

2.2 方案选型:为什么是Node.js + tmux + cc switch

选Node.js作为运行时,原因很直接。Claude Code和Codex的CLI都是Node.js生态里的包,npm install是最自然的安装方式。Node.js LTS版本(比如20.x或22.x)的稳定性经过大量项目验证,没必要为了新特性去冒险。我实测下来,Node.js 20 LTS配合npm 10,装Claude Code和Codex都没遇到过依赖冲突。

tmux的选择更多是出于“终端复用”的刚需。它比screen更活跃,配置也更直观。一个典型的openrig布局是这样的:session名叫“ai-work”,里面开三个window,第一个跑Claude Code,第二个跑Codex,第三个留给普通的shell操作。每个window可以再分pane,比如左边看代码,右边跟AI对话。这种布局一旦配好,写进tmux.conf,以后一条命令就能恢复整个工作现场。

cc switch的定位是“模型端点切换器”。它本身不产生智能,但它解决了“我想用DeepSeek的时候不用手动改Codex配置”这个问题。它的工作原理通常是维护多份配置文件,切换时把对应的那份软链或者复制到工具读取的位置。这个思路很干净,比在环境变量里塞一堆if-else要可靠得多。

2.3 优势与边界:这套方案适合什么,不适合什么

openrig这套组合的优势在于轻量和透明。所有组件都是命令行工具,没有GUI依赖,跑在远程Ubuntu服务器上或者本地Windows的WSL里都一样。配置文件是纯文本,可以进git做版本管理。出问题了,排查路径清晰:先看Node.js版本,再看tmux会话,再看cc switch的配置指向。

但它也有边界。如果你完全不用终端,所有操作都在VS Code的图形界面里完成,那tmux的价值就大打折扣。VS Code有自己的终端管理和任务系统,虽然不如tmux灵活,但对纯GUI用户更友好。另外,如果你只用一个模型,从不切换,那cc switch就是多余的。openrig的核心价值在于“多工具、多模型、多会话”的场景,单工具单模型的用户可以直接跳过中间层。

还有一个容易被忽略的点:openrig不解决网络层面的问题。它假设你的终端能正常访问所需的API端点。如果端点本身不可达,那是另一个维度的事情,不在openrig的职责范围内。

3. 核心细节解析与实操要点

3.1 Node.js环境:版本锁定与安装路径的坑

Node.js的安装看起来简单,但坑不少。最常见的错误是直接用系统包管理器装了一个过旧的版本,比如Ubuntu apt里的Node.js可能还是12.x。Claude Code和Codex对Node.js版本有最低要求,太旧了直接跑不起来。

我的做法是用nvm管理Node.js版本。nvm的好处是版本隔离,你可以同时装18、20、22,随时切换。安装nvm的命令很标准,但要注意安装完后需要重新加载shell配置,否则nvm命令找不到。具体来说,在Ubuntu上:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

然后关掉终端重开,或者执行source ~/.bashrc。接着装Node.js 20 LTS:

nvm install 20 nvm use 20 nvm alias default 20

nvm alias default 20这步很关键,它保证新开的终端默认用20版本,而不是系统自带的旧版本。我见过有人装完nvm后每次都要手动nvm use,就是因为漏了这步。

Windows用户如果不用WSL,直接装Node.js的Windows安装包也行。从官网下载LTS版本的.msi文件,一路下一步。但要注意,Windows下的路径分隔符和Ubuntu不同,tmux在Windows原生环境下不可用,需要WSL或者Git Bash配合。我个人的建议是,如果你主力在Windows,又想要tmux,直接上WSL2,省去很多兼容性麻烦。

注意:不要用nvm install node这种命令,它会装最新的Current版本,而不是LTS。Current版本可能包含未稳定的特性,Claude Code和Codex在上面跑可能出现奇怪的报错。

3.2 tmux会话管理:布局保存与快速恢复

tmux的默认配置比较朴素,但稍微改几行就能变得很顺手。我通常会在~/.tmux.conf里加这几条:

# 把前缀键从Ctrl+b改成Ctrl+a,更顺手 set -g prefix C-a bind C-a send-prefix # 开启鼠标支持,方便调整pane大小 set -g mouse on # 窗口编号从1开始 set -g base-index 1 setw -g pane-base-index 1 # 快速重载配置 bind r source-file ~/.tmux.conf \; display "Config reloaded"

改完前缀键后,所有tmux操作从Ctrl+b变成Ctrl+a。比如新建窗口是Ctrl+a c,水平分pane是Ctrl+a %,垂直分pane是Ctrl+a "。

对于openrig场景,我建议创建一个专门的session:

tmux new-session -s ai-work -n claude

然后在claude这个window里启动Claude Code。接着Ctrl+a c新建一个window叫codex,在里面启动Codex。再新建一个window叫shell,用来跑git、npm这些命令。布局调好后,Ctrl+a ddetach,整个会话就在后台保持。下次回来tmux attach -t ai-work,一切照旧。

如果想更进一步,可以把这套布局写成一个脚本,每次执行就自动创建好所有window和pane。tmux支持send-keys命令,可以在创建window后自动输入启动命令。比如:

tmux new-session -d -s ai-work -n claude tmux send-keys -t ai-work:claude 'claude' C-m tmux new-window -t ai-work -n codex tmux send-keys -t ai-work:codex 'codex' C-m

这样一条脚本跑完,两个AI助手都已经在各自的window里待命了。

3.3 cc switch与多模型端点切换

cc switch的核心逻辑是配置文件切换。以Codex为例,它的配置通常放在~/.codex/config.json或者类似位置。当你用cc switch切到DeepSeek时,它会把一份预置的DeepSeek配置写进去,或者把软链接指向那份配置。

我自己的做法是手动维护几份配置文件,放在~/.config/cc-switch/profiles/下面,命名成claude-official.json、codex-deepseek.json、codex-local.json这样。cc switch的作用就是把这些文件复制到工具实际读取的路径。如果你不想用cc switch,写个简单的shell函数也能达到同样效果:

ccswitch() { local profile=$1 cp ~/.config/cc-switch/profiles/$profile.json ~/.codex/config.json echo "Switched to $profile" }

这样ccswitch codex-deepseek就切到了DeepSeek端点。简单粗暴,但有效。

需要注意的是,切换配置后,正在运行的Codex进程不会自动重载配置。你需要退出Codex再重新启动,新配置才会生效。我踩过这个坑,切了配置发现没变化,折腾半天才发现是进程没重启。

提示:cc switch这类工具在切换时最好保留一份“已知可用”的配置作为回退。万一新配置有问题,能快速切回来,不至于卡在半路。

3.4 本地模型接入:LM Studio与Codex的配合

用LM Studio跑本地模型,然后让Codex去调用,这个场景越来越常见。LM Studio默认会在http://localhost:1234暴露一个兼容OpenAI的API。Codex的配置里需要把base URL指向这个地址,API key随便填一个非空字符串就行,本地模型不校验。

配置大概长这样:

{ "baseURL": "http://localhost:1234/v1", "apiKey": "lm-studio", "model": "local-model" }

这里有个细节:LM Studio里加载的模型名称要和配置里的model字段对应。如果你在LM Studio里加载的是qwen2.5-coder-7b,那model字段就写这个。写错了Codex会报模型不存在的错误。

本地模型的响应速度取决于你的硬件。7B参数量的模型在16GB内存的机器上跑,生成速度大概每秒十几到几十个token。如果你期待和云端模型一样的流畅度,可能会失望。但本地模型的好处是数据不出本机,适合处理敏感代码。

4. 实操过程与核心环节实现

4.1 从零搭建:Ubuntu下的完整流程

假设你拿到一台干净的Ubuntu 22.04,想把这套openrig环境搭起来。下面是我实际跑过一遍的步骤。

第一步,更新系统包并安装基础工具:

sudo apt update && sudo apt upgrade -y sudo apt install -y curl git tmux build-essential

build-essential是为了编译某些npm原生模块准备的,不装的话后面npm install可能报gyp错误。

第二步,安装nvm和Node.js 20:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 20 nvm alias default 20 node -v

node -v应该输出v20.x.x。如果输出的是系统自带的旧版本,检查一下~/.bashrc里nvm的初始化脚本有没有被正确加载。

第三步,安装Claude Code和Codex:

npm install -g @anthropic-ai/claude-code npm install -g @openai/codex

这两个包的名字可能会变,以官方文档为准。安装完成后,claude和codex命令应该能在终端里直接调用。

第四步,配置tmux。把前面提到的tmux.conf写好,然后创建会话:

tmux new-session -s ai-work -n claude

在claude window里运行claude,按提示完成登录或API key配置。然后Ctrl+a c新建window,运行codex,同样完成配置。

第五步,配置cc switch。把不同端点的配置文件准备好,测试切换是否生效。

整个流程走下来,顺利的话半小时内能搞定。不顺利的话,大部分时间会花在Node.js版本和网络连接上。

4.2 Windows + VS Code的组合方案

如果你主力在Windows,又不想折腾WSL,那VS Code的集成终端也能凑合。VS Code的终端支持多标签,可以一个标签跑Claude Code,一个跑Codex。但VS Code终端没有tmux的detach能力,关掉VS Code窗口,会话就断了。

折中方案是用VS Code的Remote-SSH功能连到一台Ubuntu服务器,然后在远程终端里跑tmux。这样既保留了VS Code的编辑体验,又获得了tmux的会话保持能力。VS Code的终端本身也支持tmux,你可以在VS Code的集成终端里attach到远程的tmux会话。

具体操作:在VS Code里安装Remote-SSH扩展,配置好服务器的SSH连接,连接后在集成终端里执行tmux attach -t ai-work。之后所有操作都在tmux里进行,VS Code只作为显示和编辑的窗口。

这个方案我用了大半年,稳定性很好。唯一需要注意的是VS Code的终端在长时间无操作后可能会断开,但tmux会话在服务器端不受影响,重连后attach回去就行。

4.3 关键参数计算:超时与并发数的取舍

Claude Code和Codex在调用API时都有超时设置。默认超时可能偏短,遇到大段代码生成时容易中断。我一般会把超时调到120秒以上。具体配置位置因工具而异,通常在环境变量或者配置文件里。

并发数方面,如果你同时跑多个AI助手,要注意API的速率限制。Claude Code官方订阅有每分钟请求数限制,Codex接入第三方端点时也要看对方的限制。我的经验是,同时活跃的AI会话不要超过两个,否则容易触发限流,反而降低效率。

tmux的scrollback buffer也值得调大。默认可能只有2000行,翻历史记录时不够用。在tmux.conf里加:

set -g history-limit 50000

这样每个pane能保留5万行历史,排查问题时方便回溯。

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

5.1 安装阶段的典型报错与解决

报错一:error installing 24.21.0: node.js v24.21.0 is not yet released or is not available

这个报错通常出现在用nvm安装一个不存在的版本时。Node.js的版本号是偶数开头为LTS,奇数开头为Current。24.x如果还没发布LTS,nvm就找不到。解决办法是nvm ls-remote看一下有哪些可用版本,选一个实际存在的LTS版本安装。

报错二:codex is ignoring 1 unrecognized configuration setting

Codex在读取配置文件时发现了它不认识的字段。这通常是因为配置文件里混入了其他工具的配置项,或者字段名拼写错误。解决办法是检查配置文件,把不认识的字段删掉。Codex的配置字段以官方文档为准,不要凭感觉写。

报错三:your organization has disabled claude subscription access for claude code

这个报错说明你的账号所属组织关闭了Claude Code的访问权限。如果你用的是个人账号,检查一下订阅状态。如果是组织账号,需要联系管理员开通。这个不是技术问题,是权限问题。

报错四:cc switch local proxy failed while handling codex endpoint /responses

这个报错涉及cc switch的本地代理在处理Codex的/responses端点时失败了。可能的原因是代理配置的转发规则不对,或者目标端点不可达。排查步骤:先确认Codex单独运行时是否正常,如果单独正常,那就是cc switch的代理配置问题。检查代理的转发规则,确保/responses路径被正确映射。

5.2 运行阶段的常见异常

问题:Claude Code在tmux里运行一段时间后无响应

可能的原因是tmux的pane进入了某种阻塞状态。先尝试Ctrl+a q刷新pane编号,或者Ctrl+a r重载配置。如果还不行,detach再attach一次。我遇到过几次,都是因为终端输出太多导致tmux的渲染跟不上,detach再attach就恢复了。

问题:Codex接入DeepSeek后返回结果为空

检查DeepSeek的API key是否有效,以及base URL是否正确。DeepSeek的API端点通常是https://api.deepseek.com,但具体路径要以官方文档为准。另外,DeepSeek的模型名称和OpenAI不同,配置里的model字段要写DeepSeek支持的模型名。

问题:本地LM Studio模型响应极慢

先确认LM Studio里模型的加载状态。如果模型还在加载中,API请求会排队。另外,检查机器的GPU是否被正确使用。LM Studio默认可能用CPU推理,速度会慢很多。在LM Studio的设置里开启GPU加速,速度会有明显提升。

5.3 常见问题速查表

问题现象可能原因排查步骤解决方法
Node.js版本报错版本不存在或过旧node -v查看当前版本用nvm安装LTS版本
Codex配置被忽略配置文件有未知字段检查config.json删除未知字段
Claude Code无响应tmux渲染阻塞detach再attach重载tmux配置
本地模型响应慢CPU推理或模型未加载完查看LM Studio状态开启GPU加速
cc switch代理失败转发规则错误单独测试Codex修正代理配置
API返回空结果key或端点错误检查配置更正key和URL

提示:遇到任何报错,第一步永远是看日志。Claude Code和Codex通常会把详细错误写到stderr或者日志文件里。不要只看终端上那行简短的错误提示,往下翻几行往往能找到真正的原因。

5.4 我踩过的几个坑

第一个坑是Node.js的全局包路径问题。用nvm装的Node.js,全局包在~/.nvm/versions/node/v20.x.x/bin/下面。如果你用sudo npm install -g,包会装到系统路径,和nvm的路径冲突。解决办法是永远不要用sudo npm install -g,nvm环境下不需要sudo。

第二个坑是tmux的默认shell。tmux启动时用的shell可能和你的登录shell不同,导致环境变量不一致。在tmux.conf里加set -g default-shell /bin/bash可以避免这个问题。

第三个坑是cc switch切换后忘记重启Codex进程。前面提过,这里再强调一次。配置文件的变更不会热加载,必须重启进程。

第四个坑是VS Code的终端编码问题。在Windows下,VS Code终端默认可能是GBK编码,导致Claude Code输出的中文乱码。在VS Code设置里把终端编码改成UTF-8可以解决。

6. 进阶玩法:把openrig做成可移植的配置包

6.1 用git管理你的openrig配置

一旦这套环境调稳定了,下一步就是把它变成可移植的。我的做法是创建一个git仓库,把tmux.conf、cc switch的profiles、Node.js的版本声明(.nvmrc)、以及一个安装脚本都放进去。换一台机器时,clone下来跑一遍安装脚本,环境就恢复了。

.nvmrc文件里写20,然后在安装脚本里用nvm use读取这个文件。这样Node.js版本就跟着仓库走,不会出现这台机器20、那台机器18的情况。

安装脚本大概长这样:

#!/bin/bash set -e # 安装nvm if [ ! -d "$HOME/.nvm" ]; then curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash fi # 加载nvm export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # 安装Node.js nvm install nvm alias default $(cat .nvmrc) # 安装全局包 npm install -g @anthropic-ai/claude-code @openai/codex # 配置tmux cp tmux.conf ~/.tmux.conf # 配置cc switch profiles mkdir -p ~/.config/cc-switch/profiles cp profiles/*.json ~/.config/cc-switch/profiles/ echo "openrig environment ready."

这个脚本在Ubuntu和WSL下都能跑。Windows原生环境需要调整路径,但逻辑是一样的。

6.2 多机器同步的注意事项

多机器同步时,最大的问题是API key和敏感配置不能进git。我的做法是把敏感信息放在环境变量里,配置文件里只写占位符。安装脚本运行时从环境变量读取并填充。

比如Codex的配置里写"apiKey": "${CODEX_API_KEY}",然后在shell的profile里export这个变量。这样git仓库里只有模板,没有真实key。

另一个注意事项是不同机器的硬件配置不同。本地模型的配置在一台有GPU的机器上能用,在另一台只有CPU的机器上可能就跑不动。我的做法是把本地模型的配置单独放在一个profile里,不同机器按需切换。

6.3 后续可以扩展的方向

这套openrig环境搭好之后,还可以往几个方向扩展。一是加监控,用tmux的status bar显示当前API的延迟和token消耗。二是加自动化,用tmux的hook在会话创建时自动拉取最新的代码仓库。三是加备份,定期把tmux的scrollback buffer导出到文件,方便事后检索。

我个人最想加的是token消耗的实时显示。Claude Code和Codex的API调用都有token计数,如果能把这些数字汇总到tmux的status bar上,就能随时知道今天用了多少。这个需要写一点脚本去解析API的响应头或者日志,目前还在折腾中。

这套东西说到底就是一个思路:把重复的、易错的、需要记忆的操作,变成一次配置、多次复用的流程。openrig不是什么官方标准,它更像是一种工作习惯的具象化。你完全可以根据自己的需求增删组件,只要核心逻辑是“让终端环境可保持、可切换、可移植”,那就是openrig的精神。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进