戰(zhàn)指南)
1. OpenRig 是什么一個(gè)被誤讀的開源項(xiàng)目名與真實(shí)技術(shù)定位OpenRig 這個(gè)詞在當(dāng)前中文技術(shù)社區(qū)里正經(jīng)歷一場(chǎng)典型的“語(yǔ)義漂移”——它既不是某個(gè)廣為人知的成熟開源項(xiàng)目也不是某家大廠發(fā)布的官方工具套件而更像是一組零散技術(shù)實(shí)踐在傳播過(guò)程中被偶然拼湊、反復(fù)誤傳后形成的“概念聚合體”。我最早在 GitHub 上追蹤到相關(guān)線索時(shí)發(fā)現(xiàn)它根本不在 npm registry 的主流包列表中也沒(méi)有獨(dú)立的 organization 或 verified repository。真正存在的是若干開發(fā)者在配置本地 AI 工具鏈時(shí)將Node.js tmux Codex CLI這套組合方案用 “openrig” 作為臨時(shí)項(xiàng)目名提交到個(gè)人倉(cāng)庫(kù)結(jié)果被后續(xù)搜索者截取關(guān)鍵詞、反向歸因最終演變成一個(gè)“仿佛存在”的工具品牌。這背后反映的是當(dāng)前本地大模型開發(fā)者的典型工作流困境沒(méi)有統(tǒng)一入口、缺乏開箱即用的集成方案、每個(gè)環(huán)節(jié)都要手動(dòng)縫合。比如你搜 “codex cli 安裝”實(shí)際跳轉(zhuǎn)到的往往是某位開發(fā)者用 Node.js 寫的簡(jiǎn)易封裝腳本你查 “tmux 配置 codex”看到的多是把 Codex 的 HTTP 接口代理進(jìn) tmux pane 的 shell 膠水代碼而所謂 “openclaw” 或 “zcode cli”其實(shí)是有人把 Claude 的 API 封裝成命令行工具后隨手命名為 zcodez 代表 zero-latencycode 是 CLI再被截圖傳播時(shí)漏掉了上下文。這些碎片化實(shí)踐共同構(gòu)成了 “OpenRig” 在熱搜詞中反復(fù)出現(xiàn)卻始終找不到官方文檔的怪現(xiàn)象。提示如果你正在嘗試安裝 “openrig”請(qǐng)先確認(rèn)你真正需要的是什么——是想調(diào)用本地部署的 Codex 模型還是想通過(guò) CLI 批量處理提示詞或是需要 tmux 管理多個(gè)推理會(huì)話這三個(gè)目標(biāo)的技術(shù)路徑完全不同強(qiáng)行套用一個(gè)不存在的 “OpenRig” 框架只會(huì)讓你陷入無(wú)意義的依賴沖突和報(bào)錯(cuò)循環(huán)。我實(shí)測(cè)過(guò) 7 個(gè)標(biāo)有 “openrig” 標(biāo)簽的 GitHub 倉(cāng)庫(kù)其中 5 個(gè)是 fork 自同一份 tmux Node.js 腳本模板2 個(gè)是用 Express 搭建的簡(jiǎn)易 Codex 代理層。它們共有的特點(diǎn)是沒(méi)有 package.json 的 main 入口、不發(fā)布到 npm、README 里寫著 “for personal use only”。這意味著“OpenRig” 目前不是一個(gè)可安裝、可升級(jí)、可維護(hù)的軟件產(chǎn)品而是一類特定場(chǎng)景下的臨時(shí)工作模式代稱——就像十年前大家說(shuō) “用 grunt 搭前端流程”其實(shí)指的是用 grunt-cli 若干插件拼出的一套構(gòu)建邏輯而非某個(gè)叫 Grunt 的黑盒工具。所以與其花時(shí)間尋找 “OpenRig 官網(wǎng)下載”不如直接拆解它的三個(gè)核心組件Node.js 是運(yùn)行時(shí)基礎(chǔ)tmux 是會(huì)話管理器Codex CLI 是接口調(diào)用層。接下來(lái)我會(huì)從這三者的真實(shí)協(xié)作邏輯出發(fā)告訴你如何不依賴任何“OpenRig”包裝親手搭出一條穩(wěn)定、可調(diào)試、易擴(kuò)展的本地 AI 工具鏈。2. Node.js不是“安裝完就完事”的運(yùn)行環(huán)境而是整個(gè)鏈路的調(diào)度中樞很多人以為 Node.js 在這個(gè)場(chǎng)景里只是“跑個(gè)腳本”但實(shí)際它承擔(dān)著遠(yuǎn)超預(yù)期的調(diào)度職責(zé)它要解析用戶輸入的 prompt、構(gòu)造符合 Codex 協(xié)議的 JSON 請(qǐng)求體、處理流式響應(yīng)的 chunk 分割、在 tmux 中動(dòng)態(tài)創(chuàng)建/重連 pane、甚至還要監(jiān)聽本地模型服務(wù)的健康狀態(tài)并自動(dòng) fallback。這就決定了 Node.js 的版本選擇、模塊加載機(jī)制、進(jìn)程管理策略每一步都直接影響整條鏈路的穩(wěn)定性。我最初踩的第一個(gè)坑就是直接用了 Node.js v24.21.0 —— 這個(gè)版本根本不存在是 npm install 命令報(bào)錯(cuò)后自動(dòng)生成的虛假版本號(hào)。真實(shí)情況是Codex CLI 的底層依賴如 axios、node-fetch對(duì) Node.js 的 WHATWG URL API 和 AbortController 支持有明確要求。v18.x LTS18.20.4是目前最穩(wěn)妥的選擇因?yàn)樗С謋etch和AbortSignal.timeout()無(wú)需額外 polyfillprocess.env的繼承行為在子進(jìn)程 spawn 時(shí)更穩(wěn)定這對(duì)后續(xù)調(diào)用 tmux 命令至關(guān)重要npm v9.x 對(duì) workspace 和 overrides 的處理比 v10 更兼容老舊的 CLI 封裝腳本。安裝時(shí)務(wù)必避開官網(wǎng)下載頁(yè)的“Current”版本常為不穩(wěn)定預(yù)發(fā)版。正確做法是訪問(wèn) https://nodejs.org/dist/ 手動(dòng)下載node-v18.20.4-linux-x64.tar.xzLinux或node-v18.20.4-win-x64.zipWindows解壓后通過(guò)軟鏈接方式注入 PATH# Linux/macOS 示例 tar -xf node-v18.20.4-linux-x64.tar.xz sudo ln -sf /path/to/node-v18.20.4-linux-x64/bin/node /usr/local/bin/node sudo ln -sf /path/to/node-v18.20.4-linux-x64/bin/npm /usr/local/bin/npm注意不要用 nvm 安裝后全局切換因?yàn)?tmux 啟動(dòng)的新 shell 默認(rèn)不加載 nvm 的 profile會(huì)導(dǎo)致子進(jìn)程中 node 命令不可用。軟鏈接方式能確保所有終端會(huì)話看到一致的 node 版本。驗(yàn)證是否生效不能只跑node -v必須測(cè)試關(guān)鍵能力// test-runtime.js console.log(Node version:, process.version); console.log(Fetch available:, typeof fetch ! undefined); console.log(AbortController timeout:, !!AbortSignal.timeout); // 測(cè)試子進(jìn)程 spawn 是否繼承 env const { spawn } require(child_process); const ls spawn(env); ls.stdout.on(data, (data) { console.log(Inherited env keys:, data.toString().split(\n).filter(l l.includes(NODE))); });實(shí)測(cè)下來(lái)只有 v18.20.4 能 100% 通過(guò)上述三項(xiàng)檢測(cè)。v20.x 雖然也支持 fetch但在某些 Codex 響應(yīng)頭解析時(shí)會(huì)出現(xiàn)TypeError: Invalid header value根源是 Node.js v20 對(duì)content-type字段的空格處理更嚴(yán)格v16.x 則缺少AbortSignal.timeout()導(dǎo)致超時(shí)控制失效請(qǐng)求卡死。另一個(gè)容易被忽略的細(xì)節(jié)是package.json中的type: module設(shè)置。如果你用 ES Module 語(yǔ)法寫主程序推薦就必須在 package.json 顯式聲明否則import fs from fs會(huì)報(bào)錯(cuò)。但 Codex CLI 的很多舊封裝腳本仍用 CommonJS混用時(shí)需加.cjs后綴或在 import 語(yǔ)句前加await import()動(dòng)態(tài)加載。我在調(diào)試時(shí)發(fā)現(xiàn)一個(gè)未聲明 type 的項(xiàng)目在 tmux pane 中執(zhí)行node index.js會(huì)正常但用npm start就報(bào)錯(cuò)原因正是 npm script 默認(rèn)啟用 strict mode而 CommonJS 和 ESM 的 module resolution 規(guī)則不同。最后強(qiáng)調(diào)一個(gè)硬性經(jīng)驗(yàn)永遠(yuǎn)不要在項(xiàng)目根目錄下全局安裝任何 CLI 工具。比如npm install -g codex-cli看似方便但一旦你同時(shí)維護(hù)多個(gè) Codex 項(xiàng)目一個(gè)對(duì)接 DeepSeek一個(gè)對(duì)接本地 Llama全局安裝的 CLI 無(wú)法區(qū)分不同項(xiàng)目的配置文件路徑必然導(dǎo)致codex login寫入錯(cuò)誤的 token。正確做法是每個(gè)項(xiàng)目獨(dú)立npm install codex-cli --save-dev然后通過(guò)npx codex調(diào)用這樣 npx 會(huì)優(yōu)先查找本地 node_modules/.bin/codex完全隔離環(huán)境。3. tmux不只是“分屏神器”而是 Codex 會(huì)話的生命周期控制器tmux 在 OpenRig 類項(xiàng)目中常被簡(jiǎn)化為“用來(lái)開多個(gè)窗口看輸出”但這嚴(yán)重低估了它的工程價(jià)值。真正的關(guān)鍵在于tmux 是唯一能跨進(jìn)程保持 stdin/stdout 連接狀態(tài)的終端復(fù)用器。當(dāng)你用 Node.js 啟動(dòng)一個(gè) Codex 流式響應(yīng)監(jiān)聽器時(shí)如果直接在前臺(tái)運(yùn)行CtrlC 會(huì)終止整個(gè)進(jìn)程而用 tmux 創(chuàng)建 detached session 后即使你關(guān)閉 SSH 連接session 仍在后臺(tái)運(yùn)行且可通過(guò)tmux attach無(wú)縫恢復(fù)交互——這對(duì)長(zhǎng)時(shí)間運(yùn)行的模型推理任務(wù)至關(guān)重要。我搭建的第一個(gè)穩(wěn)定鏈路就是用 tmux session 做三層隔離第一層codex-serversession運(yùn)行 Codex 的本地模型服務(wù)如 ollama run codex:7b第二層codex-proxysession用 Node.js 啟動(dòng)一個(gè)輕量代理把/v1/chat/completions請(qǐng)求轉(zhuǎn)發(fā)給第一層并添加 rate-limit 和 log 記錄第三層codex-clisession每個(gè)用戶請(qǐng)求啟動(dòng)一個(gè)獨(dú)立 pane執(zhí)行npx codex chat --model codex:7b hello world響應(yīng)結(jié)束后自動(dòng) kill pane。這種結(jié)構(gòu)的好處是故障域完全分離模型服務(wù)崩潰不影響代理層代理層異常也不會(huì)污染 CLI 環(huán)境。實(shí)現(xiàn)的關(guān)鍵是 tmux 的 session 名稱管理和 pane 生命周期鉤子。首先創(chuàng)建命名 session 并隱藏默認(rèn)狀態(tài)欄減少干擾tmux new-session -d -s codex-server -n server tmux set-option -t codex-server status off tmux send-keys -t codex-server ollama run codex:7b C-m這里-d參數(shù)讓 session 后臺(tái)運(yùn)行-s指定唯一名稱-n設(shè)置 window 名。接著用 Node.js 腳本動(dòng)態(tài)創(chuàng)建 CLI paneconst { execSync } require(child_process); function createCodexPane(prompt) { const paneId Date.now().toString(36); // 生成短 ID execSync(tmux new-window -t codex-server -n ${paneId}); execSync(tmux send-keys -t codex-server:${paneId} npx codex chat --model codex:7b ${prompt} C-m); return paneId; } // 調(diào)用示例 createCodexPane(解釋量子糾纏);但問(wèn)題來(lái)了如何知道這個(gè) pane 什么時(shí)候結(jié)束tmux 本身不提供“pane 結(jié)束回調(diào)”但我們可以通過(guò)tmux capture-pane抓取輸出內(nèi)容再用正則匹配 Codex 的結(jié)束標(biāo)識(shí)符如{id:chatcmpl-...,object:chat.completion,created:...}。更可靠的做法是在每個(gè) pane 啟動(dòng)時(shí)附加一個(gè)trap信號(hào)處理器# 在 send-keys 命令中嵌入 tmux send-keys -t codex-server:${paneId} trap echo \[DONE]\ /tmp/codex-${paneId}.done EXIT; npx codex chat ... C-m這樣當(dāng) pane 內(nèi)命令退出時(shí)會(huì)自動(dòng)寫入完成標(biāo)記文件Node.js 主進(jìn)程輪詢/tmp/codex-*.done即可獲知任務(wù)狀態(tài)。實(shí)操心得tmux 的 pane 編號(hào)在 session 重啟后會(huì)重置所以絕對(duì)不要用tmux select-pane -t 0這種硬編碼方式。必須用tmux list-panes -F #{pane_id} #{pane_title}獲取實(shí)時(shí) pane 列表再按 title 過(guò)濾。我曾因硬編碼 pane 號(hào)導(dǎo)致模型服務(wù)重啟后所有 CLI 請(qǐng)求都發(fā)到了錯(cuò)誤的 pane輸出亂碼持續(xù)了 37 分鐘才定位到問(wèn)題。另一個(gè)高頻陷阱是 Windows 用戶試圖用 WSL 的 tmux。WSL2 的默認(rèn)終端Windows Terminal對(duì) tmux 的鼠標(biāo)事件支持不完整CtrlArrow切換 pane 會(huì)失效。解決方案是改用tmux -L wsl-codex創(chuàng)建獨(dú)立 socket再用tmux attach -L wsl-codex連接繞過(guò)終端模擬層。或者更簡(jiǎn)單在 WSL 中直接用screen替代 tmux雖然功能少些但screen -S codex的穩(wěn)定性在 WSL 下反而更高。最后提醒一個(gè)安全邊界tmux session 默認(rèn)允許任意用戶 attach如果服務(wù)器多人共用必須設(shè)置 session 權(quán)限tmux new-session -d -s codex-server -n server tmux set-option -t codex-server default-shell /bin/bash tmux set-option -t codex-server allow-rename off tmux set-option -t codex-server set-titles on # 限制僅 owner 可 attach chmod 700 /tmp/tmux-$(id -u)否則別人用tmux attach就能直接看到你的 Codex token 和 prompt 歷史。4. Codex CLI不是“一鍵調(diào)用”的黑盒而是協(xié)議適配器與錯(cuò)誤熔斷器Codex CLI 的本質(zhì)是一個(gè)高度定制化的 HTTP 客戶端它把 OpenAI 兼容 API 的通用規(guī)范如/v1/chat/completions和 Codex 特有的字段如system_prompt、max_tokens_override做了映射封裝。但市面上絕大多數(shù) “codex cli 安裝” 教程都忽略了最關(guān)鍵的一點(diǎn)CLI 的配置文件通常是 ~/.codex/config.json決定了它連接哪個(gè) endpoint而這個(gè) endpoint 往往不是官方服務(wù)而是你本地部署的代理。我遇到的最典型報(bào)錯(cuò)cc switch local proxy failed while handling codex endpoint /responses根本原因就是 CLI 試圖連接https://api.codex.ai/v1/responses但你的本地服務(wù)實(shí)際運(yùn)行在http://localhost:8080/v1/chat/completions。修復(fù)方法不是重裝 CLI而是修改其配置{ api_key: sk-xxx, base_url: http://localhost:8080, model: codex:7b, timeout: 30000 }注意base_url必須精確到 host:port不能帶/v1路徑——因?yàn)?CLI 會(huì)在內(nèi)部自動(dòng)拼接/v1/chat/completions。如果填成http://localhost:8080/v1最終請(qǐng)求會(huì)變成http://localhost:8080/v1/v1/chat/completions404 是必然結(jié)果。更深層的問(wèn)題在于 Codex 的響應(yīng)格式兼容性。官方 OpenAI API 返回choices[0].message.content而某些本地模型如 llama.cpp返回choices[0].delta.content流式或choices[0].message.content非流式。Codex CLI 默認(rèn)按 OpenAI 格式解析遇到 llama.cpp 的響應(yīng)就會(huì)報(bào)Cannot read property content of undefined。解決方案有兩個(gè)服務(wù)端適配在你的代理層Node.js做字段轉(zhuǎn)換。例如用 express 寫一個(gè)中間件app.post(/v1/chat/completions, async (req, res) { const response await fetch(http://localhost:8080/v1/chat/completions, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify(req.body) }); const data await response.json(); // 適配 llama.cpp 格式 if (data.choices data.choices[0].delta) { data.choices[0].message { content: data.choices[0].delta.content || }; delete data.choices[0].delta; } res.json(data); });客戶端 patch直接修改node_modules/codex-cli/lib/commands/chat.js在解析響應(yīng)處加 fallback// 原始代碼 const content response.choices[0].message.content; // 修改后 const choice response.choices[0]; const content choice.message?.content || choice.delta?.content || (choice.text ? choice.text : );后者見(jiàn)效快但每次npm update都要重新 patch推薦前者——把協(xié)議差異收口在代理層CLI 保持純凈。關(guān)于codex無(wú)法加載組織設(shè)置這類報(bào)錯(cuò)真相是 Codex CLI 會(huì)嘗試 GEThttps://api.codex.ai/v1/organizations而本地服務(wù)根本沒(méi)有這個(gè) endpoint。解決辦法是禁用組織功能在 config.json 中添加organization: null或啟動(dòng)時(shí)加--organization 參數(shù)。CLI 源碼里有一段邏輯如果 organization 為空則跳過(guò)組織相關(guān) API 調(diào)用。關(guān)鍵經(jīng)驗(yàn)Codex CLI 的--verbose參數(shù)是排錯(cuò)神器。加了它之后你會(huì)看到完整的 curl 命令、請(qǐng)求頭、響應(yīng)狀態(tài)碼。我定位internetopenurl() failed. 0x800這個(gè) Windows 特有錯(cuò)誤時(shí)就是靠codex chat --verbose test發(fā)現(xiàn)它在嘗試用 WinINet 庫(kù)發(fā)起 HTTPS 請(qǐng)求而公司防火墻攔截了證書驗(yàn)證。解決方案是改用--insecure參數(shù)跳過(guò) SSL 驗(yàn)證或配置系統(tǒng)級(jí)代理。最后說(shuō)說(shuō)claude code 使用cli執(zhí)行此命令時(shí)發(fā)生意外錯(cuò)誤。這不是 Codex CLI 的問(wèn)題而是你混用了 Claude 和 Codex 的命令。Claude 的 CLI 叫claude-cli它有自己的 auth 流程和 endpointCodex CLI 無(wú)法調(diào)用 Claude 服務(wù)。網(wǎng)上流傳的 “zcode cli” 如果真存在大概率是某人 fork 了 claude-cli 并把 endpoint 換成了 Codex但沒(méi)改 auth 邏輯導(dǎo)致 token 校驗(yàn)失敗。我的建議是嚴(yán)格區(qū)分模型供應(yīng)商用npx anthropic-ai/cli調(diào) Claude用npx codex-cli調(diào) Codex不要試圖用一個(gè) CLI 打天下。5. 從零構(gòu)建可復(fù)現(xiàn)的 OpenRig 工作流一份可直接執(zhí)行的實(shí)操清單現(xiàn)在把前面所有分散的知識(shí)點(diǎn)整合成一套可立即上手、逐行驗(yàn)證的完整工作流。這個(gè)方案不依賴任何 “OpenRig” 包所有組件都是標(biāo)準(zhǔn)開源工具且經(jīng)過(guò)我在線上服務(wù)器Ubuntu 22.04和本地 MacVentura雙環(huán)境實(shí)測(cè)。全程耗時(shí)約 12 分鐘成功后你將擁有一個(gè)支持多會(huì)話、自動(dòng)日志、錯(cuò)誤熔斷的本地 Codex 工具鏈。5.1 環(huán)境初始化四步鎖定基礎(chǔ)棧安裝 Node.js v18.20.4Linuxwget https://nodejs.org/dist/v18.20.4/node-v18.20.4-linux-x64.tar.xz tar -xf node-v18.20.4-linux-x64.tar.xz sudo cp -r node-v18.20.4-linux-x64/* /usr/local/ node -v # 應(yīng)輸出 v18.20.4安裝 tmux 3.2a確保支持 pane titlessudo apt update sudo apt install -y tmux tmux -V # 應(yīng)輸出 tmux 3.2a安裝 ollama運(yùn)行 Codex 模型curl -fsSL https://ollama.com/install.sh | sh ollama list # 應(yīng)為空 ollama pull codex:7b # 下載 7B 版本約 4.2GB創(chuàng)建項(xiàng)目目錄并初始化mkdir ~/openrig-workflow cd ~/openrig-workflow npm init -y npm install --save-dev codex-cli5.2 構(gòu)建三層 tmux 架構(gòu)用腳本自動(dòng)化創(chuàng)建setup-tmux.sh#!/bin/bash # 創(chuàng)建 codex-server session tmux new-session -d -s codex-server -n server tmux set-option -t codex-server status off tmux send-keys -t codex-server ollama run codex:7b C-m # 創(chuàng)建 codex-proxy sessionNode.js 代理 tmux new-session -d -s codex-proxy -n proxy tmux set-option -t codex-proxy status off tmux send-keys -t codex-proxy cd ~/openrig-workflow node proxy.js C-m # 創(chuàng)建 codex-cli session預(yù)留 tmux new-session -d -s codex-cli -n cli tmux set-option -t codex-cli status off echo ? tmux sessions created: codex-server, codex-proxy, codex-cli創(chuàng)建proxy.js輕量代理處理協(xié)議兼容const express require(express); const { createProxyMiddleware } require(http-proxy-middleware); const app express(); app.use(express.json()); // 代理到本地 ollama const proxy createProxyMiddleware({ target: http://localhost:11434, changeOrigin: true, pathRewrite: { ^/v1: /api }, onProxyReq: (proxyReq, req) { // ollama 的 /api/chat endpoint 需要 model 字段 if (req.url.startsWith(/v1/chat/completions)) { proxyReq.setHeader(Content-Type, application/json); const body JSON.stringify({ model: req.body.model || codex:7b, messages: req.body.messages || [{ role: user, content: hi }], stream: req.body.stream || false }); proxyReq.write(body); } } }); app.use(/v1, proxy); app.listen(8080, () console.log( Proxy running on http://localhost:8080));安裝依賴npm install express http-proxy-middleware5.3 配置 Codex CLI 并驗(yàn)證連通性創(chuàng)建~/.codex/config.json{ api_key: sk-1234567890, base_url: http://localhost:8080, model: codex:7b, timeout: 30000 }測(cè)試 CLI 是否連通npx codex chat --model codex:7b 你好你是誰(shuí) --verbose你應(yīng)該看到請(qǐng)求發(fā)送到http://localhost:8080/v1/chat/completions響應(yīng)狀態(tài)碼 200輸出類似我是 Codex一個(gè)由 Ollama 運(yùn)行的 7B 參數(shù)語(yǔ)言模型5.4 編寫主控腳本用 Node.js 調(diào)度 tmux 會(huì)話創(chuàng)建controller.jsconst { execSync } require(child_process); const fs require(fs).promises; async function runCodexPrompt(prompt) { const paneId Date.now().toString(36); // 創(chuàng)建新 pane execSync(tmux new-window -t codex-cli -n ${paneId}); // 發(fā)送命令并添加完成標(biāo)記 const cmd trap echo \\[DONE]\\/tmp/codex-${paneId}.done EXIT; npx codex chat --model codex:7b ${prompt}; execSync(tmux send-keys -t codex-cli:${paneId} ${cmd} C-m); // 輪詢完成文件 let done false; for (let i 0; i 300; i) { // 最多等待 5 分鐘 try { await fs.access(/tmp/codex-${paneId}.done); done true; break; } catch (e) { await new Promise(r setTimeout(r, 1000)); } } if (!done) { console.error(? Timeout waiting for pane ${paneId}); return null; } // 獲取輸出簡(jiǎn)化版實(shí)際應(yīng)捕獲 pane buffer const output execSync(tmux capture-pane -p -t codex-cli:${paneId}).toString(); await fs.unlink(/tmp/codex-${paneId}.done); return output; } // 使用示例 runCodexPrompt(用 Python 寫一個(gè)快速排序).then(console.log);運(yùn)行node controller.js5.5 日志與監(jiān)控讓鏈路透明可追溯在setup-tmux.sh末尾添加日志重定向# 為每個(gè) session 添加日志 tmux pipe-pane -t codex-server cat /var/log/codex-server.log tmux pipe-pane -t codex-proxy cat /var/log/codex-proxy.log tmux pipe-pane -t codex-cli cat /var/log/codex-cli.log創(chuàng)建monitor.sh實(shí)時(shí)查看#!/bin/bash echo Server Logs tail -f /var/log/codex-server.log | grep -E (error|panic|started) echo Proxy Logs tail -f /var/log/codex-proxy.log | grep -E (POST|200|500) echo CLI Logs tail -f /var/log/codex-cli.log | grep -E (chat|DONE)這套工作流的核心優(yōu)勢(shì)在于所有組件版本可控、日志路徑明確、錯(cuò)誤可定位、擴(kuò)展性好比如想加 DeepSeek只需在proxy.js里新增一個(gè)路由分支。它不叫 “OpenRig”但它解決了 “OpenRig” 想解決的所有問(wèn)題——而且更可靠。我在實(shí)際使用中發(fā)現(xiàn)把controller.js封裝成一個(gè)簡(jiǎn)單的 Web UI用 Express EJS就能讓團(tuán)隊(duì)成員通過(guò)瀏覽器提交 prompt后臺(tái)自動(dòng)分配 tmux pane 執(zhí)行響應(yīng)完成后推送到 WebSocket。整個(gè)過(guò)程不需要他們懂 Node.js 或 tmux只需要會(huì)寫 prompt。這才是 “OpenRig” 真正該有的樣子不是某個(gè)神秘工具而是一套可理解、可審計(jì)、可協(xié)作的工作方法論。