一个基于 Node.js 的 Web 控制台,把 Codex CLI 和 Claude Code 会话装进浏览器窗口中统一管理。
AI Coding CLI 综合管理平台
当前项目目录:
/home/nbtang/nbtangInOne
一个基于 Node.js 的 Web 控制台,把 Codex CLI(cd)和 Claude Code(cc)装进浏览器窗口中统一管理。
当前仓库内已经实现:
control-plane + web-uicodex host-adapter(cd)claude host-adapter(cc)- 浏览器访问审批
- 会话继续、新建、隐藏
- 项目收藏(含别名,按 machineId::cwd 标识)
- 附件上传、预览、删除
- Run 执行(通过 Web UI 新建/继续会话,SSE 流式查看执行过程)
- Codex 速率限制状态查看
- cd/cc 手动选择(项目级 preferred/effective runtime,刷新后在同一浏览器会话内恢复)
- cd/cc 额度感知禁用(额度不足时禁用输入和发送,不自动切换)
- CC 图片理解辅助(CC + 图片时通过 OpenRouter 多模态模型生成图片描述后注入 prompt)
当前项目的默认进程
常用端口与监听地址:
control-plane:0.0.0.0:3209codex host-adapter:127.0.0.1:3211claude host-adapter:0.0.0.0:3212
默认访问入口:
http://127.0.0.1:3209
启动方式
启动当前项目主控制台:
cd /home/nbtang/nbtangInOne
./start-nbtanginone.sh
这个脚本会启动:
control-planeon0.0.0.0:3209codex host-adapteron127.0.0.1:3211claude host-adapteron0.0.0.0:3212
单独启动 Codex adapter(默认 127.0.0.1:3211):
cd /home/nbtang/nbtangInOne
./start-codex-host-adapter.sh
单独启动 Claude adapter(默认 0.0.0.0:3212):
cd /home/nbtang/nbtangInOne
./start-claude-host-adapter.sh
本机 cc 固定使用 DeepSeek 兼容模型 deepseek-v4-pro,不依赖 Claude 官方登录态。启动 adapter 前需要在本机创建环境文件:
mkdir -p ~/.config/nbtanginone
$EDITOR ~/.config/nbtanginone/claude-host-adapter.env
环境文件至少需要:
ANTHROPIC_BASE_URL=...
ANTHROPIC_AUTH_TOKEN=...
如果余额接口使用单独 key,可额外配置 DEEPSEEK_API_KEY=...;未配置时余额查询会复用 ANTHROPIC_AUTH_TOKEN。
CC 图片理解需要 OpenRouter API,需配置 OPENROUTER_API_KEY=...;未配置时图片理解会降级跳过。
start-claude-host-adapter.sh、start-control-plane-3209.sh、start-nbtanginone.sh 都会读取 ~/.config/nbtanginone/claude-host-adapter.env。不要把 token 写入仓库文档或提交。
启动独立 3209 control-plane(不附带 host-adapter):
cd /home/nbtang/nbtangInOne
./start-control-plane-3209.sh
停止主控制台:
cd /home/nbtang/nbtangInOne
./stop-nbtanginone.sh
停止独立 3209 control-plane:
cd /home/nbtang/nbtangInOne
./stop-control-plane-3209.sh
停止 codex host-adapter:
cd /home/nbtang/nbtangInOne
./stop-codex-host-adapter.sh
当前仓库中的主要脚本
- start-nbtanginone.sh: 启动当前项目(control-plane + cd adapter + cc adapter)
- stop-nbtanginone.sh: 停止主控制台
- start-codex-host-adapter.sh: 单独启动 codex adapter
- stop-codex-host-adapter.sh: 单独停止 codex adapter
- start-claude-host-adapter.sh: 启动 Claude adapter
- start-control-plane-3209.sh: 启动独立
3209control-plane - stop-control-plane-3209.sh: 停止独立
3209control-plane - approve-login-3209.sh:
3209控制台专用审批脚本 - unhide-session.sh: 取消隐藏 session
- install-autostart.sh: 安装当前项目主控制台的 user-level systemd 自启动
- install-control-plane-3209-autostart.sh: 安装
3209control-plane 的独立 user-level systemd 自启动 - uninstall-autostart.sh: 卸载主控制台的 user-level systemd 自启动
认证与审批
当前项目默认启用浏览器访问审批。单机自用部署可通过 NBTANGINONE_AUTH_DISABLED=1 关闭审批(见后文「单机自用部署」)。
浏览器第一次访问时:
- 不会直接进入主页面
- 会先提交访问请求
- 服务端写入认证状态文件
- 管理员审批后才放行
主控制台默认认证文件:
~/.codex/nbtanginone-auth.json
当前仓库内推荐所有本机 control-plane 启动方式统一使用这一份 auth 文件,避免同一浏览器在不同启动入口之间重复审批。当前代码使用环境变量 NBTANGINONE_AUTH_FILE。
审批方式:
cd /home/nbtang/nbtangInOne
./approve-login-3209.sh
approve-login-3209.sh 默认也会写入统一的 ~/.codex/nbtanginone-auth.json;如需临时审批其他 auth 文件,需显式传入 AUTH_FILE=...。
Host Registry
当前项目通过 hosts.json 注册 adapter 地址,配置本机 cd 和 cc adapter。
当前代码入口
- control-plane.mjs: 主控制台(API 网关 + 认证 + 收藏 + 内嵌 Web UI)
- server.mjs: 入口文件(导入 control-plane.mjs)
- host-adapter.mjs: Codex host-adapter
- claude-host-adapter.mjs: Claude host-adapter
- lib/codex-host-runtime.mjs: Codex 会话运行时
- lib/claude-host-runtime.mjs: Claude 会话运行时
- lib/auth-store.mjs: 浏览器访问审批系统
- lib/favorites-store.mjs: 项目收藏持久化(key = machineId::cwd)
- lib/http-utils.mjs: HTTP 工具函数
- hosts.json: 主机注册表
- host-adapter.config.example.json: Host-adapter 配置示例
当前项目的状态文件
~/.codex/nbtanginone-auth.json: 主控制台认证~/.codex/nbtanginone-state.json: Codex 会话隐藏状态(旧codexinone-state.json会兼容读取)~/.codex/nbtanginone-favorites.json: 项目收藏(key = machineId::cwd,旧codexinone-favorites.json会兼容读取)~/.claude/nbtanginone-claude-state.json: Claude 会话隐藏状态(旧codexinone-claude-state.json会兼容读取)
TODO 记录与 Code Review 约束
TODO.md 是跨开发人员交接和 code review 的依据。任何开发人员修改功能、修复问题或调整部署流程时,必须保证 TODO 记录能让其他人独立理解用户需求、实际问题、修改范围和验证状态。
必须记录
- 用户需求:用用户视角描述问题或目标,不只写实现任务。
- 好:
发送图片后,运行中的用户消息缩略图显示灰/破损,对话结束后恢复正常。 - 不好:
修改附件渲染逻辑。
- 好:
- 问题原因:说明定位到的根因、触发时序、受影响的运行时或 UI 状态。
- 修改内容:列出所有涉及文件和关键函数/路径;不能只记录最后一次小补丁。
- 行为变化:说明用户可见行为、API 行为、持久化状态或运行时生命周期有什么变化。
- 验证状态:记录已执行的检查命令、手动验证项、未验证项和原因。
- 部署/重启范围:如果修改影响 adapter、control-plane 或远端 host,必须写清楚哪些实例需要重启,哪些已重启,哪些未重启。
- Review 关注点:写出希望 reviewer 重点看的风险,例如消息合并顺序、附件生命周期、跨 host fallback、handoff 是否泄露到可见对话等。
禁止写法
- 不要只记录代码层面的局部重构,而忽略用户实际看到的问题。
- 不要把“需要重启”和“已经重启验证”混写。
- 不要遗漏同一次修改涉及的文件;如果只部署了部分 host,必须明确说明。
- 不要将运行日志文件、临时 PID 文件或本地环境噪音写成需求完成项。
- 不要把未经验证的浏览器行为写成已完成。
推荐模板
### YYYY-MM-DD 简短标题
#### 用户需求
- ...
#### 问题原因
- ...
#### 修改内容
- `path/to/file`
- 修改点
- 行为变化
#### 部署 / 重启
- [x] 本机 control-plane 已重启
- [ ] 远端 adapter 待重启:原因
#### 验证
- [x] `node --check ...`
- [x] 手动验证:...
- [ ] 待验证:...
#### Code Review 关注点
- ...
隐藏与取消隐藏
网页中的隐藏不会删除原始 session 文件,只会写入项目状态文件。
取消隐藏:
cd /home/nbtang/nbtangInOne
./unhide-session.sh
自启动
当前仓库提供 user-level systemd 模板。
安装主控制台自启动:
cd /home/nbtang/nbtangInOne
./install-autostart.sh
安装 3209 独立 control-plane 自启动:
cd /home/nbtang/nbtangInOne
./install-control-plane-3209-autostart.sh
推送到 Hub
如果需要把当前仓库代码推送到本机 hub 裸仓库:
先添加远程:
cd /home/nbtang/nbtangInOne
git remote add hub /mnt/d/git-repo/repos/nbtangInOne.git
如果已经存在 hub,可改成更新地址:
cd /home/nbtang/nbtangInOne
git remote set-url hub /mnt/d/git-repo/repos/nbtangInOne.git
推送当前分支:
cd /home/nbtang/nbtangInOne
git push -u hub $(git branch --show-current)
适配器选择(cd / cc)
发送消息时系统严格使用用户在页面上选择的运行时,不再因为额度不足自动在 cd 和 cc 之间切换。
项目级 runtime 选择
Conversation 输入框上方有 cd / cc 两个按钮:
preferredRuntime:用户希望当前项目后续使用的运行时effectiveRuntime:当前页面实际加载并执行的运行时
当用户选择 cd 且 cd 可用时,实际使用 cd。若 cd 额度不足或 weekly 已耗尽,cd 按钮会禁用,输入框、上传按钮和发送按钮也会禁用,并显示“额度不足,无法使用 cd”。系统不会临时改用 cc。
当用户选择 cc 且 cc 余额不可用或为 0 时,cc 按钮会禁用,输入框、上传按钮和发送按钮也会禁用,并显示“cc 额度不足/不可用”。系统不会临时改用 cd。
手动点击 cd / cc 切换时,Conversation 区域会显示“正在切换 adapter,请稍等...”。目标 adapter 的 project、session 和 session detail 加载完成后,输入区才恢复可用,避免用户在上下文未准备好时发送消息。
runtime 选择保存在浏览器 sessionStorage 的项目级状态中。同一设备同一浏览器刷新页面后可以恢复;PC 与手机浏览器之间不会自动同步。
页面展示以当前底层 session detail 为准。项目级可见消息缓存只作为 session detail 未加载期间的临时显示兜底,并按 machineId::cwd::runtime::sessionId 隔离,避免同一项目下 cd / cc 或不同 session 的消息互相污染。
发送前校验
用户点击发送时,客户端只检查当前选中的 runtime 是否可用:
- 当前 runtime 不可用:禁止发送。
- 当前 runtime 可用:按当前 adapter/session 发送。
- 当前有 active run:禁止切换 runtime。
cd 额度判断:
weekly == 0%:不可用。5h <= thresholdPercent:不可用,默认阈值为15%。- 不再使用
return threshold自动回切。
cc 额度判断:
- DeepSeek 余额接口返回错误:不可用。
- 余额为
0或小于0:不可用。 - 没有余额数据时暂不阻塞,按可用处理。
服务端兜底
control-plane 在转发 run 请求前也会做 preflight 检查:
- 若目标 host 是 cd 且额度不足,直接返回
429。 - 若目标 host 是 cc 且余额不可用或不足,直接返回
429。 - 不再查找同机 fallback adapter。
- 不再返回
actualHostId自动切换结果。
Handoff
新请求不再生成 handoff。历史 session 中已经落盘的 handoff 文本仍保留清理兼容逻辑,避免旧数据暴露到可见 Conversation。
关键限制
- 只在同一项目所属机器内手动切换,禁止跨主机找 adapter 操作项目。
- 不自动切换:额度不足只禁用当前 runtime,不自动使用另一个 runtime。
- 不自动回切:额度恢复后仍保持用户当前选择,需用户手动切换。
- 切换要等待数据加载完成:切换期间 Conversation 显示提示并禁用输入区。
运行时模型
- cd(Codex):
gpt-5.5+model_reasoning_effort="low",固定不切换 - cc(Claude Code):固定
deepseek-v4-pro cc依赖~/.config/nbtanginone/claude-host-adapter.env中的ANTHROPIC_BASE_URL和ANTHROPIC_AUTH_TOKEN。start-claude-host-adapter.sh在启动时检查必需环境变量,缺失则直接失败退出(adapter 不会启动),避免底层claude回退到官方/login。启动成功即表示环境就绪。cc使用 DeepSeek 兼容模型时,claude-host-adapter会每 5 分钟调用 DeepSeek/user/balance查询余额,并缓存到~/.claude/nbtanginone-deepseek-balance.json;Conversation 输入框底部会显示cc · deepseek-v4-pro · 余额 ... CNY · 今日 ... CNY。cc的今日花费使用余额快照法估算,快照文件为~/.claude/nbtanginone-deepseek-daily-usage.json:每天第一次查询余额作为当天起始余额,今日花费 = 起始余额 - 当前余额。如果当天充值、赠送或退款,估算值可能低于真实花费。
图片上传与理解
- cd + 图片:保持 Codex 原生图片能力,adapter 使用
--image传图。 - cc + 图片:control-plane 会先调用 OpenRouter
qwen/qwen-vl-max对图片做文本描述,再把[image-analysis]...[/image-analysis]注入给 CC。 - 需要配置
OPENROUTER_API_KEY;未配置或调用失败时降级为原行为,不阻塞发送。 - 当前 Codebuddy / cb 路径已从仓库移除,不再作为图片或文本 fallback。
核心功能
项目级唯一 Conversation
- 每个项目只维护一个项目级
Conversation,用户心智从project -> 多个 session收敛为project -> 唯一 conversation session退到实现层,只用于底层cd / cc持久化、恢复和运行状态跟踪- 已有项目自动迁移:优先选最近活跃的
cd,无cd则选cc - 项目卡片不再显示 runtime 信息,仅展示项目名称、路径和最近活跃时间
- Conversation 顶部会显示当前底层
session id、渲染消息数量和短 hash。刷新恢复异常时,先看这些字段:session变化表示恢复到了不同底层会话;session相同但hash变化表示前端渲染或缓存层存在差异。
Run 状态反馈
- 气泡状态分级:工具执行中显示 “正在执行 xxx...”,与
...动画水平排列
单机自用部署
单机自用建议做以下简化:
认证策略
单机自用可以关闭浏览器审批,避免每次访问都需确认:
echo 'NBTANGINONE_AUTH_DISABLED=1' > ~/.config/nbtanginone/control-plane.env
启用后无需执行 approve-login-3209.sh。
Host Registry
单机部署只需在 hosts.json 中注册本机 adapter:
{
"hosts": [
{
"id": "local",
"name": "Local CD",
"machineId": "local",
"baseUrl": "http://127.0.0.1:3211",
"kind": "adapter"
},
{
"id": "claude-local",
"name": "Local CC",
"machineId": "local",
"baseUrl": "http://127.0.0.1:3212",
"kind": "adapter"
}
]
}
systemd 服务
使用 user-level systemd 管理服务:
# 查看状态
systemctl --user status nbtanginone-control-plane-3209.service
systemctl --user status nbtanginone-host-adapter.service
systemctl --user status nbtanginone-claude-host-adapter.service
# 重启
systemctl --user restart nbtanginone-control-plane-3209.service
systemctl --user restart nbtanginone-host-adapter.service
systemctl --user restart nbtanginone-claude-host-adapter.service
说明
这个 README 只描述当前仓库 /home/nbtang/nbtangInOne 里的实现和脚本,不描述其他目录下的历史副本或外部部署流程。
下载使用量
项目总下载次数(含Clone、Pull、 zip 包及 release 下载),每日凌晨更新