bots.json 配置

通过 ~/.botmux/bots.json 配置机器人。运行 botmux setup 交互式创建,或手动编辑。文件是一个数组,每个元素是一个 bot(生产环境一个 bot 对应一个独立 daemon 进程)。

[
  {
    "larkAppId": "cli_xxx_bot1",
    "larkAppSecret": "secret_1",
    "name": "claude-main",
    "cliId": "claude-code",
    "model": "sonnet",
    "lang": "zh",
    "workingDir": "~/projects",
    "allowedUsers": ["alice@company.com"],
    "allowedChatGroups": ["oc_xxx_team"],
    "oncallChats": [{ "chatId": "oc_xxx_oncall", "workingDir": "~/projects/foo" }]
  },
  {
    "larkAppId": "cli_xxx_bot2",
    "larkAppSecret": "secret_2",
    "cliId": "codex",
    "model": "gpt-5-codex",
    "workingDir": "~/work",
    "autoStartOnNewTopic": true
  }
]

字段较多,按用途分组列出,绝大多数都是可选的——只填 larkAppId / larkAppSecret 就能跑起来,其余按需增配。

必填

字段说明
larkAppId飞书应用 App ID
larkAppSecret飞书应用 App Secret

CLI 与模型

字段说明
name进程名后缀,如 claude-mainbotmux-claude-main;留空默认 botmux-<序号>
cliIdCLI 适配器,默认 claude-code。见 多 CLI 适配器
model启动 CLI 用的模型名(如 claude --model opus);留空走 CLI 默认。同一 cliId 的多个 bot 可跑不同模型。各适配器的 modelChoicesbotmux setup 里给出的候选
cliPathOverrideCLI 入口绝对路径,用于套 wrapper / router(ccr、claude-w、aiden-x-claude 等)
disableCliBypasstrue 时不自动追加 CLI 的免审批 / 沙箱绕过参数(--yolo--dangerously-*);缺省 / false 保持原行为
backendType会话后端,可选 pty / tmux / herdr / zellij。留空自动检测:tmux 可用选 tmux,否则 ptyherdrzellij 不会被自动选中,需显式指定)。tmux / herdr / zellij 都是持久会话,对应二进制探测失败时自动回落 ptyzellij 需 ≥ 0.44);pty 直连进程、不跨重启持久。见 tmux 后端
launchShell启动 CLI 用的 shell,覆盖 daemon 的 $SHELL:填 shell 名(zsh / bash / sh)或绝对路径(如 /usr/bin/zsh)。用于登录 $SHELL(如 bash)的 rc 文件里有 exec zsh 之类跳转、在 botmux 的 bash -i 启动里把 CLI 顶掉、导致会话起不来(裸壳里 parse error)的场景——指定后直接用它启动、绕开被跳过的 rc。注意:PATH / nvm / pnpm 等要放进所选 shell 的 rc(如 .zshrc / .zprofile)。留空=用 $SHELL。下个会话生效;仅 tmux / zellij 后端(pty 直接 exec CLI,本就不受影响)。也可在 dashboard「机器人默认设置 → 启动 Shell」或 /config launchShell <值> 配置
lang该 bot 的界面语言 zh / en;留空回落 BOTMUX_LANG / LANG 环境变量
customPassthroughCommands在固定透传白名单和当前 CLI adapter 默认放行命令之上,额外放行透传给底层 CLI 的 slash 命令,如 ["/export"](Claude Code / Codex 的 /goal 已默认放行)。自动归一化(缺失的 / 自动补、转小写、仅留 [a-z0-9:_-]、去重);会遮蔽 botmux daemon 命令(如 /status)的项会被丢弃,配了也不生效。用 /list-slash-command 查看完整放行清单。见 斜杠命令
env该 bot 的进程环境变量 { "KEY": "值" },注入到这个 bot 的 CLI 进程。最常见用途:让某个 bot 跑 GLM / 第三方 Anthropic·OpenAI 兼容服务商(见下方示例),也可设 HTTPS_PROXY 或 CLI 专属开关。值支持字符串 / 数字 / 布尔;BOTMUX_ / LARK_APP_ 等 botmux 保留键会被忽略。按会话注入(下个新会话生效),不写入共享 tmux server 全局、不会串到别的 bot。也可在 dashboard「机器人默认设置 → 环境变量」配置

接入 GLM / 第三方服务商(per-bot env)

让某个 bot 跑 GLM Coding Plan(或其它 Anthropic 兼容服务商),另一个 bot 仍跑官方 Claude——给前者配 env

{
  "cliId": "claude-code",
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
    "ANTHROPIC_AUTH_TOKEN": "你的 GLM Coding Plan key"
  }
}
  • GLM 国内站把 ANTHROPIC_BASE_URL 换成 https://open.bigmodel.cn/api/anthropic
  • 给 Codex 这类 OpenAI 协议 CLI 接入时,填 OPENAI_BASE_URL / OPENAI_API_KEY(服务商的 OpenAI 兼容端点)而非 ANTHROPIC_*
  • 隔离:env 按会话注入到 CLI 进程,全后端一致(tmux / zellij 经每个 pane 注入,绝不写共享 server 全局),所以一个 bot 的服务商配置不会串到别的 bot。
  • 安全:值以明文存在 bots.json 与进程环境,不是密钥保险箱;/config get 等聊天面会脱敏显示(dashboard 编辑器 owner 鉴权后显示原值)。
  • 改完下个新会话生效。

工作目录

字段说明
workingDir默认工作目录,支持逗号分隔多个。从该目录向下递归找 git 仓库(最多 3 层),不向上扫
workingDirs工作目录数组写法(["~/a", "~/b"]);显式配置时优先于 workingDir 的逗号分隔形式
defaultWorkingDir单仓库默认目录:无 oncall / 无同群兄弟 session 时直接进入,跳过 repo 选择卡片。/cd 仍可中途切换。纯运行时回落,不写状态、不改权限模型

权限与授权

字段说明
allowedUsers操作权名单(完整邮箱ou_xxx)。配了 allowedChatGroups 时至少要有一个作为 owner
allowedChatGroups可对话群(oc_xxx)。群内任何成员可对话(仅 canTalk),敏感操作仍由 allowedUsers 控制
oncallChatsoncall 绑定,[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]。见 oncall
defaultOncall该 bot 的默认:新群聊首条新话题自动绑定 oncall。{ "enabled": true, "workingDir": "~/foo", "since": <epoch ms> }since 之前已存在的老群不受影响
globalGrants全局可对话名单(ou_xxx,人或 bot)。任意群可对话,仅 canTalk
chatGrants按群的 per-user 授权 { "oc_xxx": ["ou_yyy"] },仅放行 canTalk。一般由 /grant 卡片写入,也可手配
messageQuota消息额度开关 { "defaultLimit": N }:配了正整数后,不带数字的 /grant 套用 N 条额度;不配则授权无限。仅约束 talk 授权,不影响 canOperate
restrictGrantCommandstrue 时,仅靠 per-user 授权(chatGrants / globalGrants)放行的人禁用所有斜杠命令,只能普通对话;owner / allowedUsers / oncall / 整群成员不受影响。默认 false
autoGrantRequestCards默认开启。显式设为 false 时,群里未授权的人或外部 bot @ 本 bot 但被对话权限闸挡住时,不再自动给 owner 发 /grant 申请卡,改为静默丢弃

文件沙盒

字段说明
sandboxtrue 时,新会话在 Linux 文件沙盒中启动。写入被隔离,需要通过 /land 审阅落盘
sandboxHidePaths在沙盒内用空目录 / 空文件遮罩的路径,避免机器人读取,例如 ["~/.ssh", "~/.botmux/bots.json"]
sandboxReadonlyPaths在沙盒内额外只读挂载的已存在路径,适合共享源码快照、参考仓库或生成文档等只允许查看、不允许修改的输入
sandboxNetwork沙盒会话的网络策略。缺省 / true 保留当前网络和代理访问;false 添加 --unshare-net,阻断普通网络出口

卡片与终端

字段说明
brandLabel卡片底部品牌文案。undefined=默认 botmux 链接;""=隐藏;其它字符串=原样渲染(支持 markdown)。纯样式,不影响路由 / 权限
disableStreamingCardtrue 时彻底不发实时流式 session 卡片(web 终端仍跑、最终答复仍经 botmux send 到达,只是没有自动刷新的状态卡)。给嫌实时卡吵的用户
silentTurnReactionstrue 时,无卡片会话不再给触发消息添加 GoGoGo / DONE reaction。只影响 disableStreamingCardnoCardChats 关闭实时卡片后的轻量状态提示;默认 false
receivedReactionEmoji无卡片会话「已收到」reaction 的飞书 emoji_type;undefined=默认 GoGoGo(冲!)。自由字符串,填错只是静默不加表情(best-effort)
doneReactionEmoji无卡片会话「已完成」reaction 的飞书 emoji_type;undefined=默认 DONE(✅)。设成与 receivedReactionEmoji 相同值可让完成态不翻脸——适合 idle 判定可能提前触发的 CLI(如 Pi),避免过早出现误导性的 ✅
writableTerminalLinkInCardtrue 时卡片正文直接内嵌可写终端链接(带 token,看得到卡片的人都能操作);默认藏在「获取写权限」按钮后私发给点击者。disableStreamingCard 开启时无意义
privateCardtrue/card 走 ephemeral 私有卡片,仅 allowedUsers 可见(talk 授权与裸触发者收不到),仅普通 group 聊天有效,且不能 live 更新。只作用于 /card 命令本身

主动开工

字段说明
autoStartOnGroupJointrue 时,被拉入含至少一名 allowedUsers 的新群即自动开工(不必 @)。需在飞书后台为该应用订阅 im.chat.member.bot.added_v1 事件
autoStartOnGroupJoinPrompt配合上面:自动开工的首轮 prompt;留空 / 空白则空消息开场,让 bot 自己读群上下文。autoStartOnGroupJoin 关闭时无意义
autoStartOnNewTopictrue 时,话题群里每个新话题的首条消息无需 @ 也自动开工(普通群无效)。默认被动(仅 @ 触发)

总结命令

字段说明
summaryRange显式总结命令 @机器人 /summary 使用的历史读取范围。limit 表示普通群最近 N 条消息,默认 50;sinceHours 表示普通群最近 N 小时,默认 24。任一字段设为 0 表示该维度不限制。话题群始终读取当前话题/thread 历史,再按总结窗口过滤

示例:

{
  "summaryRange": {
    "limit": 50,
    "sinceHours": 24
  }
}
  • 只有显式 @机器人 /summary 会触发总结;不 @ 机器人时仍按普通群/话题的既有路由规则处理,不会因为关键词自动唤醒。
  • dashboard 的「/summary 总结范围」保存的就是 summaryRange
  • 如果本次触发前存在上一条 @同一机器人 /summary,总结窗口只包含上一条之后到本次触发为止的消息;找不到上一条时回退到 limit / sinceHours
  • limitsinceHours 同时也是安全上限;两者都为 0 时表示不做该维度限制。

旧内容触发配置

字段说明
contentTriggersLegacy / 不再生效。 旧版本曾用于关键词 / 正则免 @ 触发,但当前消息路由不会再根据 contentTriggers 唤醒 bot。保留该字段解析仅用于兼容旧 bots.json:如果存在名为 dashboard-default-summary-trigger 的旧 dashboard 配置,botmux 会尽量从其中迁移/读取 limitsinceHours 作为 summaryRange 的兜底值。新配置请使用 summaryRange

语音

字段说明
voice该 bot 的语音引擎覆盖,按字段合并到 ~/.botmux/config.json 的全局 voice 块之上(per-bot 优先)。有可用语音凭据时,回复卡片会出现「🔊 语音总结」按钮。见 语音总结

运行时状态(自动维护,勿手改)

下列字段由 botmux 自身写入并随授权 / 开关一起持久化进 bots.json,列出仅为说明,不要手动编辑

字段说明
defaultOncallAutoboundChatsdefaultOncall 已自动绑过的 chat_id(append-only)。一旦记录,即使后续解绑也不会再次自动绑
quotaStatescope 级消息额度计数 { "chat:<cid>:<oid>" | "global:<oid>": { limit, used } };用满自动收回对应 scope 授权
noCardChats/card off|on 写入的「该群不发流式卡片」名单

配置优先级BOTS_CONFIG 环境变量 → ~/.botmux/bots.json。改完跑 botmux restart 生效。