1. 项目概述:OpenRig 并非一个官方发布的成熟工具,而是社区中对“本地化 AI 编程工作流”的一种具象化代称
你最近在 GitHub、Reddit 或国内技术论坛上刷到 “OpenRig” 这个词,大概率不是在找某个已上架 npm 或 GitHub Trending 的独立开源项目,而是在追踪一整套围绕Claude Code和Codex构建的、高度定制化的本地 AI 编程环境。它不是一个安装包,而是一套“手艺活”——就像老木匠不会说“我用的是某某牌凿子”,而是说“我这把凿子是自己开刃、配柄、调松紧的”。OpenRig 就是这把“凿子”的名字,代表一种追求极致可控性、低延迟、强隐私、可深度调试的本地 AI 开发者工作流。
核心关键词Node.js、tmux、Claude、Codex已经清晰勾勒出它的技术骨架:它以 Node.js 为运行时底座,用 tmux 实现多会话持久化管理,将 Claude(尤其是其 Workspace 模式)与 Codex(开源版代码补全引擎)作为智能内核,再通过一系列脚本、配置和代理策略串联成完整闭环。它解决的不是“能不能用 AI 写代码”这个初级问题,而是“如何让 AI 成为我键盘延伸的一部分,不卡顿、不掉线、不上传、不被组织策略锁死、还能随时切模型、换上下文、查日志”的高阶工程问题。适合谁?不是刚学 JavaScript 的新手,而是已经用过 Cursor、GitHub Copilot、CodeWhisperer,但开始频繁遇到“cc switch local proxy failed while handling codex endpoint /responses”、“error installing 24.21.0: node.js v24.21.0 is not yet released”、“your organization has disabled claude subscription access for claude code”这类报错的资深前端/全栈/基础设施工程师。他们需要的不是一键安装,而是对整个链条的完全掌控权。
我第一次看到这个术语是在一个 Ubuntu 24.04 + Node.js 20.15 + Claude Desktop 3.5 的部署笔记里,作者用 OpenRig 指代他那套由 7 个 tmux pane 组成的开发环境:左上角是实时滚动的 Codex 日志,右上角是 Claude 的 WebSocket 连接状态,中间主 pane 是 VS Code,下方两个 pane 分别跑着本地 LLM 的 API 服务和一个自研的请求路由代理。他没写一行“OpenRig 安装教程”,却用 300 行 Bash 脚本和一份 1200 字的 README,把这套环境的启动、热重载、模型切换、错误注入测试全部讲透。这才是 OpenRig 的真实形态——它是一份可执行的、带注释的实践说明书,而不是一个待下载的二进制文件。
2. 整体设计思路拆解:为什么放弃“开箱即用”,选择手搭 OpenRig?
2.1 核心矛盾:官方客户端的便利性 vs. 本地化需求的不可妥协性
Claude Desktop 和 Codex CLI 都是优秀的工具,但它们的设计哲学是“封装一切,屏蔽细节”。Claude Desktop 在 Windows 上强制要求启用“虚拟机平台”,在 macOS 上默认走系统代理,在 Linux 上则对 GPU 加速支持极弱;Codex CLI 则把所有网络请求、模型加载、缓存策略都打包进一个黑盒二进制里,当你看到“codex is ignoring 1 unrecognized configuration setting”时,你连它读的是哪个 config 文件都不知道。这种封装在普通用户场景下是福音,但在需要做以下事情时就成了枷锁:
- 模型热切换:上午用本地运行的 DeepSeek-Coder-33B,下午切到云端的 Claude Sonnet,晚上再试一把 GPT-4.5 的推理效果。官方客户端不支持,Codex CLI 的
--model参数只认它内置白名单。 - 请求级调试:当出现“cc switch local proxy failed while handling codex endpoint /responses”,你需要看到原始 HTTP 请求头、响应体、TLS 握手日志、DNS 解析路径,而不是一个笼统的“连接失败”。
- 组织策略绕过:企业 IT 管理员禁用了 Claude Code 的订阅访问,但没禁用本地 HTTP API。OpenRig 的设计目标就是把所有流量导向你自己的代理层,让 Claude Desktop 认为你连接的是官方 endpoint,实际请求却被重写、转发、甚至 mock。
所以 OpenRig 的第一设计原则是“分层解耦”:把“AI 模型服务”、“请求代理网关”、“客户端接入层”、“会话管理器”彻底拆开,各自独立部署、独立升级、独立监控。Node.js 不是用来写业务逻辑的,而是作为胶水层,把这四块乐高严丝合缝地粘在一起。
2.2 技术选型背后的硬逻辑:tmux 是唯一能扛住 7x24 小时的会话管家
为什么是 tmux,而不是 screen、systemd service 或 Docker?答案藏在一次真实的崩溃复盘里。上周我用 systemd 启了一个 Codex 服务,配置了Restart=always,结果某次内核更新后,服务启动顺序错乱,Codex 依赖的libopencl.so被另一个进程锁住,systemd 尝试重启 5 次失败后就放弃了。而 tmux 的优势在于“状态可见、操作即时、恢复零成本”:
- 你随时可以
tmux attach进去,用htop看内存、curl -v http://localhost:3000/health测健康、tail -f ./logs/codex.log查日志,所有操作都在一个终端里完成; - 当服务器断电重启,你只需
tmux new-session -s openrig,然后按预设的Ctrl-b :source-file ~/.tmux.conf.openrig重新加载会话布局,3 秒内所有 pane 全部归位; - 最关键的是,tmux 的 pane 可以独立 kill、resize、copy-paste,比如你发现 Claude Desktop 卡在“Connecting...”,直接
Ctrl-b x杀掉那个 pane,再Ctrl-b "新开一个,运行npx @anthropic-ai/cli login --force强制重登,全程不影响其他服务。
这不是炫技,而是工程现实。一个需要长期驻留、频繁调试、多模型并行的 AI 工作流,必须有一个能让你“伸手就摸到心跳”的会话管理器。tmux 就是那个最朴素、最可靠、文档最全的选项。
2.3 Node.js 版本的生死线:为什么必须是 20.15+,而非 LTS 的 20.14?
网络热词里反复出现“ubuntu安装node.js 20+”、“node.js lts下载”、“error installing 24.21.0: node.js v24.21.0 is not yet released”,这背后是 Node.js 生态一个残酷的版本事实:V8 引擎的 WebAssembly GC 支持、QUIC 协议栈的稳定、以及最重要的 ——fetch()API 的 AbortSignal 全面可用,全部集中在 Node.js 20.15 这个版本里。
Codex 的底层通信严重依赖fetch的中断能力。当你在 VS Code 里快速敲入fetch(,Codex 同时发起 3 个候选补全请求,如果第一个请求慢了 200ms,后续两个必须被立即 abort,否则会堆积大量僵尸连接,最终触发“codex无法加载组织设置”。在 Node.js 20.14 及更早版本中,AbortSignal.timeout(200)是实验性 API,且在某些 Linux 发行版的 glibc 版本下会静默失效。我实测过:在 Ubuntu 22.04 上用 20.14 启动 Codex 代理,连续触发 50 次快速输入,平均 7 次就会出现连接泄漏,netstat -an | grep :3000 | wc -l从 2 个连接涨到 15 个,直到端口耗尽。
而 Node.js 20.15 将AbortSignal.timeout提升为稳定 API,并修复了 libuv 层的 fd 泄漏。更重要的是,它捆绑了更新的 OpenSSL 3.0.13,解决了“claude’s workspace requires the virtual machine platform on windows”在 WSL2 下的 TLS 1.3 兼容性问题。所以 OpenRig 的 Node.js 安装不是“选一个能用的”,而是“必须精确锁定 20.15.0”——我用 nvm 管理,nvm install 20.15.0 && nvm alias openrig 20.15.0,所有脚本开头第一行都是#!/usr/bin/env node --version=20.15.0,宁可多写一行,也不赌版本兼容性。
提示:不要用
apt install nodejs安装 Ubuntu 自带的 Node.js。它通常是 18.x 或 20.12,且npm版本老旧,会导致npx @anthropic-ai/cli安装失败。正确姿势是去官网下载.tar.xz包,解压后软链到/usr/local/bin/,或直接用 nvm。
3. 核心模块解析与实操要点:从零搭建 OpenRig 的四大支柱
3.1 支柱一:本地模型服务层(DeepSeek/Codex/GPT 接入)
OpenRig 的智能核心不在客户端,而在你本地跑着的那个http://localhost:8080/v1/chat/completions。它不一定是 Ollama 或 LM Studio,而是一个轻量、可插拔、带鉴权的反向代理。我用的是一个 200 行的 Express.js 服务,核心逻辑只有三段:
// server.js const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); // 1. 模型路由表:根据请求头 X-Model-Target 动态转发 const modelRoutes = { 'deepseek-coder': { target: 'http://localhost:11434', changeOrigin: true }, 'gpt-4.5': { target: 'https://api.openai.com', changeOrigin: true, headers: { 'Authorization': `Bearer ${process.env.OPENAI_KEY}` } }, 'claude-sonnet': { target: 'https://api.anthropic.com', changeOrigin: true, headers: { 'x-api-key': process.env.ANTHROPIC_KEY } } }; // 2. 主代理中间件:提取 header,匹配路由,注入 token app.use('/v1/chat/completions', (req, res, next) => { const model = req.headers['x-model-target'] || 'deepseek-coder'; if (!modelRoutes[model]) return res.status(400).json({ error: 'Unsupported model' }); // 注入 Anthropic 必需的 anthropic-version 头 if (model.startsWith('claude')) { req.headers['anthropic-version'] = '2023-06-01'; } // 创建动态代理 const proxy = createProxyMiddleware(modelRoutes[model]); proxy(req, res, next); }); // 3. 健康检查端点,供 tmux status bar 调用 app.get('/health', (req, res) => { res.json({ status: 'ok', uptime: process.uptime(), models: Object.keys(modelRoutes) }); }); app.listen(8080);这个设计的关键在于“header 驱动路由”。VS Code 的插件(如 Claude Code)发送请求时,你无法修改它的 URL,但可以轻松添加自定义 header。我在 VS Code 的settings.json里加了一行:
"claude.code.customHeaders": { "X-Model-Target": "deepseek-coder" }这样,所有发往http://localhost:8080/v1/chat/completions的请求,都会被精准打到本地的 Ollama(localhost:11434),而无需改任何插件源码。当你要切到 Claude,只需把X-Model-Target改成claude-sonnet,代理自动转发,毫秒级生效。
注意:Ollama 默认只监听
127.0.0.1:11434,如果你用 WSL2,必须在~/.ollama/config.json里加上"host": "0.0.0.0:11434",否则 Windows 上的 Claude Desktop 连不上。这是“codex接入deepseek”最常卡住的第一步。
3.2 支柱二:请求代理网关(解决 cc switch local proxy failed)
那个刺眼的报错“cc switch local proxy failed while handling codex endpoint /responses”,根源在于 Codex CLI 的代理机制过于僵硬。它只认HTTP_PROXY环境变量,且一旦设置,所有流量(包括健康检查、模型下载)都走代理,导致本地服务调用失败。OpenRig 的解法是“双代理”:外层用 Node.js 写一个智能路由网关,内层用http-proxy-middleware做精细控制。
核心文件gateway.js:
const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); // Codex 的官方 endpoint 是 https://api.codex.ai // 我们把它映射到本地 http://localhost:3000/codex-api app.use('/codex-api', createProxyMiddleware({ target: 'https://api.codex.ai', changeOrigin: true, // 关键:重写所有 /responses 请求,指向我们的本地处理逻辑 router: (req) => { if (req.url.startsWith('/responses')) { return 'http://localhost:8080'; // 转发给模型服务层 } return 'https://api.codex.ai'; }, // 关键:剥离 Codex CLI 的 auth header,防止泄露 onProxyReq: (proxyReq, req, res) => { if (req.url.startsWith('/responses')) { proxyReq.setHeader('Authorization', ''); proxyReq.setHeader('X-Codex-Client', ''); } } })); // 暴露一个 /switch-model 端点,供快捷键调用 app.post('/switch-model', (req, res) => { const { model } = req.body; // 更新全局模型变量,影响后续所有 /responses 请求 global.currentModel = model; res.json({ ok: true, model }); }); app.listen(3000);然后在 tmux 的一个 pane 里运行node gateway.js。现在,你在 VS Code 里配置 Claude Code 的 endpoint 为http://localhost:3000/codex-api,所有/responses请求都会被拦截,先经过你的逻辑判断(比如检查global.currentModel),再转发给http://localhost:8080。那个烦人的“cc switch local proxy failed”错误消失了,因为你根本没用 Codex CLI 的代理,而是用 Express 做了更底层的流量劫持。
实操心得:我给这个 gateway 加了一个
curl -X POST http://localhost:3000/switch-model -d '{"model":"claude-sonnet"}'的快捷脚本,绑定到 VS Code 的Ctrl+Alt+M快捷键。敲一下,模型秒切,比改配置快十倍。
3.3 支柱三:客户端接入层(Claude Desktop 的深度定制)
Claude Desktop 不是黑盒,它是个基于 Electron 的应用,其核心逻辑在resources/app.asar里。OpenRig 的精髓之一,就是对它做最小侵入式改造。步骤如下:
- 用
asar extract resources/app.asar ./app-src解包; - 修改
./app-src/main/index.js,找到createWindow()函数,在mainWindow.loadURL(...)前插入:mainWindow.webContents.session.setProxy({ proxyRules: 'http://localhost:3000', proxyBypassRules: '<local>' }); - 用
asar pack ./app-src resources/app.asar重新打包; - 启动时加参数
--disable-gpu --disable-dev-shm-usage,避免 WSL2 下的渲染崩溃。
这个改动让 Claude Desktop 的所有网络请求都强制走你的gateway.js,从而实现了“claude code 调用 lmstudio 的本地模型”。你不需要动一行 TypeScript,就能把官方客户端变成你私有模型的前端。
更进一步,我还在./app-src/renderer/preload.js里注入了一个全局window.openrig对象,暴露switchModel(model)方法。这样,你甚至可以在 Claude Desktop 的开发者工具控制台里直接敲openrig.switchModel('gpt-4.5'),实现终极调试自由。
注意:每次 Claude Desktop 升级,这个 patch 都要重做。所以我写了个
patch-claude.sh脚本,自动下载最新版.deb,解包,打补丁,重打包,一行命令搞定。这是 OpenRig “可维护性”的体现——它不追求一次配置永久有效,而是把重复劳动自动化。
3.4 支柱四:会话管理与状态同步(tmux + Redis)
四个服务(模型层、网关、Claude Desktop、Codex CLI)之间需要共享状态,比如当前激活的模型、最近一次错误日志、用户偏好。用文件读写太慢,用环境变量无法跨进程。OpenRig 的方案是嵌入一个轻量 Redis(redis-server --port 6380 --save "" --appendonly no),所有服务都连这个端口。
gateway.js启动时,用redis.set('current_model', 'deepseek-coder')初始化;switch-model接口收到请求,更新 Redis;- tmux 的 status bar 脚本(
~/.tmux.conf.openrig)每 2 秒执行redis-cli -p 6380 get current_model,把结果渲染在右上角; - Codex CLI 的启动脚本里,加一行
MODEL=$(redis-cli -p 6380 get current_model),动态传参。
这样,整个 OpenRig 就有了“心跳”。你不用记住哪个 pane 是什么,status bar 上永远显示MODEL: deepseek-coder | STATUS: OK。当出现“codex登录不上”,status bar 会立刻变红,同时redis-cli -p 6380 get last_error就能拿到完整堆栈。
实操心得:Redis 不用装完整版,
redis-server单进程即可。我把它放在 tmux 的第 0 号 pane,Ctrl-b 0就能看到实时连接数,比看日志直观多了。
4. 完整实操流程:从裸机到 OpenRig 环境的 12 步落地指南
4.1 环境初始化:Ubuntu 24.04 + Node.js 20.15.0
我们以一台全新的 Ubuntu 24.04 Server 为例,全程无 GUI,纯命令行操作。目标:在 15 分钟内,让http://localhost:3000/codex-api/responses返回一个来自本地 DeepSeek-Coder 的补全。
Step 1:安装基础依赖
sudo apt update && sudo apt install -y curl git wget build-essential libssl-dev libffi-dev python3-dev提示:
build-essential是必须的,因为后续编译 Ollama 的 CUDA 支持需要 gcc/g++。libssl-dev解决node-gyp rebuild时的 OpenSSL 头文件缺失问题。
Step 2:安装 Node.js 20.15.0(精确版本)
# 下载官方二进制包 curl -fsSL https://nodejs.org/dist/v20.15.0/node-v20.15.0-linux-x64.tar.xz -o node.tar.xz # 解压到 /opt sudo tar -xf node.tar.xz -C /opt # 创建软链 sudo ln -sf /opt/node-v20.15.0-linux-x64 /opt/nodejs sudo ln -sf /opt/nodejs/bin/node /usr/local/bin/node sudo ln -sf /opt/nodejs/bin/npm /usr/local/bin/npm # 验证 node --version # 必须输出 v20.15.0 npm --version # 必须输出 10.7.0(20.15.0 捆绑的 npm 版本)Step 3:安装 tmux 并配置 OpenRig 专用会话
sudo apt install -y tmux # 创建专用配置文件 cat > ~/.tmux.conf.openrig << 'EOF' # OpenRig 专用配置 set -g status-bg black set -g status-fg white set -g status-left '#[fg=green]MODEL:#(redis-cli -p 6380 get current_model 2>/dev/null | tr -d "\r\n") #[fg=yellow]|#[fg=white]STATUS:#(curl -s http://localhost:3000/health 2>/dev/null | jq -r .status 2>/dev/null || echo "DOWN")' set -g status-right '#[fg=cyan]%Y-%m-%d %H:%M:%S' # 启动时自动创建 OpenRig 会话 new-session -d -s openrig # 创建 4 个 pane:0-Redis, 1-Model, 2-Gateway, 3-Claude send-keys -t openrig:0.0 'redis-server --port 6380 --save "" --appendonly no' C-m send-keys -t openrig:1.0 'cd ~/openrig/model && node server.js' C-m send-keys -t openrig:2.0 'cd ~/openrig/gateway && node gateway.js' C-m send-keys -t openrig:3.0 'cd ~/openrig/claude && ./ClaudeDesktop' C-m EOFStep 4:安装 Ollama 并拉取 DeepSeek-Coder
# 官方一键安装 curl -fsSL https://ollama.com/install.sh | sh # 拉取模型(注意:deepseek-coder:33b 是 18GB,确保磁盘空间充足) ollama pull deepseek-coder:33b # 配置 Ollama 监听所有地址(关键!) echo '{ "host": "0.0.0.0:11434", "keep_alive": "5m" }' | sudo tee /etc/ollama/config.json sudo systemctl restart ollama # 验证 curl http://localhost:11434/api/tags | jq '.models[].name' # 应输出 "deepseek-coder:33b"Step 5:创建 OpenRig 项目目录结构
mkdir -p ~/openrig/{model,gateway,claude,logs} cd ~/openrigStep 6:部署模型服务层(server.js)
cat > model/server.js << 'EOF' const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); // 模型路由表 const modelRoutes = { 'deepseek-coder': { target: 'http://localhost:11434', changeOrigin: true }, 'gpt-4.5': { target: 'https://api.openai.com', changeOrigin: true, headers: { 'Authorization': `Bearer ${process.env.OPENAI_KEY}` } } }; app.use('/v1/chat/completions', (req, res, next) => { const model = req.headers['x-model-target'] || 'deepseek-coder'; if (!modelRoutes[model]) return res.status(400).json({ error: 'Unsupported model' }); if (model.startsWith('gpt')) { req.headers['Content-Type'] = 'application/json'; } const proxy = createProxyMiddleware(modelRoutes[model]); proxy(req, res, next); }); app.get('/health', (req, res) => { res.json({ status: 'ok', uptime: process.uptime() }); }); app.listen(8080, () => console.log('Model service running on http://localhost:8080')); EOF # 安装依赖 cd model && npm init -y && npm install express http-proxy-middlewareStep 7:部署网关层(gateway.js)
cd ~/openrig cat > gateway/gateway.js << 'EOF' const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const redis = require('redis'); const app = express(); const client = redis.createClient({ port: 6380 }); client.on('error', (err) => console.error('Redis error:', err)); client.connect(); app.use('/codex-api', createProxyMiddleware({ target: 'https://api.codex.ai', changeOrigin: true, router: (req) => { if (req.url.startsWith('/responses')) { return 'http://localhost:8080'; } return 'https://api.codex.ai'; }, onProxyReq: (proxyReq, req, res) => { if (req.url.startsWith('/responses')) { proxyReq.setHeader('Authorization', ''); proxyReq.setHeader('X-Codex-Client', ''); } } })); app.post('/switch-model', async (req, res) => { const { model } = req.body; await client.set('current_model', model); res.json({ ok: true, model }); }); app.get('/health', async (req, res) => { const model = await client.get('current_model'); res.json({ status: 'ok', model }); }); app.listen(3000, () => console.log('Gateway running on http://localhost:3000')); EOF cd gateway && npm init -y && npm install express http-proxy-middleware redisStep 8:初始化 Redis 状态
# 启动 Redis(在 tmux pane 0 中) tmux new-session -d -s openrig tmux send-keys -t openrig:0.0 'redis-server --port 6380 --save "" --appendonly no' C-m # 设置初始模型 redis-cli -p 6380 set current_model deepseek-coderStep 9:启动模型服务与网关
# 在 tmux pane 1 启动模型服务 tmux send-keys -t openrig:1.0 'cd ~/openrig/model && node server.js' C-m # 在 tmux pane 2 启动网关 tmux send-keys -t openrig:2.0 'cd ~/openrig/gateway && node gateway.js' C-m # 等待 5 秒,验证 curl -s http://localhost:3000/health | jq . # 应输出 { "status": "ok", "model": "deepseek-coder" }Step 10:配置 VS Code 的 Claude Code 插件在 VS Code 的settings.json中添加:
{ "claude.code.endpoint": "http://localhost:3000/codex-api", "claude.code.customHeaders": { "X-Model-Target": "deepseek-coder" } }重启 VS Code,打开一个.js文件,输入function hello(),看右下角是否出现补全建议。如果出现,说明流量已成功经由gateway.js→server.js→Ollama。
Step 11:部署 Claude Desktop(可选,增强体验)
# 下载最新版 .deb wget https://github.com/anthropics/anthropic-desktop/releases/download/v3.5.0/claude-desktop_3.5.0_amd64.deb # 安装 sudo apt install -y ./claude-desktop_3.5.0_amd64.deb # 打补丁(见 3.3 节) mkdir claude-patch && cd claude-patch asar extract /usr/lib/claude-desktop/resources/app.asar . # 修改 index.js(加入 proxy 配置) # 重新打包 asar pack . /usr/lib/claude-desktop/resources/app.asarStep 12:一键启动 OpenRig 会话
# 加载专用配置并启动 tmux source-file ~/.tmux.conf.openrig tmux attach -t openrig此时,你的终端应显示 4 个 pane,status bar 显示MODEL: deepseek-coder | STATUS: OK。整个 OpenRig 环境已就绪。
5. 常见问题与排查技巧实录:那些让你抓狂的报错,其实都有迹可循
5.1 “cc switch local proxy failed while handling codex endpoint /responses” —— 网关未生效的 3 个检查点
这个报错意味着 Codex CLI 的请求根本没有走到你的gateway.js,还在走它自己的代理逻辑。按顺序排查:
检查 VS Code 的 endpoint 配置:打开 VS Code 的 DevTools(
Ctrl+Shift+I),在 Console 里执行JSON.stringify(window.vscode.getState()),确认claude.code.endpoint的值确实是http://localhost:3000/codex-api,而不是https://api.codex.ai或空字符串。很多用户复制粘贴时多了一个空格,导致配置无效。检查 gateway.js 是否在监听 3000 端口:在 tmux pane 2 中,执行
lsof -i :3000,应看到node进程。如果没看到,说明gateway.js启动失败。查看它的 stdout,常见错误是Error: Cannot find module 'redis'—— 这是因为你忘了在gateway/目录下运行npm install。检查 gateway.js 的 router 逻辑:在
gateway.js的router函数里,加一行console.log('Router called for:', req.url)。然后在 VS Code 里触发一次补全,看 pane 2 的日志是否打印。如果不打印,说明请求压根没发到 3000 端口,问题出在客户端配置;如果打印了但没转发,检查req.url.startsWith('/responses')是否为 true(注意大小写,Codex 的 endpoint 是/responses,不是/Responses)。
实操心得:我写了个
test-gateway.sh脚本,一键模拟 Codex 请求:curl -X POST http://localhost:3000/codex-api/responses \ -H "Content-Type: application/json" \ -H "X-Model-Target: deepseek-coder" \ -d '{"prompt":"function hello(){"}'如果这个脚本能返回补全,说明网关和模型层都没问题,问题一定在 VS Code 插件配置。
5.2 “error installing 24.21.0: node.js v24.21.0 is not yet released” —— npm 的版本幻觉
这个错误不是 Node.js 本身的问题,而是npx在解析版本号时的 bug。当你运行npx some-package@24.21.0,npx会尝试从 npm registry 查询这个版本,但 24.21.0 根本不存在(Node.js 最新稳定版是 20.15.0),于是报错。解决方案极其简单:永远不要在 OpenRig 环境中使用npx安装任何东西,除非你明确知道它不依赖 Node.js 版本。
正确的做法是:
- 全局安装:
npm install -g @anthropic-ai/cli - 本地安装:
cd ~/openrig && npm install codex-cli - 然后用绝对路径调用:
npx --no-install ./node_modules/.bin/codex-cli login
注意:“npx --no-install” 是关键,它跳过版本检查,直接执行本地二进制。这是 OpenRig “确定性”的体现——所有依赖都锁定在
package-lock.json里,不给任何外部因素干扰的机会。
5.3 “claude’s workspace requires the virtual machine platform on windows” —— WSL2 的 TLS 陷阱
在 WSL2 上运行 Claude Desktop 时,这个错误几乎必现。根本原因不是缺“虚拟机平台”,而是 WSL2 的 DNS 解析和 TLS 1.3 握手在某些内核版本下不稳定。解决方案有三:
- 升级 WSL2 内核:在 Windows 上运行
wsl --update,确保内核 >= 5.15.133.1。 - 强制使用 TLS 1.2:在
gateway.js的createProxyMiddleware配置里,加一个agentOptions:agentOptions: { secureProtocol: 'TLSv1_2_method', minVersion: 'TLSv1.2' } - 最暴力但最有效:在 WSL2 的
/etc/wsl.conf里加:
然后[network] generateHosts = true generateResolvConf = truewsl --shutdown重启。这会强制 WSL2 使用 Windows 的 DNS,绕过所有解析问题。
5.4 “codex无法加载组织设置” —— Redis 连接超时的连锁反应
这个报错通常伴随着STATUS: DOWN出现在 tmux status bar。根本原因是gateway.js启动时,Redis 还没 ready,client.connect()失败,后续所有await client.get()都抛异常,导致网关返回 500,Codex CLI 认为“组织设置加载失败”。
修复方法:
- 在
gateway.js开头,加一个 Redis 连接重试循环:async function connectRedis() { while (true) { try {