botmux 只有一个 bin 入口 src/cli.ts(约 13k 行,#!/usr/bin/env node)。命令分发不用任何 CLI 框架:顶层直接 const command = process.argv[2] 后进入一个大 switch(src/cli.ts:12887),各 cmdX() 处理函数大部分就地定义在 cli.ts 内,较重的子命令拆到 src/cli/ 目录(34 个文件)并通过动态 import 懒加载,避免启动时拉入全部依赖。用户可见的命令清单见 cli-commands。

命令分发结构

三类入口:

  1. 内联 handler:cmdStart/cmdStop/cmdRestart/cmdLogs/cmdStatus/cmdList/cmdDelete/cmdResume/cmdSuspend/cmdSend/cmdHistory/cmdQuoted/cmdDispatch/cmdReport/cmdBots/cmdAsk/cmdHook/cmdWhiteboard/cmdSchedule 等约 40 个 cmdX 函数直接写在 cli.ts(每个函数定义行号可用 grep '^async function cmd' src/cli.ts 定位)。
  2. 拆分模块(动态 import):capabilities、bind、device、skill、skills、mcp serve、workflow(部分)、template、v3、goal、vc-agent,case 内 await import('./cli/xxx.js') 或 ./core/...、./workflows/v3/...、./platform/...。
  3. default → 插件命令:未命中的命令先交给 runPluginCommandByName(command, ...),插件以一级命令形式扩展(botmux <plugin-cmd>),都不命中才 showHelp()(src/cli.ts:13151)。

Workflow 安全门

BOTMUX_WORKFLOW=1(由 v3 ephemeral worker pool 注入)时,CLI 在分发前做默认拒绝过滤(src/cli.ts:12119):只放行只读/内省命令(status/history/quoted/bots/skill/hook/capabilities/mcp serve 等白名单),schedule/workflow/template/v3 的变更性子命令二次过滤。设计意图:workflow 子代理的副作用必须走 hostExecutor activity 才有 effectAttempted 追踪。

命令 → 实现位置对照(选摘)

命令实现
setup / setup list|add|configure|edit|removecli.ts cmdSetup/cmdSetupScripted + src/setup/*(见 setup-flow)
start / stop / restart / start-bot / stop-botcli.ts + src/cli/pm2-*.ts、fleet-shutdown.ts
list / delete / resume / suspendcli.ts + src/cli/session-picker-*.ts、session-list-liveness.ts
send / quoted / history / bots / create-group / grantcli.ts + src/cli/send-dispatch.ts、quoted-render.ts、bots-list-output.ts、create-group-resolver.ts、exact-chat-grant*.ts
schedulecli.ts cmdSchedule + src/cli/deferred-topic-send.ts
dashboardcli.ts cmdDashboard + src/cli/dashboard-command.ts、dashboard-endpoint.ts
workflow / template / v3 / goalsrc/cli/workflow.ts、saved-workflow.ts、workflow-migration.ts、workflow-run-archive.ts、v3-run-cancel.ts + src/workflows/v3/*
vc-agentsrc/cli/vc-agent.ts(见 vc-agent)
skill / skillssrc/core/skills/cli-session-command.ts / cli-admin-command.ts(见 skills)
mcp servesrc/core/plugins/mcp/gateway.js
autostartcli.ts + src/autostart.ts

墓碑命令(改名后保留 fail-loud 入口):cd → 报错指向 role switch(假切换成功比报错危险);thread → 指向 history。

src/cli/ 文件职责分组

PM2 fleet 生命周期(daemon 用 PM2 托管,这组是纯函数化的安全栅栏):

  • pm2-command.ts spawn 命令构造;pm2-jlist.ts jlist 输出严格解析;pm2-preflight.ts Linux God 二进制可用性探测;pm2-descriptor-guard.ts 未注册 descriptor 守卫;pm2-god-admission.ts live God 入场准入(kill 按 PID、RPC 按 socket,都无法绑定代际,故 live God 不可自动替换);pm2-exact-start.ts 精确 startProcessId RPC;pm2-shutdown-capability.ts 关停能力认证;pm2-start-transaction.ts 有界启动事务 + stop_exit_codes 策略校验;fleet-shutdown.ts fleet 信号与等待;supervisor-shutdown-client.ts 认证关停 HTTP 客户端;daemon-lifecycle-env.ts PM2 env 块镜像清单。

会话选择器 TUI(botmux list 交互界面):session-picker-layout.ts 响应式列布局、session-picker-viewport.ts 垂直滚动窗口几何、terminal-width.ts 跨终端保守上界的 cell 宽度表、session-list-liveness.ts 会话存活判定(cold-resume dormant 等)、zmx-managed-attach.ts ZMX 托管会话 attach。全部抽成纯函数便于单测。

消息收发:send-dispatch.ts(cmdSend 的核心:主消息派发、stdin 别名附件、interactive 卡片 JSON 规范化、图片/文件/视频附件校验);deferred-topic-send.ts(定时任务到点后在原话题续消息);quoted-render.ts(botmux quoted 纯函数渲染管线);bots-list-output.ts、create-group-resolver.ts(bot 引用解析:larkAppId → 进程名 → 别名)、exact-chat-grant.ts + exact-chat-grant-client.ts(talk-only 精确群授权)。

其余:dashboard-command.ts/dashboard-endpoint.ts(dashboard 进程 /__cli/* 的 loopback HMAC 客户端);capabilities.ts(botmux capabilities 机器可读能力文档,schemaVersion=1);arg-utils.ts(无副作用 argv 辅助,测试可在不触发顶层 switch 的情况下 import);stdin-encoding.ts(Windows stdin 乱码拒收);v3-run-cancel.ts(workflow cancel 传输缝)。

设计要点

  • 顶层 switch 有副作用,辅助逻辑尽量下沉 src/cli/ 纯函数模块,测试绕过入口直接 import。
  • 命令在 workflow 子代理内默认拒绝,是「新命令不会静默泄漏给 bypass-permission worker」的护栏。
  • 会话内命令(send/history/schedule/ask 等)通过进程树 session marker 或 BOTMUX_SESSION_ID 自动推断会话上下文(findAncestorSessionContext)。

相关:cli-commands、architecture-overview、daemon-worker、setup-flow