Bridge between IM platforms and AI coding CLIs — one topic, one CLI session with live streaming

163 stars | TypeScript | MIT | 2026-03 | Node.js >= 22

飞书话题群 + AI 编程 CLI 的桥接层。Daemon 监听飞书消息,为每个新话题自动启动独立 CLI 进程,提供实时流式卡片和可交互 Web 终端。

核心定位

不做 SDK wrapper,直接桥接 CLI 进程。

botmux 不重新实现 Agent 能力,而是直接桥接已有的 AI 编程 CLI(Claude Code、Codex、Cursor、Gemini、OpenCode、Antigravity)。记忆、上下文管理、工具调用、权限体系——这些能力 CLI 本身都在快速迭代,botmux 选择站在这个进化之上,而不是平行重造一套。CLI 的每次升级,botmux 零适配自动受益。

整体架构

飞书消息 → Daemon (2503行) → Worker Pool → Worker进程(每会话独立)
                                                  ↓
                                      CliAdapter (8种CLI适配器)
                                                  ↓
                                      Backend (pty / tmux)
                                                  ↓
                                      IdleDetector → BridgeTurnQueue
                                                  ↓
                                      飞书流式卡片 / Web终端(xterm.js)

三层进程模型:

  • PM2 — 管理 daemon 生命周期,开机自启
  • Daemon (daemon.ts, 2503行) — 处理飞书事件、路由消息、管理会话、调度 Workflow
  • Worker (worker.ts) — 每个会话独立进程,持有 PTY + WebSocket 服务器

源码结构

src/
├── adapters/
│   ├── backend/        # pty-backend, tmux-backend, tmux-pipe-backend
│   └── cli/            # 8种CLI适配器 + registry + shared-hints
├── core/               # session-manager, worker-pool, scheduler, command-handler
├── dashboard/          # Web管控面 (esbuild打包的前端 + IPC后端)
├── im/lark/            # 飞书SDK封装:card-builder, event-dispatcher, identity-cache
├── services/           # bridge-turn-queue, bridge-rotation-policy, session-store等
├── skills/             # Skill定义 + 安装器
├── utils/              # idle-detector, terminal-renderer, screenshot-renderer
└── workflows/          # 完整工作流引擎 (orchestrator, events, hostExecutors)

180个测试文件,核心模块均有单元测试。

核心技术深度分析

1. BridgeTurnQueue — 异步流归因状态机

最复杂的模块,解决的核心问题:飞书消息和 CLI 的 JSONL transcript 是两个异步流,需要精确对应”哪条飞书消息触发了哪段 assistant 输出”。

纯状态机设计(无 IO,测试友好):

mark(turnId, fingerprint)  → 飞书消息到来时打标记
ingest(events)             → 消费 JSONL transcript,用 fingerprint 匹配 user event 启动 turn
drainEmittable()           → 弹出已有 assistant 文本的 turn,发回飞书

边界情况处理:

场景处理方式
HOL-block drop前一 turn 无 assistant 文本但新 user event 来了 → 直接丢弃(Claude 单线程不会回来)
Local terminal input用户直接在 tmux 里打字,fingerprint 不匹配 → 合成 isLocal turn,飞书显示”🖥️ 终端本地对话”
Headless turndaemon 重启导致 collecting 指针丢失,assistant 文本孤立 → 合成 headless turn 避免静默丢弃
Type-aheadClaude Code 支持 supportsTypeAhead,通过 attachment(queued_command) 事件触发 turn start

2. Session ID Rotation 三层追踪

Claude Code 在 /clear、--resume、进程重启时会轮换 session ID(对应不同 JSONL 文件)。bridge-rotation-policy.ts 实现三层策略:

  1. Pid resolver(主路径) — 读 ~/.claude/sessions/<pid>.json 获取当前 session ID
    • 盲区:Claude Code 2.1.123 只在进程启动时写一次,/clear 不刷新
  2. Fingerprint fallback(补充) — 扫描目录下所有 JSONL,找包含消息 fingerprint 的文件
    • 解决 /clear 场景
  3. Quiet rotation(兜底) — 按 mtime 启发式选最活跃的 JSONL
    • 仅在前两者都无法判断时启用,多 pane 场景下容易误选兄弟 pane

竞态处理:stalePidStateSessionId 记录”已被 fingerprint 覆盖的旧 sid”,阻止 pid resolver 把 watcher 拉回去。

3. CliAdapter 接口

src/adapters/cli/types.ts 定义的核心抽象,支持 8 种 CLI:claude-code、aiden、coco、codex、cursor、gemini、opencode、antigravity。

关键设计:writeInput 可返回 { submitted: boolean, recheck?: () => boolean } — 允许 adapter 在写入后异步验证(通过读 JSONL 确认 user event 出现),失败时提供 recheck 闭包供 worker 延迟重试(处理 hook 慢、磁盘忙等情况)。

interface CliAdapter {
  buildArgs(opts)           // 构建启动参数
  writeInput(pty, content)  // 写入用户消息(可验证是否成功)
  buildResumeCommand(opts)  // 生成用户可粘贴的本地恢复命令
  completionPattern?        // CLI 完成标记正则
  readyPattern?             // CLI 就绪标记正则(抑制过早的 idle 检测)
  supportsTypeAhead?        // 是否支持 Claude Code 的 type-ahead
  injectsSessionContext?    // 是否通过 --append-system-prompt 注入上下文
  skillsDir?                // Skill 目录路径
}

4. IdleDetector — 双策略空闲检测

检测 CLI 何时”空闲可接受输入”:

  • Strategy 1: completionPattern — CLI 特定完成标记正则(如 Claude Code 的 ✢ 符号),匹配后 500ms 确认
  • Strategy 2: Quiescence — PTY 静默 2s + 最近 3s 内无 spinner 字符(·✢✳✶✻✽⠋⠙⠹...)

readyPattern 用于抑制过早的 idle 判断(如 CoCo 的 ⏵⏵ 状态栏出现前不算就绪)。

5. Workflow 引擎

src/workflows/ 是一个完整的持久化工作流引擎,参考 Temporal/Durable Execution 思路:

核心设计:

  • Event sourcing — 所有状态变更写入 NDJSON 事件日志,状态通过 replay 重建
  • 纯决策层 — orchestrator.ts 是纯函数,输入 Snapshot + WorkflowDefinition,输出 OrchestratorAction[],不做任何 IO
  • 幂等性 — events/idempotency.ts 保证同一 effect 不重复执行
  • Human Gate — 节点可声明 humanGate.stage='before',要求人工审批后才执行
  • 冷恢复 — cold-attach.ts + resume.ts 支持 daemon 重启后从磁盘恢复 in-flight runs

安全强制:side-effect executor(feishu-send、feishu-reply、botmux-schedule)默认强制要求 humanGate 或显式 unsafeAllowUngated: true,在 schema 解析时就拦截,不依赖运行时约定。

节点类型:

  • subagent — 启动 bot worker,传入 prompt,收集 output JSON
  • hostExecutor — 调用注册的 executor(飞书发消息、定时任务等)

WorkflowDefinition 用 Zod 做 schema 验证,parseWorkflowDefinition 额外做图校验(DAG 无环、deps 引用合法、至少一个 root node)。

6. TmuxBackend — 进程常驻核心

pty-under-tmux 架构:
  node-pty 进程 → tmux new-session/attach-session
  kill() 只 detach(pty viewer 退出,tmux session 存活)
  destroySession() 才真正 kill tmux session

会话命名:bmx-<sessionId.slice(0,8)>

Adopt 模式:adoptedPaneTarget 记录真实 pane 地址(如 0:2.0),所有 pane 级 tmux 命令必须显式寻址,避免误操作兄弟 pane。

与 OpenClaw 对比

特性botmuxOpenClaw
底层架构直接桥接完整 CLI 进程基于 Agent SDK 重新构建
CLI 能力完整运行时(hooks/memory/plan mode/Skill//命令)SDK API 子集
CLI 升级零适配自动受益需跟进 SDK 版本变更
记忆/上下文直接复用 CLI 内建记忆系统需自建记忆系统
多 CLI 支持8 种 CLI 一键切换绑定单一 SDK
Web 终端可交互完整终端,移动端快捷键工具栏通常仅 Web 聊天界面
多机器人协作多 bot 同群 @mention 路由,独立进程隔离通常单机器人
复杂度代价Bridge 层极复杂(JSONL 追踪 + rotation + fingerprint)直接 API 回调,无此复杂度
适用场景想用完整 CLI 能力的个人/小团队需要深度定制 Agent 行为的产品

功能特性

实时流式卡片

  • 终端输出实时渲染为 Markdown,自动过滤 TUI 装饰
  • 状态指示:🟡 启动中 → 🔵 工作中 → 🟢 就绪
  • 操作按钮:打开终端、获取操作链接、重启 CLI、关闭会话

Web 终端(可交互)

  • 只读链接展示在群话题流式卡片上
  • 可操作链接通过私聊按需获取(一次一密)
  • 移动端悬浮快捷键工具栏(Esc、Ctrl+C、Tab、方向键等)

Tmux 会话常驻

  • 核心收益:Daemon 重启不中断 CLI,botmux restart 时 worker 退出但 tmux session 保持运行
  • botmux list 交互式列出所有活跃会话并 attach

多机器人协作

  • 同一群聊中通过 @mention 路由消息
  • @<bot1> @<bot2> /t xxx 让每个 bot 各自独立开新话题
  • /introduce 让各 bot 互相登记 open_id,支持跨 bot 协作

会话接入(Adopt)

  • /adopt 将已在 tmux 中运行的 CLI 进程无缝接入 botmux
  • 共享模式:iTerm2 和飞书双向同步
  • 一键接管:点击「🔄 接管」转为标准 botmux 会话

定时任务

  • 斜杠命令:/schedule 每日17:50 帮我看看AI圈有什么新闻
  • 支持中文自然语言、duration、cron 表达式、ISO 时间戳
  • 到点在原话题内续消息,不另开 thread

会话内 Skill(给 CLI agent 用)

通过 --append-system-prompt 注入,不依赖 MCP 协议,对所有 8 种 CLI 通用:

  • botmux send — 向当前话题发消息(文本/图片/文件/@mention)
  • botmux history — 读取当前会话历史消息
  • botmux quoted <message_id> — 读取被引用的消息
  • botmux bots list — 查询当前群聊的机器人及 open_id
  • botmux schedule — 增删改查定时任务

安装与配置

npm install -g botmux
botmux setup   # 交互式配置(扫码建应用或手动粘 AppID/Secret)
botmux start
botmux autostart enable  # macOS launchd / Linux user systemd,无需 sudo

bots.json 核心字段

[{
  "larkAppId": "cli_xxx",
  "larkAppSecret": "secret",
  "name": "claude-main",
  "cliId": "claude-code",
  "workingDir": "~/projects",
  "allowedUsers": ["alice@company.com"]
}]

cliId 可选:claude-code、aiden、coco、codex、cursor、gemini、opencode、antigravity

值得借鉴的设计

  1. BridgeTurnQueue 纯状态机 — 复杂异步归因逻辑封装成纯函数,测试无需 mock IO
  2. writeInput 验证机制 — 写入后异步确认 + recheck 闭包,比 sleep 等待更可靠
  3. Workflow humanGate 强制 — schema 层面要求 side-effect 节点必须有人工审批
  4. stalePidStateSessionId 竞态处理 — 两个异步信号源(pid resolver + fingerprint)之间的优先级协调
  5. pty-under-tmux 架构 — 用 node-pty 包裹 tmux,kill 只 detach 不销毁,实现进程常驻

局限性

  • 仅支持飞书:目前仅支持飞书 (feishu.cn) 租户,Lark 国际版不支持
  • Bridge 层复杂度高:JSONL 追踪 + session rotation + fingerprint 匹配,这是”直接桥接 CLI”必须付出的代价
  • Idle 检测依赖 PTY 输出特征:CLI 更新 UI 风格可能导致误判
  • 早期项目:163 stars,2026-03 创建,API 可能变动

相关页面

人工增加

## Oncall模式
- `/oncall bind <path>` — 绑定当前群到某个项目目录,发起人自动成为 owner
- `/oncall unbind` — 解绑(仅 owner)
- `/oncall status` — 查看当前绑定
    
## 会话能「搬家」:/relay 接力
 
Adopt 是把本机 tmux 里的进程接进飞书;
Relay 是把一个已经在 botmux 里跑的会话从 A 群搬到 B 群。