botmux 2.9.1 → 2.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.en.md +140 -76
  2. package/README.md +134 -75
  3. package/dist/adapters/backend/pty-backend.d.ts +6 -0
  4. package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
  5. package/dist/adapters/backend/pty-backend.js +10 -0
  6. package/dist/adapters/backend/pty-backend.js.map +1 -1
  7. package/dist/adapters/backend/session-backend-selector.d.ts +11 -0
  8. package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -0
  9. package/dist/adapters/backend/session-backend-selector.js +26 -0
  10. package/dist/adapters/backend/session-backend-selector.js.map +1 -0
  11. package/dist/adapters/backend/tmux-backend.d.ts +80 -3
  12. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  13. package/dist/adapters/backend/tmux-backend.js +301 -49
  14. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  15. package/dist/adapters/backend/tmux-pipe-backend.d.ts +100 -0
  16. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -0
  17. package/dist/adapters/backend/tmux-pipe-backend.js +473 -0
  18. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -0
  19. package/dist/adapters/cli/aiden.d.ts.map +1 -1
  20. package/dist/adapters/cli/aiden.js +5 -0
  21. package/dist/adapters/cli/aiden.js.map +1 -1
  22. package/dist/adapters/cli/claude-code.d.ts +40 -1
  23. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  24. package/dist/adapters/cli/claude-code.js +470 -49
  25. package/dist/adapters/cli/claude-code.js.map +1 -1
  26. package/dist/adapters/cli/coco.d.ts.map +1 -1
  27. package/dist/adapters/cli/coco.js +191 -9
  28. package/dist/adapters/cli/coco.js.map +1 -1
  29. package/dist/adapters/cli/codex.d.ts.map +1 -1
  30. package/dist/adapters/cli/codex.js +94 -17
  31. package/dist/adapters/cli/codex.js.map +1 -1
  32. package/dist/adapters/cli/shared-hints.d.ts +2 -2
  33. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  34. package/dist/adapters/cli/shared-hints.js +7 -5
  35. package/dist/adapters/cli/shared-hints.js.map +1 -1
  36. package/dist/adapters/cli/types.d.ts +38 -1
  37. package/dist/adapters/cli/types.d.ts.map +1 -1
  38. package/dist/autostart.d.ts +14 -0
  39. package/dist/autostart.d.ts.map +1 -0
  40. package/dist/autostart.js +357 -0
  41. package/dist/autostart.js.map +1 -0
  42. package/dist/bot-registry.d.ts +29 -3
  43. package/dist/bot-registry.d.ts.map +1 -1
  44. package/dist/bot-registry.js +91 -12
  45. package/dist/bot-registry.js.map +1 -1
  46. package/dist/cli/arg-utils.d.ts +11 -0
  47. package/dist/cli/arg-utils.d.ts.map +1 -0
  48. package/dist/cli/arg-utils.js +25 -0
  49. package/dist/cli/arg-utils.js.map +1 -0
  50. package/dist/cli/create-group-resolver.d.ts +32 -0
  51. package/dist/cli/create-group-resolver.d.ts.map +1 -0
  52. package/dist/cli/create-group-resolver.js +70 -0
  53. package/dist/cli/create-group-resolver.js.map +1 -0
  54. package/dist/cli/quoted-render.d.ts +30 -0
  55. package/dist/cli/quoted-render.d.ts.map +1 -0
  56. package/dist/cli/quoted-render.js +29 -0
  57. package/dist/cli/quoted-render.js.map +1 -0
  58. package/dist/cli.js +916 -272
  59. package/dist/cli.js.map +1 -1
  60. package/dist/config.d.ts +6 -0
  61. package/dist/config.d.ts.map +1 -1
  62. package/dist/config.js +18 -8
  63. package/dist/config.js.map +1 -1
  64. package/dist/core/command-handler.d.ts +43 -0
  65. package/dist/core/command-handler.d.ts.map +1 -1
  66. package/dist/core/command-handler.js +167 -64
  67. package/dist/core/command-handler.js.map +1 -1
  68. package/dist/core/dashboard-events.d.ts +57 -0
  69. package/dist/core/dashboard-events.d.ts.map +1 -0
  70. package/dist/core/dashboard-events.js +23 -0
  71. package/dist/core/dashboard-events.js.map +1 -0
  72. package/dist/core/dashboard-ipc-server.d.ts +43 -0
  73. package/dist/core/dashboard-ipc-server.d.ts.map +1 -0
  74. package/dist/core/dashboard-ipc-server.js +481 -0
  75. package/dist/core/dashboard-ipc-server.js.map +1 -0
  76. package/dist/core/dashboard-locate.d.ts +20 -0
  77. package/dist/core/dashboard-locate.d.ts.map +1 -0
  78. package/dist/core/dashboard-locate.js +26 -0
  79. package/dist/core/dashboard-locate.js.map +1 -0
  80. package/dist/core/dashboard-rows.d.ts +31 -0
  81. package/dist/core/dashboard-rows.d.ts.map +1 -0
  82. package/dist/core/dashboard-rows.js +65 -0
  83. package/dist/core/dashboard-rows.js.map +1 -0
  84. package/dist/core/inherit-peer.d.ts +14 -0
  85. package/dist/core/inherit-peer.d.ts.map +1 -0
  86. package/dist/core/inherit-peer.js +32 -0
  87. package/dist/core/inherit-peer.js.map +1 -0
  88. package/dist/core/scheduler.d.ts +24 -0
  89. package/dist/core/scheduler.d.ts.map +1 -1
  90. package/dist/core/scheduler.js +93 -2
  91. package/dist/core/scheduler.js.map +1 -1
  92. package/dist/core/session-activity.d.ts +3 -0
  93. package/dist/core/session-activity.d.ts.map +1 -0
  94. package/dist/core/session-activity.js +20 -0
  95. package/dist/core/session-activity.js.map +1 -0
  96. package/dist/core/session-discovery.d.ts +39 -0
  97. package/dist/core/session-discovery.d.ts.map +1 -1
  98. package/dist/core/session-discovery.js +114 -21
  99. package/dist/core/session-discovery.js.map +1 -1
  100. package/dist/core/session-manager.d.ts +72 -0
  101. package/dist/core/session-manager.d.ts.map +1 -1
  102. package/dist/core/session-manager.js +396 -106
  103. package/dist/core/session-manager.js.map +1 -1
  104. package/dist/core/types.d.ts +27 -2
  105. package/dist/core/types.d.ts.map +1 -1
  106. package/dist/core/types.js +14 -3
  107. package/dist/core/types.js.map +1 -1
  108. package/dist/core/worker-pool.d.ts +72 -3
  109. package/dist/core/worker-pool.d.ts.map +1 -1
  110. package/dist/core/worker-pool.js +459 -38
  111. package/dist/core/worker-pool.js.map +1 -1
  112. package/dist/daemon.d.ts.map +1 -1
  113. package/dist/daemon.js +645 -314
  114. package/dist/daemon.js.map +1 -1
  115. package/dist/dashboard/aggregator.d.ts +41 -0
  116. package/dist/dashboard/aggregator.d.ts.map +1 -0
  117. package/dist/dashboard/aggregator.js +125 -0
  118. package/dist/dashboard/aggregator.js.map +1 -0
  119. package/dist/dashboard/auth.d.ts +23 -0
  120. package/dist/dashboard/auth.d.ts.map +1 -0
  121. package/dist/dashboard/auth.js +66 -0
  122. package/dist/dashboard/auth.js.map +1 -0
  123. package/dist/dashboard/operator-selector.d.ts +20 -0
  124. package/dist/dashboard/operator-selector.d.ts.map +1 -0
  125. package/dist/dashboard/operator-selector.js +39 -0
  126. package/dist/dashboard/operator-selector.js.map +1 -0
  127. package/dist/dashboard/registry.d.ts +35 -0
  128. package/dist/dashboard/registry.d.ts.map +1 -0
  129. package/dist/dashboard/registry.js +74 -0
  130. package/dist/dashboard/registry.js.map +1 -0
  131. package/dist/dashboard/web/app.d.ts +2 -0
  132. package/dist/dashboard/web/app.d.ts.map +1 -0
  133. package/dist/dashboard/web/app.js +45 -0
  134. package/dist/dashboard/web/app.js.map +1 -0
  135. package/dist/dashboard/web/bot-defaults.d.ts +2 -0
  136. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -0
  137. package/dist/dashboard/web/bot-defaults.js +201 -0
  138. package/dist/dashboard/web/bot-defaults.js.map +1 -0
  139. package/dist/dashboard/web/groups.d.ts +16 -0
  140. package/dist/dashboard/web/groups.d.ts.map +1 -0
  141. package/dist/dashboard/web/groups.js +584 -0
  142. package/dist/dashboard/web/groups.js.map +1 -0
  143. package/dist/dashboard/web/schedules.d.ts +2 -0
  144. package/dist/dashboard/web/schedules.d.ts.map +1 -0
  145. package/dist/dashboard/web/schedules.js +105 -0
  146. package/dist/dashboard/web/schedules.js.map +1 -0
  147. package/dist/dashboard/web/sessions.d.ts +2 -0
  148. package/dist/dashboard/web/sessions.d.ts.map +1 -0
  149. package/dist/dashboard/web/sessions.js +374 -0
  150. package/dist/dashboard/web/sessions.js.map +1 -0
  151. package/dist/dashboard/web/store.d.ts +23 -0
  152. package/dist/dashboard/web/store.d.ts.map +1 -0
  153. package/dist/dashboard/web/store.js +82 -0
  154. package/dist/dashboard/web/store.js.map +1 -0
  155. package/dist/dashboard-web/app.js +263 -0
  156. package/dist/dashboard-web/index.html +23 -0
  157. package/dist/dashboard-web/style.css +93 -0
  158. package/dist/dashboard.d.ts +2 -0
  159. package/dist/dashboard.d.ts.map +1 -0
  160. package/dist/dashboard.js +639 -0
  161. package/dist/dashboard.js.map +1 -0
  162. package/dist/im/lark/card-builder.d.ts +18 -1
  163. package/dist/im/lark/card-builder.d.ts.map +1 -1
  164. package/dist/im/lark/card-builder.js +70 -9
  165. package/dist/im/lark/card-builder.js.map +1 -1
  166. package/dist/im/lark/card-handler.d.ts.map +1 -1
  167. package/dist/im/lark/card-handler.js +123 -109
  168. package/dist/im/lark/card-handler.js.map +1 -1
  169. package/dist/im/lark/client.d.ts +35 -0
  170. package/dist/im/lark/client.d.ts.map +1 -1
  171. package/dist/im/lark/client.js +114 -11
  172. package/dist/im/lark/client.js.map +1 -1
  173. package/dist/im/lark/event-dispatcher.d.ts +88 -6
  174. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  175. package/dist/im/lark/event-dispatcher.js +398 -62
  176. package/dist/im/lark/event-dispatcher.js.map +1 -1
  177. package/dist/im/lark/forwarded-renderer.d.ts +23 -0
  178. package/dist/im/lark/forwarded-renderer.d.ts.map +1 -0
  179. package/dist/im/lark/forwarded-renderer.js +105 -0
  180. package/dist/im/lark/forwarded-renderer.js.map +1 -0
  181. package/dist/im/lark/md-card.d.ts +73 -0
  182. package/dist/im/lark/md-card.d.ts.map +1 -0
  183. package/dist/im/lark/md-card.js +332 -0
  184. package/dist/im/lark/md-card.js.map +1 -0
  185. package/dist/im/lark/merge-forward.d.ts +32 -0
  186. package/dist/im/lark/merge-forward.d.ts.map +1 -0
  187. package/dist/im/lark/merge-forward.js +110 -0
  188. package/dist/im/lark/merge-forward.js.map +1 -0
  189. package/dist/im/lark/message-parser.d.ts +9 -3
  190. package/dist/im/lark/message-parser.d.ts.map +1 -1
  191. package/dist/im/lark/message-parser.js +48 -13
  192. package/dist/im/lark/message-parser.js.map +1 -1
  193. package/dist/im/lark/quote-hint.d.ts +18 -0
  194. package/dist/im/lark/quote-hint.d.ts.map +1 -0
  195. package/dist/im/lark/quote-hint.js +23 -0
  196. package/dist/im/lark/quote-hint.js.map +1 -0
  197. package/dist/services/bridge-fallback-gate.d.ts +42 -0
  198. package/dist/services/bridge-fallback-gate.d.ts.map +1 -0
  199. package/dist/services/bridge-fallback-gate.js +12 -0
  200. package/dist/services/bridge-fallback-gate.js.map +1 -0
  201. package/dist/services/bridge-rotation-policy.d.ts +139 -0
  202. package/dist/services/bridge-rotation-policy.d.ts.map +1 -0
  203. package/dist/services/bridge-rotation-policy.js +125 -0
  204. package/dist/services/bridge-rotation-policy.js.map +1 -0
  205. package/dist/services/bridge-turn-queue.d.ts +154 -0
  206. package/dist/services/bridge-turn-queue.d.ts.map +1 -0
  207. package/dist/services/bridge-turn-queue.js +316 -0
  208. package/dist/services/bridge-turn-queue.js.map +1 -0
  209. package/dist/services/chat-first-seen-store.d.ts +27 -0
  210. package/dist/services/chat-first-seen-store.d.ts.map +1 -0
  211. package/dist/services/chat-first-seen-store.js +114 -0
  212. package/dist/services/chat-first-seen-store.js.map +1 -0
  213. package/dist/services/claude-transcript.d.ts +268 -0
  214. package/dist/services/claude-transcript.d.ts.map +1 -0
  215. package/dist/services/claude-transcript.js +798 -0
  216. package/dist/services/claude-transcript.js.map +1 -0
  217. package/dist/services/coco-transcript.d.ts +35 -0
  218. package/dist/services/coco-transcript.d.ts.map +1 -0
  219. package/dist/services/coco-transcript.js +192 -0
  220. package/dist/services/coco-transcript.js.map +1 -0
  221. package/dist/services/codex-bridge-queue.d.ts +56 -0
  222. package/dist/services/codex-bridge-queue.d.ts.map +1 -0
  223. package/dist/services/codex-bridge-queue.js +150 -0
  224. package/dist/services/codex-bridge-queue.js.map +1 -0
  225. package/dist/services/codex-transcript.d.ts +84 -0
  226. package/dist/services/codex-transcript.d.ts.map +1 -0
  227. package/dist/services/codex-transcript.js +298 -0
  228. package/dist/services/codex-transcript.js.map +1 -0
  229. package/dist/services/group-creator.d.ts +23 -0
  230. package/dist/services/group-creator.d.ts.map +1 -0
  231. package/dist/services/group-creator.js +75 -0
  232. package/dist/services/group-creator.js.map +1 -0
  233. package/dist/services/groups-store.d.ts +98 -0
  234. package/dist/services/groups-store.d.ts.map +1 -0
  235. package/dist/services/groups-store.js +213 -0
  236. package/dist/services/groups-store.js.map +1 -0
  237. package/dist/services/oncall-store.d.ts +80 -8
  238. package/dist/services/oncall-store.d.ts.map +1 -1
  239. package/dist/services/oncall-store.js +265 -55
  240. package/dist/services/oncall-store.js.map +1 -1
  241. package/dist/services/project-scanner.d.ts +1 -2
  242. package/dist/services/project-scanner.d.ts.map +1 -1
  243. package/dist/services/project-scanner.js +118 -68
  244. package/dist/services/project-scanner.js.map +1 -1
  245. package/dist/services/schedule-store.d.ts +5 -0
  246. package/dist/services/schedule-store.d.ts.map +1 -1
  247. package/dist/services/schedule-store.js +77 -1
  248. package/dist/services/schedule-store.js.map +1 -1
  249. package/dist/services/session-store.d.ts +22 -0
  250. package/dist/services/session-store.d.ts.map +1 -1
  251. package/dist/services/session-store.js +62 -4
  252. package/dist/services/session-store.js.map +1 -1
  253. package/dist/setup/bots-store.d.ts +3 -0
  254. package/dist/setup/bots-store.d.ts.map +1 -0
  255. package/dist/setup/bots-store.js +24 -0
  256. package/dist/setup/bots-store.js.map +1 -0
  257. package/dist/setup/detect-platform.d.ts +14 -0
  258. package/dist/setup/detect-platform.d.ts.map +1 -0
  259. package/dist/setup/detect-platform.js +139 -0
  260. package/dist/setup/detect-platform.js.map +1 -0
  261. package/dist/setup/ensure-fonts.d.ts +13 -0
  262. package/dist/setup/ensure-fonts.d.ts.map +1 -0
  263. package/dist/setup/ensure-fonts.js +225 -0
  264. package/dist/setup/ensure-fonts.js.map +1 -0
  265. package/dist/setup/ensure-tmux.d.ts +60 -0
  266. package/dist/setup/ensure-tmux.d.ts.map +1 -0
  267. package/dist/setup/ensure-tmux.js +236 -0
  268. package/dist/setup/ensure-tmux.js.map +1 -0
  269. package/dist/setup/index.d.ts +9 -0
  270. package/dist/setup/index.d.ts.map +1 -0
  271. package/dist/setup/index.js +46 -0
  272. package/dist/setup/index.js.map +1 -0
  273. package/dist/setup/lark-scopes.json +301 -0
  274. package/dist/setup/register-app.d.ts +52 -0
  275. package/dist/setup/register-app.d.ts.map +1 -0
  276. package/dist/setup/register-app.js +91 -0
  277. package/dist/setup/register-app.js.map +1 -0
  278. package/dist/setup/verify-permissions.d.ts +115 -0
  279. package/dist/setup/verify-permissions.d.ts.map +1 -0
  280. package/dist/setup/verify-permissions.js +207 -0
  281. package/dist/setup/verify-permissions.js.map +1 -0
  282. package/dist/skills/definitions.d.ts +4 -0
  283. package/dist/skills/definitions.d.ts.map +1 -1
  284. package/dist/skills/definitions.js +133 -19
  285. package/dist/skills/definitions.js.map +1 -1
  286. package/dist/skills/installer.d.ts +3 -1
  287. package/dist/skills/installer.d.ts.map +1 -1
  288. package/dist/skills/installer.js +18 -3
  289. package/dist/skills/installer.js.map +1 -1
  290. package/dist/types.d.ts +44 -0
  291. package/dist/types.d.ts.map +1 -1
  292. package/dist/utils/bot-routing.d.ts +6 -0
  293. package/dist/utils/bot-routing.d.ts.map +1 -0
  294. package/dist/utils/bot-routing.js +50 -0
  295. package/dist/utils/bot-routing.js.map +1 -0
  296. package/dist/utils/file-lock.d.ts +2 -0
  297. package/dist/utils/file-lock.d.ts.map +1 -0
  298. package/dist/utils/file-lock.js +114 -0
  299. package/dist/utils/file-lock.js.map +1 -0
  300. package/dist/utils/font-installer.js +1 -1
  301. package/dist/utils/font-installer.js.map +1 -1
  302. package/dist/utils/idle-detector.d.ts +6 -0
  303. package/dist/utils/idle-detector.d.ts.map +1 -1
  304. package/dist/utils/idle-detector.js +25 -4
  305. package/dist/utils/idle-detector.js.map +1 -1
  306. package/dist/utils/logger.d.ts +10 -0
  307. package/dist/utils/logger.d.ts.map +1 -1
  308. package/dist/utils/logger.js +60 -8
  309. package/dist/utils/logger.js.map +1 -1
  310. package/dist/utils/render-dimensions.d.ts +48 -0
  311. package/dist/utils/render-dimensions.d.ts.map +1 -0
  312. package/dist/utils/render-dimensions.js +55 -0
  313. package/dist/utils/render-dimensions.js.map +1 -0
  314. package/dist/utils/screen-analyzer.d.ts.map +1 -1
  315. package/dist/utils/screen-analyzer.js +24 -0
  316. package/dist/utils/screen-analyzer.js.map +1 -1
  317. package/dist/utils/screenshot-renderer.d.ts.map +1 -1
  318. package/dist/utils/screenshot-renderer.js +67 -23
  319. package/dist/utils/screenshot-renderer.js.map +1 -1
  320. package/dist/utils/terminal-renderer.d.ts +16 -0
  321. package/dist/utils/terminal-renderer.d.ts.map +1 -1
  322. package/dist/utils/terminal-renderer.js +40 -23
  323. package/dist/utils/terminal-renderer.js.map +1 -1
  324. package/dist/utils/transient-snapshot.d.ts +28 -0
  325. package/dist/utils/transient-snapshot.d.ts.map +1 -0
  326. package/dist/utils/transient-snapshot.js +96 -0
  327. package/dist/utils/transient-snapshot.js.map +1 -0
  328. package/dist/worker.js +2248 -83
  329. package/dist/worker.js.map +1 -1
  330. package/package.json +12 -5
package/README.en.md CHANGED
@@ -48,7 +48,7 @@ Compared to OpenClaw-style approaches built on Agent SDKs:
48
48
  | Feature | botmux | OpenClaw-style |
49
49
  |---------|--------|---------------|
50
50
  | Architecture | Bridges full CLI processes directly | Rebuilds on Agent SDK |
51
- | CLI Capabilities | Full runtime (hooks, memory, plan mode, MCP ecosystem, `/` commands) | SDK API subset, missing features must be reimplemented |
51
+ | CLI Capabilities | Full runtime (hooks, memory, plan mode, skills, `/` commands) | SDK API subset, missing features must be reimplemented |
52
52
  | CLI Upgrades | Zero-adaptation automatic benefit | Must track SDK version changes |
53
53
  | Memory / Context | Reuses CLI's built-in memory system, improves as the CLI evolves | Must build custom memory system, duplicating CLI-native capabilities |
54
54
  | Multi-CLI Support | 4 CLIs, switch with one config (Claude Code / Codex / Gemini / OpenCode) | Tied to a single SDK, cannot switch CLIs |
@@ -71,78 +71,73 @@ Compared to OpenClaw-style approaches built on Agent SDKs:
71
71
 
72
72
  ## 5-Minute Setup
73
73
 
74
+ > 💡 **TL;DR**: run `botmux setup` and pick "scan-to-create" to finish Steps 1+2 in one shot (the official `@larksuiteoapi/node-sdk` device flow gives you the AppID/AppSecret). PersonalAgent apps come with event subscriptions and bot capability pre-configured, so only Step 4 (permissions) + Step 5 (optional redirect URL) + Step 6 (publish) require browser clicks; the setup wizard writes a JSON file with a one-line clipboard copy command and prints deep-links to each remaining step.
75
+
74
76
  ### Step 1: Create a Lark App
75
77
 
76
- Go to the [Lark Open Platform](https://open.larkoffice.com/app) and click "Create Custom App".
78
+ **Recommended**: `botmux setup` → pick "1) Scan-to-create app". Scan with the Lark mobile app and the AppID/AppSecret are persisted automatically; no manual browser navigation. Falls back to manual paste on cancel/timeout/network error.
79
+
80
+ > ⚠️ **Currently only Feishu (feishu.cn) tenants are supported.** If scan detects a Lark international (larksuite.com) tenant, setup aborts — the daemon runtime (Lark Client/WSClient/event-dispatcher) hasn't been wired up for the `larksuite.com` domain yet, so accepting Lark credentials would land users in a half-working state. A follow-up PR will add full Lark support.
81
+
82
+ **Manual**: go to the [Lark Open Platform](https://open.larkoffice.com/app) and click "Create Custom App".
77
83
 
78
84
  ![Create App](docs/setup/create-app.png)
79
85
 
80
86
  ### Step 2: Get Credentials
81
87
 
88
+ > The scan-to-create path completes this step automatically; skip to Step 3.
89
+
82
90
  Open the app details page → "Credentials & Basic Info", and copy the **App ID** and **App Secret**.
83
91
 
84
92
  ![Get Credentials](docs/setup/credentials.png)
85
93
 
86
- ### Step 3: Add Permissions
87
-
88
- Go to "Permissions & Scopes" → "Batch Import/Export", and paste the following JSON to import all permissions at once:
89
-
90
- ![Permissions](docs/setup/permissions.png)
91
-
92
- <details>
93
- <summary>Click to expand batch import JSON</summary>
94
-
95
- ```json
96
- {
97
- "scopes": {
98
- "tenant": [
99
- "contact:user.base:readonly",
100
- "contact:user.id:readonly",
101
- "im:chat:read",
102
- "im:chat.members:bot_access",
103
- "im:chat.members:read",
104
- "im:message",
105
- "im:message:readonly",
106
- "im:message:send_as_bot",
107
- "im:message:update",
108
- "im:message.group_at_msg",
109
- "im:message.group_at_msg:readonly",
110
- "im:message.group_msg",
111
- "im:message.p2p_msg:readonly",
112
- "im:message.reactions:write_only",
113
- "im:resource"
114
- ]
115
- }
116
- }
117
- ```
118
- </details>
119
-
120
- ### Step 4: Install & Start botmux
94
+ ### Step 3: Install & Start botmux
121
95
 
122
96
  ```bash
123
97
  # Install
124
98
  npm install -g botmux
125
99
 
126
- # Interactive setup — enter the App ID and App Secret from Step 2
100
+ # Interactive setup — pick "1) Scan-to-create app" or "2) Paste AppID/Secret manually".
101
+ # Credentials are validated with a tenant_access_token call before bots.json is written.
102
+ # At the end of setup the wizard writes the full scope JSON to ~/.botmux/lark-scopes.json
103
+ # and prints a one-line clipboard copy command for your platform.
127
104
  botmux setup
128
105
 
129
- # Start (must be running before configuring WebSocket subscription Lark checks for an active connection)
106
+ # Start (if you ever need to verify the event subscription, Lark requires the daemon to be running so it can detect the WebSocket connection)
107
+ # Re-validates credentials before forking workers; missing scopes only WARN, do not block the daemon.
130
108
  botmux start
131
109
  ```
132
110
 
133
- ### Step 5: Configure Event Subscription
111
+ ### Step 4: Add Permissions
134
112
 
135
- Back in the Lark Open Platform, go to "Events & Callbacks":
113
+ Run the copy-to-clipboard command setup printed, then go to "Permissions & Scopes" → "Batch Import/Export" and paste. Submit for review — visibility "only me" auto-approves.
136
114
 
137
- 1. **Subscription mode**: Click the edit icon, select "Receive events via persistent connection" (WebSocket) — requires botmux to be running so Lark can detect the connection
115
+ ![Permissions](docs/setup/permissions.png)
138
116
 
139
- ![WebSocket subscription](docs/setup/event-websocket.png)
117
+ The full JSON lives at `~/.botmux/lark-scopes.json` (also tracked in-repo at [src/setup/lark-scopes.json](src/setup/lark-scopes.json), kept in sync with the internal wiki, covers ~290 tenant + user scopes).
140
118
 
141
- 2. **Add event**: Click "Add Event", search and add `im.message.receive_v1` (Receive messages v2.0)
119
+ ```bash
120
+ # macOS (local)
121
+ cat ~/.botmux/lark-scopes.json | pbcopy
122
+ # Linux desktop (local X server)
123
+ cat ~/.botmux/lark-scopes.json | xclip -selection clipboard
124
+ # SSH / headless: just cat — selecting in your local terminal copies to your local clipboard
125
+ cat ~/.botmux/lark-scopes.json
126
+ # SSH via OSC 52 — write to local clipboard through terminal (iTerm2 / kitty / WezTerm / Alacritty / tmux 1.5+)
127
+ base64 -w0 < ~/.botmux/lark-scopes.json | awk 'BEGIN{printf "\033]52;c;"}{printf "%s",$0}END{printf "\a"}'
128
+ ```
129
+
130
+ > Scan-created PersonalAgent apps have `im.message.receive_v1` + `card.action.trigger` subscribed and the bot capability enabled out of the box, per botmux maintainer testing. Lark hasn't documented this as stable behavior, so **if the bot receives no messages at all after setup**, see "Step 8: Troubleshoot — bot not receiving messages" below for a manual fallback.
131
+
132
+ ### Step 5: Add Redirect URL (optional)
142
133
 
143
- ![Add event](docs/setup/event-receive-msg.png)
134
+ If you plan to use `/login` inside Lark to let botmux act on your behalf for docs / calendar / wiki / sheets, add a redirect URL under "Security Settings" → "Redirect URL":
144
135
 
145
- 3. **Enable callback**: Switch to the "Callback Configuration" tab, turn on "Card action callback" (`card.action.trigger`)
136
+ ```
137
+ http://127.0.0.1:9768/callback
138
+ ```
139
+
140
+ Skip this step if you only need bot messaging.
146
141
 
147
142
  ### Step 6: Publish the App
148
143
 
@@ -158,6 +153,25 @@ Go to "Version Management & Release", click "Create Version" and publish. Set av
158
153
 
159
154
  ![Add bot to group](docs/setup/add-bot-to-group.png)
160
155
 
156
+ ### Step 8: Troubleshoot — bot not receiving messages (fallback)
157
+
158
+ PersonalAgent apps come with event subscriptions and bot capability pre-configured; in normal cases you don't touch this. If the bot **receives no messages at all** after setup (not even DMs), verify these two settings:
159
+
160
+ - **Event subscription**: Open Platform → your app → Events & Callbacks → should be subscribed to `im.message.receive_v1` + `card.action.trigger`. If missing, add them manually. Subscription mode must be "Receive via persistent connection" (WebSocket), and the botmux daemon must be running.
161
+ - **Bot capability**: Open Platform → your app → Features → Bot should be enabled (it is by default). Adjust name/avatar if needed.
162
+
163
+ After verifying, restart: `botmux restart`.
164
+
165
+ ### Step 9: Enable Boot-time Autostart (recommended)
166
+
167
+ Once the bot is sending and receiving messages cleanly, run:
168
+
169
+ ```bash
170
+ botmux autostart enable
171
+ ```
172
+
173
+ This registers the daemon with your user's init system (launchd on macOS, user systemd on Linux). **No sudo required.** After a reboot — or after logging back in — the daemon comes up on its own. See [CLI Commands § Boot-time Autostart](#boot-time-autostart) below for the full reference.
174
+
161
175
  ---
162
176
 
163
177
  ## Features
@@ -182,7 +196,7 @@ On mobile/tablet, a floating shortcut toolbar provides Esc, Ctrl+C, Tab, arrow k
182
196
 
183
197
  ### Multi-Bot Collaboration
184
198
 
185
- Run multiple Lark bots on a single machine, each mapped to a different CLI. In the same group chat, messages are routed via @mention — each bot gets its own isolated CLI process. With a single bot in the group, it responds automatically without @.
199
+ Run multiple Lark bots on a single machine, each mapped to a different CLI. In the same group chat, messages are routed via @mention — each bot gets its own isolated CLI process. With a single bot in the group, it responds automatically without @. In a regular (non-topic) group, `@<bot1> @<bot2> /t xxx` spawns one independent thread per mentioned bot anchored at the same message.
186
200
 
187
201
  ### Tmux Persistence
188
202
 
@@ -191,8 +205,8 @@ When tmux is installed, botmux automatically uses it. CLI processes persist insi
191
205
  **Key benefit: daemon restarts don't interrupt the CLI.** During `botmux restart`, the worker process exits but the tmux session (and the CLI inside it) keeps running. The next incoming message triggers a re-attach — no `--resume` context reload needed.
192
206
 
193
207
  ```bash
194
- # Recommended: interactive session picker — select and attach to tmux
195
- npx botmux list
208
+ # Interactive session picker — select and attach to tmux (see § CLI Commands)
209
+ botmux list
196
210
 
197
211
  # Or manually attach (session name = bmx-<first 8 chars of session ID>)
198
212
  tmux attach -t bmx-<first-8-chars-of-session-id>
@@ -202,10 +216,6 @@ tmux attach -t bmx-<first-8-chars-of-session-id>
202
216
  BACKEND_TYPE=pty botmux start
203
217
  ```
204
218
 
205
- `botmux list` provides an interactive TUI showing all active sessions with ID, title, working directory, PID, uptime, and status. Use arrow keys to select and Enter to attach. Use `botmux list --plain` for plain-text table output suitable for scripting.
206
-
207
- **Session naming:** `bmx-<first 8 chars of session UUID>`
208
-
209
219
  **Lifecycle:**
210
220
 
211
221
  | Event | tmux session | CLI process |
@@ -246,13 +256,28 @@ When a CLI spawns inside a botmux session it automatically gets
246
256
  `~/.botmux/bin` on PATH plus a set of ready-to-use Skills:
247
257
 
248
258
  - `botmux send` — send a message to the current thread (text, images, files, @mention)
249
- - `botmux thread messages` — fetch thread history
259
+ - `botmux history` — fetch session history (topic groups → in-thread, regular groups → whole chat)
260
+ - `botmux quoted <message_id>` — when the user @ed the bot via Lark's quote-reply UI, fetch the quoted message on demand
250
261
  - `botmux bots list` — discover bots + their `open_id`s
251
262
  - `botmux schedule` — manage scheduled tasks
252
263
 
253
264
  These capabilities are wired via `--append-system-prompt` and Skill
254
- descriptions, so the agent picks them up automatically. The pre-April-2026
255
- MCP entry point has been removed (stale config is auto-cleaned on upgrade).
265
+ descriptions, so the agent picks them up automatically. Compared to
266
+ Anthropic's official Telegram channel which exposes each action as an
267
+ MCP tool — the Skill + CLI combo skips the MCP handshake on every CLI
268
+ launch, doesn't burn tool-list tokens, and works across every CLI that
269
+ can read a system prompt and shell out (Claude Code / Codex / Gemini /
270
+ OpenCode), with no MCP protocol support required.
271
+
272
+ ### Dashboard
273
+
274
+ > `botmux dashboard` issues a one-time-token URL — manage every daemon/bot from the browser.
275
+
276
+ - One-click locate back to the Feishu thread / open Web Terminal / multi-select batch close
277
+ - Create a new group with auto owner-transfer + @-mention notification
278
+ - Disband or leave a chat (associated sessions auto-closed)
279
+
280
+ <img src="docs/dashboard.png" alt="botmux dashboard" width="800" />
256
281
 
257
282
  ---
258
283
 
@@ -260,8 +285,8 @@ MCP entry point has been removed (stale config is auto-cleaned on upgrade).
260
285
 
261
286
  ### Workflow
262
287
 
263
- 1. Send a message in your Lark topic group to create a new thread
264
- 2. The bot shows a repo selection card — pick a project or click "Start directly"
288
+ 1. Send a message in a Lark topic group to create a new thread; or in a regular group send `/t <prompt>` to force-open a new topic
289
+ 2. The bot shows a repo selection card — pick a project or click "Start directly" (chats bound via `/oncall bind` skip this step)
265
290
  3. The CLI spawns in the selected directory
266
291
  4. A live streaming card appears in the thread, showing real-time terminal output with markdown rendering
267
292
  5. Each reply creates a new streaming card for that turn; previous cards freeze at their last state
@@ -278,20 +303,21 @@ MCP entry point has been removed (stale config is auto-cleaned on upgrade).
278
303
  | `/cd <path>` | Change working directory |
279
304
  | `/status` | Show session info (uptime, terminal URL, etc.) |
280
305
  | `/restart` | Restart CLI process |
281
- | `/close` | Close session and terminate CLI |
306
+ | `/close` | Close session and send a resumable card (with the CLI's native resume command) |
307
+ | `/t <prompt>` / `/topic <prompt>` | Force-open a new topic from a non-topic group (shows the repo selector); empty prompt is allowed — fill it in after picking the repo |
308
+ | `/oncall bind <path>` | Bind current chat to a project dir, skip the repo card (any group member can @ the bot; buttons / daemon commands still gated by `allowedUsers`) |
309
+ | `/oncall unbind` / `/oncall status` | Unbind / inspect oncall binding |
282
310
  | `/adopt` | Adopt a running CLI session (tmux) |
283
311
  | `/schedule` | Manage scheduled tasks |
312
+ | `/login` / `/login status` | Lark user OAuth (e.g. to download images from third-party cards) / show OAuth status |
284
313
  | `/help` | Show available commands |
285
314
  | `/compact` `/model` `/clear` `/plugin` `/usage` | Forwarded verbatim to the underlying CLI (e.g. Claude Code's built-in slash commands) |
286
315
 
287
316
  ### Scheduled Task Management
288
317
 
289
- **Recommended: talk to the agent**
290
- Just say "add a reminder to summarize yesterday's PRs every morning at 9:00" — the `botmux-schedule` Skill handles it and confirms with you.
318
+ Two creation paths are covered above in [Scheduled Tasks](#scheduled-tasks); below is just the slash-command syntax and management commands.
291
319
 
292
- **Slash command (quick)**
293
-
294
- ```
320
+ ```bash
295
321
  # Chinese NL
296
322
  /schedule 每日17:50 check AI news
297
323
  /schedule 工作日每天9:00 run health check
@@ -301,22 +327,14 @@ Just say "add a reminder to summarize yesterday's PRs every morning at 9:00" —
301
327
  /schedule 30分钟后 verify deployment
302
328
  /schedule 明天9:00 standup reminder
303
329
 
304
- # English
330
+ # English / cron
305
331
  /schedule every 2h probe services
306
332
  /schedule 30m remind me to drink water
307
-
308
- # Cron
309
333
  /schedule 0 9 * * * good morning
310
- ```
311
-
312
- Manage tasks:
313
334
 
314
- ```
335
+ # Manage
315
336
  /schedule list
316
- /schedule remove <id>
317
- /schedule enable <id>
318
- /schedule disable <id>
319
- /schedule run <id>
337
+ /schedule remove|enable|disable|run <id>
320
338
  ```
321
339
 
322
340
  **Execution behavior**: the task fires inside the **original thread where it was created** — no new topic per run. Working directory is preserved. If the original session is still alive, the prompt is injected into it; otherwise a fresh worker spawns bound to the same thread root.
@@ -362,6 +380,7 @@ botmux setup
362
380
  | `workingDir` | No | Default working directory, supports comma-separated |
363
381
  | `allowedUsers` | No | Allowed users (email prefixes or open_ids) |
364
382
  | `projectScanDir` | No | Directory to scan for git repos |
383
+ | `oncallChats` | No | Oncall bindings (written by `/oncall bind`), e.g. `[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]`; any group member can @ the bot |
365
384
 
366
385
  **Config priority:** `BOTS_CONFIG` env var > `~/.botmux/bots.json`
367
386
 
@@ -400,6 +419,22 @@ botmux setup
400
419
  | `botmux delete <id>` | Close a session by ID prefix (alias: `del`/`rm`) |
401
420
  | `botmux delete all` | Close all active sessions |
402
421
  | `botmux delete stopped` | Clean up zombie sessions with dead processes |
422
+ | `botmux autostart enable` | Register boot-time autostart (macOS launchd / Linux user systemd, no sudo) |
423
+ | `botmux autostart disable` | Unregister boot-time autostart |
424
+ | `botmux autostart status` | Show autostart status |
425
+ | `botmux dashboard` | Print a fresh Web Dashboard URL (rotates the token; previous URL becomes invalid) |
426
+
427
+ ### Boot-time Autostart
428
+
429
+ `botmux autostart enable` registers the daemon with your user's init system so it comes back automatically after a reboot:
430
+
431
+ - **macOS**: writes `~/Library/LaunchAgents/com.botmux.daemon.plist` and loads it via `launchctl bootstrap`. **No sudo required.**
432
+ - **Linux**: writes `~/.config/systemd/user/botmux.service` and runs `systemctl --user enable --now`. **No sudo required.**
433
+ - On servers / headless boxes the user systemd manager stops when you log out. To survive logouts and reboots, also run `sudo loginctl enable-linger <your-user>` — `autostart enable` warns when linger is off.
434
+ - Containers / SSH-only sessions without a user DBus fall back to printing manual instructions.
435
+ - The `node` and `cli.js` paths baked into the unit come from `process.execPath` at install time. After switching nvm/fnm versions, run `botmux autostart enable` once to rewrite. `botmux start`/`restart` also detect path drift and refresh the unit in place — no manual step needed.
436
+ - `enable` / `disable` **only manage the autostart hook — they do not touch a running daemon**. To start the daemon right away run `botmux start`; to stop it run `botmux stop`. This avoids the "I just wanted to turn off autostart, why did my service also die" footgun.
437
+ - If you prefer letting systemd own the lifecycle (`systemctl --user start/stop botmux`), that works too — the unit declares `ExecStop=botmux stop` for a clean shutdown path.
403
438
 
404
439
  ### Agent-facing subcommands
405
440
 
@@ -409,7 +444,8 @@ Run from inside a botmux-spawned CLI session — session context is auto-detecte
409
444
  |------------|-------------|
410
445
  | `botmux send [content]` | Send a message to the current thread (stdin / heredoc / `--content-file`; `--images` / `--files` / `--mention` flags) |
411
446
  | `botmux bots list` | List bots in the current chat (includes `open_id` for `--mention`) |
412
- | `botmux thread messages [--limit N]` | Fetch thread message history (JSON) |
447
+ | `botmux history [--limit N]` | Fetch session message history (JSON); topic groups → in-thread, regular groups → whole chat |
448
+ | `botmux quoted <message_id>` | Fetch a single quoted message (JSON); the ID comes from the daemon-injected `[用户引用了消息 用 botmux quoted om_xxx 查看]` prefix |
413
449
  | `botmux schedule add <schedule> <prompt>` | Create a scheduled task bound to the current thread |
414
450
  | `botmux schedule list/remove/pause/resume/run` | Manage scheduled tasks |
415
451
 
@@ -417,6 +453,34 @@ These require the `~/.botmux/bin/botmux` wrapper, which the daemon writes at sta
417
453
 
418
454
  ---
419
455
 
456
+ ## Web Dashboard
457
+
458
+ botmux ships a LAN-accessible Web Dashboard for managing all sessions and scheduled tasks across every configured bot.
459
+
460
+ ```bash
461
+ botmux dashboard
462
+ # prints: http://<lan-ip>:7891/?t=<token>
463
+ ```
464
+
465
+ Each invocation rotates the token — previous URLs are invalidated immediately. This is by design, so a leaked link stops working as soon as you fetch a new one.
466
+
467
+ v1 features:
468
+ - **Sessions board** — every active and closed session across every bot, filterable by CLI / status / adopt / free-text. The detail drawer exposes a "📍 定位到飞书话题" button that posts a marker into the original thread (workaround for Feishu having no public topic deep-link), then opens AppLink to the chat. Also: copy IDs, close session, open xterm.
469
+ - **Schedules board** — every scheduled task across every bot, with Run-now / Pause / Resume actions.
470
+
471
+ Environment variables (set in `~/.botmux/.env`):
472
+
473
+ | Variable | Default | Purpose |
474
+ |----------|---------|---------|
475
+ | `BOTMUX_DASHBOARD_HOST` | `0.0.0.0` | Dashboard HTTP bind address |
476
+ | `BOTMUX_DASHBOARD_PORT` | `7891` | Dashboard HTTP port |
477
+ | `BOTMUX_DASHBOARD_EXTERNAL_HOST` | `WEB_EXTERNAL_HOST` or LAN-IP autodetect | Host used in the printed URL |
478
+ | `BOTMUX_DAEMON_IPC_BASE_PORT` | `7892` | Per-daemon IPC port = base + botIndex |
479
+
480
+ The dashboard runs as its own pm2 process (`botmux-dashboard`) — `pnpm daemon:restart` brings it up alongside every bot daemon. Each daemon exposes a localhost-only IPC at `127.0.0.1:7892+botIndex`; the dashboard process is a thin reverse proxy + token gate. The HMAC secret at `~/.botmux/.dashboard-secret` (mode `0600`) is generated on first start and is used only to sign `botmux dashboard` rotation requests — it never reaches the browser.
481
+
482
+ ---
483
+
420
484
  ## Contributing
421
485
 
422
486
  See [CONTRIBUTING.md](CONTRIBUTING.md).