botmux 可以在关键生命周期事件发生时异步调用外部命令。命令失败、超时或不存在只会写日志,不阻塞 botmux 主流程(fire-and-forget)。
配置位置
按优先级从高到低:
BOTMUX_HOOKS_JSON环境变量(直接传 JSON 数组)BOTMUX_HOOKS_FILE指定的文件路径- 默认
~/.botmux/data/hooks.json
环境变量机制见 env。
配置字段
[
{
"event": "session.requires_attention",
"command": "/absolute/path/to/your-hook --flag value",
"timeoutMs": 5000,
"filter": { "chatId": "oc_xxx" },
"redact": { "fullContentEvents": ["session.requires_attention"] }
}
]| 字段 | 类型 | 说明 |
|---|---|---|
event | string | 必填。订阅的事件名(见下表) |
command | string | 必填。外部可执行命令;支持参数,但不经 shell 执行(不能用管道/重定向) |
timeoutMs | number | 可选。默认 5000;超时先 SIGTERM,再兜底 SIGKILL |
filter.chatId | string|string[] | 可选。只匹配指定飞书群 / 话题所在 chat |
filter.senderOpenId | string|string[] | 可选。只匹配指定发送者 open_id |
redact.fullContentEvents | string[] | 可选。默认截断长文本;列入 allowlist 的事件透传全文 |
支持事件
| 事件 | 触发时机 |
|---|---|
topic.new | 收到新话题 / @mention |
thread.reply | 收到已有话题回复 |
outbound.send | botmux 发送普通消息成功 |
outbound.reply | botmux 回复话题消息成功 |
schedule.fired | 定时任务执行完成(见 schedule) |
session.start | worker / adopt worker 启动成功 |
session.exit | worker 退出、崩溃或会话被关闭(daemon shutdown 默认静音) |
session.idle | session 进入或离开 idle,按 session + 状态 10s 去重 |
session.requires_attention | TUI prompt 或 worker user_notify 需要用户处理 |
会话生命周期概念见 session-model。
Payload
所有 payload 通过 stdin 写入 hook 命令,同时设置环境变量 BOTMUX_HOOK_EVENT。每份 payload 都包含 event、emittedAt;事件上下文可含 sessionId、chatId、chatType、larkAppId、scope、anchor、title、cliId、workingDir、hasHistory、spawnedAt、lastMessageAt。
各事件额外字段:
| 事件 | 额外字段 |
|---|---|
topic.new | messageId、senderOpenId、senderType、msgType、content |
thread.reply | messageId、rootId、parentId、senderOpenId、senderType、msgType、content |
outbound.send | messageId、msgType、uuid、content |
outbound.reply | messageId、replyId、msgType、replyInThread、uuid、content |
schedule.fired | id、name、schedule、status、error、rootMessageId、runAt |
session.start | reason、pid、adoptedFrom |
session.exit | reason、code(worker 退出路径;dashboard_close 为 null) |
session.idle | prevState、newState、transition、source |
session.requires_attention | reason、description、optionsCount、optionsPreview、multiSelect、message |
默认把 content、message、description、finalOutput、lastScreenContent 截断到 600 字符,并补充 xxxLength / xxxTruncated;只有 redact.fullContentEvents 内的事件透传全文。
快速验证与实践
仓库内置 examples/hooks/ 示例脚本,复制即用:echo-to-log.sh(把 payload 写入本地日志,配好 hooks.json 后 tail -f /tmp/botmux-hook.log 即可验证)、osascript-notify.sh(macOS 通知中心)、http-webhook.sh(HTTP webhook)。
用 session.start hook 自动更新 Skills:botmux 原生集成 agentbuddy 作为 skill 来源(botmux skills install <agentbuddy命令> 安装、botmux skills update <name> 更新)。配合 session.start hook 可在每次新会话启动时自动检查更新,等效于 Claude Code settings.json 的 SessionStart Hook:
[
{
"event": "session.start",
"command": "botmux skills update my-skill-name",
"timeoutMs": 60000
}
]注意事项:
botmux skills update只接受单个 skill 名称,不支持*或正则;更新全部需脚本循环(botmux skills list | cut -f1 | while read ...逐个 update)。- 想直接跑
npx agentbuddy update(更新用户全局 skills 而非 botmux 管理的 skills)时,受 hook 执行环境限制(shell: false不支持管道/重定向;环境变量被清洗,只保留 PATH/HOME/TMPDIR/SHELL/USER 等基础项),建议写成包装脚本(私有 npm 源在脚本内自行export npm_config_registry)。 - 默认
timeoutMs5000ms 对涉及网络请求的更新不够,必须显式加大(建议 60s+);超时后先SIGTERM再SIGKILL整个进程组。 - hook 异步执行,不阻塞会话启动;skill 更新完成后需新会话才生效。
- 可用
filter限定只对特定chatId/senderOpenId生效,避免所有会话都跑更新。 - 推荐优先使用
botmux skills update:它经过 botmux 的 telemetry 清理(clearAgentbuddyTelemetry),更新的是 botmux 注入的 skill 版本,与 botmux skill 生命周期一致。Skill 系统见 skill-cli。
写自己的 hook
hook 命令可以是任意 executable:bash / Python / Node / Go 二进制、公司内部 CLI、HTTP 转发器都行。命令 exit 0 视为成功;非 0 / 超时 / 找不到命令只写 botmux 日志,不会影响收发消息、定时任务或 session 生命周期。