clawdbot 2026.1.4

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 (503) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/LICENSE +21 -0
  3. package/README-header.png +0 -0
  4. package/README.md +297 -0
  5. package/dist/agents/agent-paths.js +17 -0
  6. package/dist/agents/bash-process-registry.js +126 -0
  7. package/dist/agents/bash-tools.js +837 -0
  8. package/dist/agents/clawdbot-tools.js +30 -0
  9. package/dist/agents/clawdis-tools.js +27 -0
  10. package/dist/agents/context.js +34 -0
  11. package/dist/agents/defaults.js +6 -0
  12. package/dist/agents/model-auth.js +112 -0
  13. package/dist/agents/model-catalog.js +55 -0
  14. package/dist/agents/model-fallback.js +191 -0
  15. package/dist/agents/model-scan.js +263 -0
  16. package/dist/agents/model-selection.js +116 -0
  17. package/dist/agents/models-config.js +49 -0
  18. package/dist/agents/pi-embedded-helpers.js +74 -0
  19. package/dist/agents/pi-embedded-runner.js +407 -0
  20. package/dist/agents/pi-embedded-subscribe.js +568 -0
  21. package/dist/agents/pi-embedded-utils.js +20 -0
  22. package/dist/agents/pi-embedded.js +1 -0
  23. package/dist/agents/pi-oauth.js +88 -0
  24. package/dist/agents/pi-tools.js +433 -0
  25. package/dist/agents/sandbox-paths.js +68 -0
  26. package/dist/agents/sandbox.js +644 -0
  27. package/dist/agents/shell-utils.js +53 -0
  28. package/dist/agents/skills-install.js +244 -0
  29. package/dist/agents/skills-status.js +157 -0
  30. package/dist/agents/skills.js +470 -0
  31. package/dist/agents/steerable-agent-loop.js +338 -0
  32. package/dist/agents/steerable-provider-transport.js +48 -0
  33. package/dist/agents/system-prompt.js +104 -0
  34. package/dist/agents/tool-display.js +162 -0
  35. package/dist/agents/tool-images.js +138 -0
  36. package/dist/agents/tools/browser-tool.js +339 -0
  37. package/dist/agents/tools/canvas-tool.js +193 -0
  38. package/dist/agents/tools/common.js +88 -0
  39. package/dist/agents/tools/cron-tool.js +124 -0
  40. package/dist/agents/tools/discord-actions-guild.js +186 -0
  41. package/dist/agents/tools/discord-actions-messaging.js +285 -0
  42. package/dist/agents/tools/discord-actions-moderation.js +70 -0
  43. package/dist/agents/tools/discord-actions.js +56 -0
  44. package/dist/agents/tools/discord-schema.js +199 -0
  45. package/dist/agents/tools/discord-tool.js +16 -0
  46. package/dist/agents/tools/gateway-tool.js +46 -0
  47. package/dist/agents/tools/gateway.js +27 -0
  48. package/dist/agents/tools/image-tool.js +132 -0
  49. package/dist/agents/tools/nodes-tool.js +413 -0
  50. package/dist/agents/tools/nodes-utils.js +92 -0
  51. package/dist/agents/tools/sessions-helpers.js +88 -0
  52. package/dist/agents/tools/sessions-history-tool.js +53 -0
  53. package/dist/agents/tools/sessions-list-tool.js +143 -0
  54. package/dist/agents/tools/sessions-send-helpers.js +100 -0
  55. package/dist/agents/tools/sessions-send-tool.js +347 -0
  56. package/dist/agents/tools/slack-actions.js +129 -0
  57. package/dist/agents/tools/slack-schema.js +59 -0
  58. package/dist/agents/tools/slack-tool.js +16 -0
  59. package/dist/agents/usage.js +39 -0
  60. package/dist/agents/workspace.js +241 -0
  61. package/dist/auto-reply/chunk.js +76 -0
  62. package/dist/auto-reply/envelope.js +38 -0
  63. package/dist/auto-reply/group-activation.js +20 -0
  64. package/dist/auto-reply/heartbeat.js +57 -0
  65. package/dist/auto-reply/model.js +14 -0
  66. package/dist/auto-reply/reply/abort.js +14 -0
  67. package/dist/auto-reply/reply/agent-runner.js +371 -0
  68. package/dist/auto-reply/reply/block-streaming.js +34 -0
  69. package/dist/auto-reply/reply/body.js +29 -0
  70. package/dist/auto-reply/reply/commands.js +207 -0
  71. package/dist/auto-reply/reply/directive-handling.js +361 -0
  72. package/dist/auto-reply/reply/directives.js +47 -0
  73. package/dist/auto-reply/reply/followup-runner.js +149 -0
  74. package/dist/auto-reply/reply/groups.js +91 -0
  75. package/dist/auto-reply/reply/mentions.js +38 -0
  76. package/dist/auto-reply/reply/model-selection.js +114 -0
  77. package/dist/auto-reply/reply/queue.js +399 -0
  78. package/dist/auto-reply/reply/reply-tags.js +26 -0
  79. package/dist/auto-reply/reply/session-updates.js +87 -0
  80. package/dist/auto-reply/reply/session.js +160 -0
  81. package/dist/auto-reply/reply/typing.js +75 -0
  82. package/dist/auto-reply/reply.js +535 -0
  83. package/dist/auto-reply/send-policy.js +28 -0
  84. package/dist/auto-reply/status.js +158 -0
  85. package/dist/auto-reply/templating.js +9 -0
  86. package/dist/auto-reply/thinking.js +49 -0
  87. package/dist/auto-reply/tokens.js +2 -0
  88. package/dist/auto-reply/tool-meta.js +74 -0
  89. package/dist/auto-reply/transcription.js +57 -0
  90. package/dist/auto-reply/types.js +1 -0
  91. package/dist/browser/bridge-server.js +37 -0
  92. package/dist/browser/cdp.js +382 -0
  93. package/dist/browser/chrome.js +432 -0
  94. package/dist/browser/client-actions-core.js +67 -0
  95. package/dist/browser/client-actions-observe.js +24 -0
  96. package/dist/browser/client-actions-types.js +1 -0
  97. package/dist/browser/client-actions.js +3 -0
  98. package/dist/browser/client-fetch.js +43 -0
  99. package/dist/browser/client.js +105 -0
  100. package/dist/browser/config.js +140 -0
  101. package/dist/browser/constants.js +4 -0
  102. package/dist/browser/profiles-service.js +122 -0
  103. package/dist/browser/profiles.js +85 -0
  104. package/dist/browser/pw-ai.js +2 -0
  105. package/dist/browser/pw-session.js +144 -0
  106. package/dist/browser/pw-tools-core.js +363 -0
  107. package/dist/browser/routes/agent.js +535 -0
  108. package/dist/browser/routes/basic.js +155 -0
  109. package/dist/browser/routes/index.js +8 -0
  110. package/dist/browser/routes/tabs.js +105 -0
  111. package/dist/browser/routes/utils.js +62 -0
  112. package/dist/browser/screenshot.js +40 -0
  113. package/dist/browser/server-context.js +377 -0
  114. package/dist/browser/server.js +81 -0
  115. package/dist/browser/target-id.js +18 -0
  116. package/dist/browser/trash.js +21 -0
  117. package/dist/canvas-host/a2ui/.bundle.hash +1 -0
  118. package/dist/canvas-host/a2ui/a2ui.bundle.js +17768 -0
  119. package/dist/canvas-host/a2ui/index.html +246 -0
  120. package/dist/canvas-host/a2ui.js +187 -0
  121. package/dist/canvas-host/server.js +382 -0
  122. package/dist/cli/browser-cli-actions-input.js +459 -0
  123. package/dist/cli/browser-cli-actions-observe.js +56 -0
  124. package/dist/cli/browser-cli-examples.js +31 -0
  125. package/dist/cli/browser-cli-inspect.js +97 -0
  126. package/dist/cli/browser-cli-manage.js +286 -0
  127. package/dist/cli/browser-cli-shared.js +1 -0
  128. package/dist/cli/browser-cli.js +26 -0
  129. package/dist/cli/canvas-cli.js +416 -0
  130. package/dist/cli/cron-cli.js +454 -0
  131. package/dist/cli/deps.js +17 -0
  132. package/dist/cli/dns-cli.js +180 -0
  133. package/dist/cli/gateway-cli.js +489 -0
  134. package/dist/cli/gateway-rpc.js +20 -0
  135. package/dist/cli/hooks-cli.js +135 -0
  136. package/dist/cli/models-cli.js +248 -0
  137. package/dist/cli/nodes-camera.js +57 -0
  138. package/dist/cli/nodes-canvas.js +26 -0
  139. package/dist/cli/nodes-cli.js +946 -0
  140. package/dist/cli/nodes-screen.js +37 -0
  141. package/dist/cli/parse-duration.js +20 -0
  142. package/dist/cli/ports.js +97 -0
  143. package/dist/cli/program.js +406 -0
  144. package/dist/cli/prompt.js +19 -0
  145. package/dist/cli/tui-cli.js +35 -0
  146. package/dist/cli/wait.js +8 -0
  147. package/dist/commands/agent.js +645 -0
  148. package/dist/commands/antigravity-oauth.js +327 -0
  149. package/dist/commands/configure.js +480 -0
  150. package/dist/commands/doctor.js +484 -0
  151. package/dist/commands/health.js +108 -0
  152. package/dist/commands/models/aliases.js +64 -0
  153. package/dist/commands/models/fallbacks.js +99 -0
  154. package/dist/commands/models/image-fallbacks.js +99 -0
  155. package/dist/commands/models/list.js +323 -0
  156. package/dist/commands/models/scan.js +266 -0
  157. package/dist/commands/models/set-image.js +23 -0
  158. package/dist/commands/models/set.js +23 -0
  159. package/dist/commands/models/shared.js +72 -0
  160. package/dist/commands/models.js +7 -0
  161. package/dist/commands/onboard-auth.js +70 -0
  162. package/dist/commands/onboard-helpers.js +295 -0
  163. package/dist/commands/onboard-interactive.js +17 -0
  164. package/dist/commands/onboard-non-interactive.js +202 -0
  165. package/dist/commands/onboard-providers.js +634 -0
  166. package/dist/commands/onboard-remote.js +120 -0
  167. package/dist/commands/onboard-skills.js +148 -0
  168. package/dist/commands/onboard-types.js +1 -0
  169. package/dist/commands/onboard.js +12 -0
  170. package/dist/commands/send.js +124 -0
  171. package/dist/commands/sessions.js +212 -0
  172. package/dist/commands/setup.js +58 -0
  173. package/dist/commands/signal-install.js +135 -0
  174. package/dist/commands/status.js +207 -0
  175. package/dist/commands/update.js +16 -0
  176. package/dist/config/config.js +6 -0
  177. package/dist/config/defaults.js +61 -0
  178. package/dist/config/io.js +147 -0
  179. package/dist/config/legacy-migrate.js +13 -0
  180. package/dist/config/legacy.js +159 -0
  181. package/dist/config/paths.js +71 -0
  182. package/dist/config/schema.js +150 -0
  183. package/dist/config/sessions.js +282 -0
  184. package/dist/config/talk.js +31 -0
  185. package/dist/config/types.js +1 -0
  186. package/dist/config/validation.js +29 -0
  187. package/dist/config/zod-schema.js +831 -0
  188. package/dist/cron/isolated-agent.js +499 -0
  189. package/dist/cron/run-log.js +72 -0
  190. package/dist/cron/schedule.js +24 -0
  191. package/dist/cron/service.js +471 -0
  192. package/dist/cron/store.js +43 -0
  193. package/dist/cron/types.js +1 -0
  194. package/dist/discord/index.js +2 -0
  195. package/dist/discord/monitor.js +1188 -0
  196. package/dist/discord/probe.js +54 -0
  197. package/dist/discord/send.js +577 -0
  198. package/dist/discord/token.js +8 -0
  199. package/dist/gateway/auth.js +121 -0
  200. package/dist/gateway/call.js +94 -0
  201. package/dist/gateway/chat-attachments.js +41 -0
  202. package/dist/gateway/client.js +180 -0
  203. package/dist/gateway/config-reload.js +274 -0
  204. package/dist/gateway/control-ui.js +184 -0
  205. package/dist/gateway/hooks-mapping.js +282 -0
  206. package/dist/gateway/hooks.js +168 -0
  207. package/dist/gateway/net.js +29 -0
  208. package/dist/gateway/protocol/index.js +61 -0
  209. package/dist/gateway/protocol/schema.js +560 -0
  210. package/dist/gateway/server-bridge-subscriptions.js +93 -0
  211. package/dist/gateway/server-bridge.js +1013 -0
  212. package/dist/gateway/server-browser.js +12 -0
  213. package/dist/gateway/server-chat.js +159 -0
  214. package/dist/gateway/server-constants.js +8 -0
  215. package/dist/gateway/server-discovery.js +62 -0
  216. package/dist/gateway/server-http.js +165 -0
  217. package/dist/gateway/server-methods/agent-job.js +125 -0
  218. package/dist/gateway/server-methods/agent.js +250 -0
  219. package/dist/gateway/server-methods/chat.js +200 -0
  220. package/dist/gateway/server-methods/config.js +50 -0
  221. package/dist/gateway/server-methods/connect.js +6 -0
  222. package/dist/gateway/server-methods/cron.js +83 -0
  223. package/dist/gateway/server-methods/health.js +28 -0
  224. package/dist/gateway/server-methods/models.js +16 -0
  225. package/dist/gateway/server-methods/nodes.js +294 -0
  226. package/dist/gateway/server-methods/providers.js +217 -0
  227. package/dist/gateway/server-methods/send.js +166 -0
  228. package/dist/gateway/server-methods/sessions.js +305 -0
  229. package/dist/gateway/server-methods/skills.js +83 -0
  230. package/dist/gateway/server-methods/system.js +118 -0
  231. package/dist/gateway/server-methods/talk.js +22 -0
  232. package/dist/gateway/server-methods/types.js +1 -0
  233. package/dist/gateway/server-methods/voicewake.js +30 -0
  234. package/dist/gateway/server-methods/web.js +58 -0
  235. package/dist/gateway/server-methods/wizard.js +100 -0
  236. package/dist/gateway/server-methods.js +53 -0
  237. package/dist/gateway/server-providers.js +644 -0
  238. package/dist/gateway/server-shared.js +1 -0
  239. package/dist/gateway/server-utils.js +35 -0
  240. package/dist/gateway/server.js +1437 -0
  241. package/dist/gateway/session-utils.js +216 -0
  242. package/dist/gateway/ws-log.js +349 -0
  243. package/dist/gateway/ws-logging.js +8 -0
  244. package/dist/globals.js +41 -0
  245. package/dist/hooks/gmail-ops.js +236 -0
  246. package/dist/hooks/gmail-setup-utils.js +278 -0
  247. package/dist/hooks/gmail-watcher.js +175 -0
  248. package/dist/hooks/gmail.js +177 -0
  249. package/dist/index.js +50 -0
  250. package/dist/infra/agent-events.js +46 -0
  251. package/dist/infra/binaries.js +9 -0
  252. package/dist/infra/bonjour-discovery.js +163 -0
  253. package/dist/infra/bonjour.js +200 -0
  254. package/dist/infra/bridge/server.js +562 -0
  255. package/dist/infra/canvas-host-url.js +54 -0
  256. package/dist/infra/env.js +8 -0
  257. package/dist/infra/errors.js +28 -0
  258. package/dist/infra/gateway-lock.js +8 -0
  259. package/dist/infra/heartbeat-events.js +21 -0
  260. package/dist/infra/heartbeat-runner.js +453 -0
  261. package/dist/infra/heartbeat-wake.js +61 -0
  262. package/dist/infra/is-main.js +37 -0
  263. package/dist/infra/machine-name.js +40 -0
  264. package/dist/infra/node-pairing.js +211 -0
  265. package/dist/infra/pam.js +42 -0
  266. package/dist/infra/path-env.js +92 -0
  267. package/dist/infra/ports.js +87 -0
  268. package/dist/infra/provider-summary.js +80 -0
  269. package/dist/infra/restart.js +29 -0
  270. package/dist/infra/retry.js +16 -0
  271. package/dist/infra/runtime-guard.js +59 -0
  272. package/dist/infra/system-events.js +44 -0
  273. package/dist/infra/system-presence.js +216 -0
  274. package/dist/infra/tailnet.js +46 -0
  275. package/dist/infra/tailscale.js +149 -0
  276. package/dist/infra/voicewake.js +77 -0
  277. package/dist/infra/widearea-dns.js +123 -0
  278. package/dist/infra/ws.js +13 -0
  279. package/dist/logger.js +52 -0
  280. package/dist/logging.js +490 -0
  281. package/dist/macos/gateway-daemon.js +141 -0
  282. package/dist/macos/relay.js +46 -0
  283. package/dist/media/constants.js +33 -0
  284. package/dist/media/host.js +42 -0
  285. package/dist/media/image-ops.js +121 -0
  286. package/dist/media/mime.js +115 -0
  287. package/dist/media/parse.js +81 -0
  288. package/dist/media/server.js +64 -0
  289. package/dist/media/store.js +139 -0
  290. package/dist/process/command-queue.js +97 -0
  291. package/dist/process/exec.js +75 -0
  292. package/dist/protocol.schema.json +2918 -0
  293. package/dist/provider-web.js +8 -0
  294. package/dist/providers/web/index.js +2 -0
  295. package/dist/runtime.js +8 -0
  296. package/dist/telegram/bot.js +394 -0
  297. package/dist/telegram/download.js +34 -0
  298. package/dist/telegram/index.js +4 -0
  299. package/dist/telegram/monitor.js +47 -0
  300. package/dist/telegram/probe.js +63 -0
  301. package/dist/telegram/proxy.js +9 -0
  302. package/dist/telegram/send.js +138 -0
  303. package/dist/telegram/token.js +30 -0
  304. package/dist/telegram/webhook-set.js +12 -0
  305. package/dist/telegram/webhook.js +56 -0
  306. package/dist/utils.js +133 -0
  307. package/dist/version.js +18 -0
  308. package/dist/web/active-listener.js +7 -0
  309. package/dist/web/auto-reply.js +1203 -0
  310. package/dist/web/inbound.js +481 -0
  311. package/dist/web/login-qr.js +204 -0
  312. package/dist/web/login.js +59 -0
  313. package/dist/web/media.js +148 -0
  314. package/dist/web/outbound.js +67 -0
  315. package/dist/web/qr-image.js +97 -0
  316. package/dist/web/reconnect.js +60 -0
  317. package/dist/web/reply-heartbeat-wake.js +61 -0
  318. package/dist/web/session.js +346 -0
  319. package/docs/AGENTS.default.md +116 -0
  320. package/docs/CNAME +1 -0
  321. package/docs/RELEASING.md +64 -0
  322. package/docs/_config.yml +51 -0
  323. package/docs/_layouts/default.html +145 -0
  324. package/docs/agent-send.md +21 -0
  325. package/docs/agent.md +104 -0
  326. package/docs/android/connect.md +131 -0
  327. package/docs/architecture.md +89 -0
  328. package/docs/assets/markdown.css +130 -0
  329. package/docs/assets/pixel-lobster.svg +60 -0
  330. package/docs/assets/terminal.css +497 -0
  331. package/docs/assets/theme.js +55 -0
  332. package/docs/audio.md +50 -0
  333. package/docs/background-process.md +74 -0
  334. package/docs/bash.md +32 -0
  335. package/docs/bonjour.md +159 -0
  336. package/docs/browser.md +289 -0
  337. package/docs/camera.md +152 -0
  338. package/docs/clawd.md +199 -0
  339. package/docs/clawdbot-mac.md +104 -0
  340. package/docs/configuration.md +1177 -0
  341. package/docs/control-api.md +49 -0
  342. package/docs/control-ui.md +83 -0
  343. package/docs/cron.md +374 -0
  344. package/docs/dashboard.md +17 -0
  345. package/docs/device-models.md +46 -0
  346. package/docs/discord.md +293 -0
  347. package/docs/discovery.md +112 -0
  348. package/docs/docker.md +251 -0
  349. package/docs/docs.json +86 -0
  350. package/docs/doctor.md +47 -0
  351. package/docs/elevated.md +31 -0
  352. package/docs/faq.md +640 -0
  353. package/docs/gateway/pairing.md +109 -0
  354. package/docs/gateway-lock.md +28 -0
  355. package/docs/gateway.md +174 -0
  356. package/docs/gmail-pubsub.md +191 -0
  357. package/docs/grammy.md +27 -0
  358. package/docs/group-messages.md +71 -0
  359. package/docs/groups.md +78 -0
  360. package/docs/health.md +28 -0
  361. package/docs/heartbeat.md +64 -0
  362. package/docs/images.md +52 -0
  363. package/docs/imessage.md +63 -0
  364. package/docs/index.md +182 -0
  365. package/docs/ios/connect.md +177 -0
  366. package/docs/ios/spec.md +236 -0
  367. package/docs/location-command.md +95 -0
  368. package/docs/logging.md +99 -0
  369. package/docs/lore.md +131 -0
  370. package/docs/mac/bun.md +133 -0
  371. package/docs/mac/canvas.md +161 -0
  372. package/docs/mac/child-process.md +72 -0
  373. package/docs/mac/dev-setup.md +81 -0
  374. package/docs/mac/health.md +28 -0
  375. package/docs/mac/icon.md +26 -0
  376. package/docs/mac/logging.md +51 -0
  377. package/docs/mac/menu-bar.md +69 -0
  378. package/docs/mac/peekaboo.md +170 -0
  379. package/docs/mac/permissions.md +40 -0
  380. package/docs/mac/release.md +76 -0
  381. package/docs/mac/remote.md +57 -0
  382. package/docs/mac/signing.md +41 -0
  383. package/docs/mac/skills.md +27 -0
  384. package/docs/mac/voice-overlay.md +52 -0
  385. package/docs/mac/voicewake.md +56 -0
  386. package/docs/mac/webchat.md +27 -0
  387. package/docs/mac/xpc.md +40 -0
  388. package/docs/models.md +90 -0
  389. package/docs/nix.md +49 -0
  390. package/docs/nodes.md +157 -0
  391. package/docs/onboarding-config-protocol.md +29 -0
  392. package/docs/onboarding.md +185 -0
  393. package/docs/presence.md +133 -0
  394. package/docs/queue.md +78 -0
  395. package/docs/refactor/browser-control-simplification.md +58 -0
  396. package/docs/refactor/canvas-a2ui.md +93 -0
  397. package/docs/refactor/cli-unification.md +64 -0
  398. package/docs/refactor/gateway-client.md +31 -0
  399. package/docs/refactor/gateway.md +99 -0
  400. package/docs/refactor/new-arch.md +171 -0
  401. package/docs/refactor/tui.md +26 -0
  402. package/docs/refactor/web-gateway-troubleshooting.md +37 -0
  403. package/docs/refactor/webagent-session.md +46 -0
  404. package/docs/remote-gateway-readme.md +148 -0
  405. package/docs/remote.md +66 -0
  406. package/docs/research/memory.md +227 -0
  407. package/docs/rpc.md +35 -0
  408. package/docs/security.md +168 -0
  409. package/docs/session-tool.md +119 -0
  410. package/docs/session.md +84 -0
  411. package/docs/sessions.md +8 -0
  412. package/docs/setup.md +118 -0
  413. package/docs/signal.md +113 -0
  414. package/docs/skills-config.md +58 -0
  415. package/docs/skills.md +149 -0
  416. package/docs/slack.md +158 -0
  417. package/docs/surface.md +20 -0
  418. package/docs/tailscale.md +71 -0
  419. package/docs/talk.md +79 -0
  420. package/docs/telegram.md +90 -0
  421. package/docs/templates/AGENTS.md +126 -0
  422. package/docs/templates/BOOTSTRAP.md +53 -0
  423. package/docs/templates/IDENTITY.md +17 -0
  424. package/docs/templates/SOUL.md +41 -0
  425. package/docs/templates/TOOLS.md +41 -0
  426. package/docs/templates/USER.md +22 -0
  427. package/docs/test.md +35 -0
  428. package/docs/thinking.md +46 -0
  429. package/docs/tools.md +248 -0
  430. package/docs/troubleshooting.md +227 -0
  431. package/docs/tui.md +69 -0
  432. package/docs/typebox.md +42 -0
  433. package/docs/voicewake.md +61 -0
  434. package/docs/web.md +115 -0
  435. package/docs/webchat.md +34 -0
  436. package/docs/webhook.md +132 -0
  437. package/docs/whatsapp-clawd.jpg +0 -0
  438. package/docs/whatsapp.md +142 -0
  439. package/docs/wizard.md +158 -0
  440. package/package.json +178 -0
  441. package/skills/apple-notes/SKILL.md +50 -0
  442. package/skills/apple-reminders/SKILL.md +67 -0
  443. package/skills/bear-notes/SKILL.md +79 -0
  444. package/skills/bird/SKILL.md +25 -0
  445. package/skills/blogwatcher/SKILL.md +46 -0
  446. package/skills/blucli/SKILL.md +27 -0
  447. package/skills/brave-search/SKILL.md +30 -0
  448. package/skills/brave-search/scripts/content.mjs +53 -0
  449. package/skills/brave-search/scripts/search.mjs +79 -0
  450. package/skills/camsnap/SKILL.md +25 -0
  451. package/skills/clawdhub/SKILL.md +53 -0
  452. package/skills/coding-agent/SKILL.md +275 -0
  453. package/skills/discord/SKILL.md +369 -0
  454. package/skills/eightctl/SKILL.md +29 -0
  455. package/skills/food-order/SKILL.md +41 -0
  456. package/skills/gemini/SKILL.md +23 -0
  457. package/skills/gifgrep/SKILL.md +47 -0
  458. package/skills/github/SKILL.md +47 -0
  459. package/skills/gog/SKILL.md +36 -0
  460. package/skills/goplaces/SKILL.md +30 -0
  461. package/skills/imsg/SKILL.md +25 -0
  462. package/skills/local-places/SERVER_README.md +101 -0
  463. package/skills/local-places/SKILL.md +91 -0
  464. package/skills/local-places/pyproject.toml +27 -0
  465. package/skills/local-places/src/local_places/__init__.py +2 -0
  466. package/skills/local-places/src/local_places/__pycache__/__init__.cpython-314.pyc +0 -0
  467. package/skills/local-places/src/local_places/__pycache__/google_places.cpython-314.pyc +0 -0
  468. package/skills/local-places/src/local_places/__pycache__/main.cpython-314.pyc +0 -0
  469. package/skills/local-places/src/local_places/__pycache__/schemas.cpython-314.pyc +0 -0
  470. package/skills/local-places/src/local_places/google_places.py +314 -0
  471. package/skills/local-places/src/local_places/main.py +65 -0
  472. package/skills/local-places/src/local_places/schemas.py +107 -0
  473. package/skills/mcporter/SKILL.md +38 -0
  474. package/skills/nano-banana-pro/SKILL.md +29 -0
  475. package/skills/nano-banana-pro/scripts/generate_image.py +167 -0
  476. package/skills/nano-pdf/SKILL.md +20 -0
  477. package/skills/notion/SKILL.md +156 -0
  478. package/skills/obsidian/SKILL.md +55 -0
  479. package/skills/openai-image-gen/SKILL.md +31 -0
  480. package/skills/openai-image-gen/scripts/gen.py +173 -0
  481. package/skills/openai-whisper/SKILL.md +19 -0
  482. package/skills/openai-whisper-api/SKILL.md +43 -0
  483. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  484. package/skills/openhue/SKILL.md +30 -0
  485. package/skills/oracle/SKILL.md +105 -0
  486. package/skills/ordercli/SKILL.md +47 -0
  487. package/skills/peekaboo/SKILL.md +153 -0
  488. package/skills/qmd/SKILL.md +26 -0
  489. package/skills/sag/SKILL.md +62 -0
  490. package/skills/slack/SKILL.md +143 -0
  491. package/skills/songsee/SKILL.md +29 -0
  492. package/skills/sonoscli/SKILL.md +26 -0
  493. package/skills/spotify-player/SKILL.md +34 -0
  494. package/skills/summarize/SKILL.md +49 -0
  495. package/skills/things-mac/SKILL.md +61 -0
  496. package/skills/tmux/SKILL.md +121 -0
  497. package/skills/tmux/scripts/find-sessions.sh +112 -0
  498. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  499. package/skills/trello/SKILL.md +84 -0
  500. package/skills/video-frames/SKILL.md +29 -0
  501. package/skills/video-frames/scripts/frame.sh +81 -0
  502. package/skills/wacli/SKILL.md +42 -0
  503. package/skills/weather/SKILL.md +49 -0
@@ -0,0 +1,120 @@
1
+ import { discoverGatewayBeacons } from "../infra/bonjour-discovery.js";
2
+ import { detectBinary } from "./onboard-helpers.js";
3
+ const DEFAULT_GATEWAY_URL = "ws://127.0.0.1:18789";
4
+ function pickHost(beacon) {
5
+ return beacon.tailnetDns || beacon.lanHost || beacon.host;
6
+ }
7
+ function buildLabel(beacon) {
8
+ const host = pickHost(beacon);
9
+ const port = beacon.gatewayPort ?? beacon.port ?? 18789;
10
+ const title = beacon.displayName ?? beacon.instanceName;
11
+ const hint = host ? `${host}:${port}` : "host unknown";
12
+ return `${title} (${hint})`;
13
+ }
14
+ function ensureWsUrl(value) {
15
+ const trimmed = value.trim();
16
+ if (!trimmed)
17
+ return DEFAULT_GATEWAY_URL;
18
+ return trimmed;
19
+ }
20
+ export async function promptRemoteGatewayConfig(cfg, prompter) {
21
+ let selectedBeacon = null;
22
+ let suggestedUrl = cfg.gateway?.remote?.url ?? DEFAULT_GATEWAY_URL;
23
+ const hasBonjourTool = (await detectBinary("dns-sd")) || (await detectBinary("avahi-browse"));
24
+ const wantsDiscover = hasBonjourTool
25
+ ? await prompter.confirm({
26
+ message: "Discover gateway on LAN (Bonjour)?",
27
+ initialValue: true,
28
+ })
29
+ : false;
30
+ if (!hasBonjourTool) {
31
+ await prompter.note("Bonjour discovery requires dns-sd (macOS) or avahi-browse (Linux).", "Discovery");
32
+ }
33
+ if (wantsDiscover) {
34
+ const spin = prompter.progress("Searching for gateways…");
35
+ const beacons = await discoverGatewayBeacons({ timeoutMs: 2000 });
36
+ spin.stop(beacons.length > 0
37
+ ? `Found ${beacons.length} gateway(s)`
38
+ : "No gateways found");
39
+ if (beacons.length > 0) {
40
+ const selection = await prompter.select({
41
+ message: "Select gateway",
42
+ options: [
43
+ ...beacons.map((beacon, index) => ({
44
+ value: String(index),
45
+ label: buildLabel(beacon),
46
+ })),
47
+ { value: "manual", label: "Enter URL manually" },
48
+ ],
49
+ });
50
+ if (selection !== "manual") {
51
+ const idx = Number.parseInt(String(selection), 10);
52
+ selectedBeacon = Number.isFinite(idx) ? (beacons[idx] ?? null) : null;
53
+ }
54
+ }
55
+ }
56
+ if (selectedBeacon) {
57
+ const host = pickHost(selectedBeacon);
58
+ const port = selectedBeacon.gatewayPort ?? 18789;
59
+ if (host) {
60
+ const mode = await prompter.select({
61
+ message: "Connection method",
62
+ options: [
63
+ {
64
+ value: "direct",
65
+ label: `Direct gateway WS (${host}:${port})`,
66
+ },
67
+ { value: "ssh", label: "SSH tunnel (loopback)" },
68
+ ],
69
+ });
70
+ if (mode === "direct") {
71
+ suggestedUrl = `ws://${host}:${port}`;
72
+ }
73
+ else {
74
+ suggestedUrl = DEFAULT_GATEWAY_URL;
75
+ await prompter.note([
76
+ "Start a tunnel before using the CLI:",
77
+ `ssh -N -L 18789:127.0.0.1:18789 <user>@${host}${selectedBeacon.sshPort ? ` -p ${selectedBeacon.sshPort}` : ""}`,
78
+ ].join("\n"), "SSH tunnel");
79
+ }
80
+ }
81
+ }
82
+ const urlInput = await prompter.text({
83
+ message: "Gateway WebSocket URL",
84
+ initialValue: suggestedUrl,
85
+ validate: (value) => String(value).trim().startsWith("ws://") ||
86
+ String(value).trim().startsWith("wss://")
87
+ ? undefined
88
+ : "URL must start with ws:// or wss://",
89
+ });
90
+ const url = ensureWsUrl(String(urlInput));
91
+ const authChoice = (await prompter.select({
92
+ message: "Gateway auth",
93
+ options: [
94
+ { value: "token", label: "Token (recommended)" },
95
+ { value: "off", label: "No auth" },
96
+ ],
97
+ }));
98
+ let token = cfg.gateway?.remote?.token ?? "";
99
+ if (authChoice === "token") {
100
+ token = String(await prompter.text({
101
+ message: "Gateway token",
102
+ initialValue: token,
103
+ validate: (value) => (value?.trim() ? undefined : "Required"),
104
+ })).trim();
105
+ }
106
+ else {
107
+ token = "";
108
+ }
109
+ return {
110
+ ...cfg,
111
+ gateway: {
112
+ ...cfg.gateway,
113
+ mode: "remote",
114
+ remote: {
115
+ url,
116
+ token: token || undefined,
117
+ },
118
+ },
119
+ };
120
+ }
@@ -0,0 +1,148 @@
1
+ import { installSkill } from "../agents/skills-install.js";
2
+ import { buildWorkspaceSkillStatus } from "../agents/skills-status.js";
3
+ import { detectBinary, resolveNodeManagerOptions } from "./onboard-helpers.js";
4
+ function summarizeInstallFailure(message) {
5
+ const cleaned = message
6
+ .replace(/^Install failed(?:\s*\([^)]*\))?\s*:?\s*/i, "")
7
+ .trim();
8
+ if (!cleaned)
9
+ return undefined;
10
+ const maxLen = 140;
11
+ return cleaned.length > maxLen ? `${cleaned.slice(0, maxLen - 1)}…` : cleaned;
12
+ }
13
+ function formatSkillHint(skill) {
14
+ const desc = skill.description?.trim();
15
+ const installLabel = skill.install[0]?.label?.trim();
16
+ const combined = desc && installLabel ? `${desc} — ${installLabel}` : desc || installLabel;
17
+ if (!combined)
18
+ return "install";
19
+ const maxLen = 90;
20
+ return combined.length > maxLen
21
+ ? `${combined.slice(0, maxLen - 1)}…`
22
+ : combined;
23
+ }
24
+ function upsertSkillEntry(cfg, skillKey, patch) {
25
+ const entries = { ...cfg.skills?.entries };
26
+ const existing = entries[skillKey] ?? {};
27
+ entries[skillKey] = { ...existing, ...patch };
28
+ return {
29
+ ...cfg,
30
+ skills: {
31
+ ...cfg.skills,
32
+ entries,
33
+ },
34
+ };
35
+ }
36
+ export async function setupSkills(cfg, workspaceDir, runtime, prompter) {
37
+ const report = buildWorkspaceSkillStatus(workspaceDir, { config: cfg });
38
+ const eligible = report.skills.filter((s) => s.eligible);
39
+ const missing = report.skills.filter((s) => !s.eligible && !s.disabled && !s.blockedByAllowlist);
40
+ const blocked = report.skills.filter((s) => s.blockedByAllowlist);
41
+ const needsBrewPrompt = process.platform !== "win32" &&
42
+ report.skills.some((skill) => skill.install.some((option) => option.kind === "brew")) &&
43
+ !(await detectBinary("brew"));
44
+ await prompter.note([
45
+ `Eligible: ${eligible.length}`,
46
+ `Missing requirements: ${missing.length}`,
47
+ `Blocked by allowlist: ${blocked.length}`,
48
+ ].join("\n"), "Skills status");
49
+ const shouldConfigure = await prompter.confirm({
50
+ message: "Configure skills now? (recommended)",
51
+ initialValue: true,
52
+ });
53
+ if (!shouldConfigure)
54
+ return cfg;
55
+ if (needsBrewPrompt) {
56
+ await prompter.note([
57
+ "Many skill dependencies are shipped via Homebrew.",
58
+ "Without brew, you'll need to build from source or download releases manually.",
59
+ ].join("\n"), "Homebrew recommended");
60
+ const showBrewInstall = await prompter.confirm({
61
+ message: "Show Homebrew install command?",
62
+ initialValue: true,
63
+ });
64
+ if (showBrewInstall) {
65
+ await prompter.note([
66
+ "Run:",
67
+ '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
68
+ ].join("\n"), "Homebrew install");
69
+ }
70
+ }
71
+ const nodeManager = (await prompter.select({
72
+ message: "Preferred node manager for skill installs",
73
+ options: resolveNodeManagerOptions(),
74
+ }));
75
+ let next = {
76
+ ...cfg,
77
+ skills: {
78
+ ...cfg.skills,
79
+ install: {
80
+ ...cfg.skills?.install,
81
+ nodeManager,
82
+ },
83
+ },
84
+ };
85
+ const installable = missing.filter((skill) => skill.install.length > 0 && skill.missing.bins.length > 0);
86
+ if (installable.length > 0) {
87
+ const toInstall = await prompter.multiselect({
88
+ message: "Install missing skill dependencies",
89
+ options: [
90
+ {
91
+ value: "__skip__",
92
+ label: "Skip for now",
93
+ hint: "Continue without installing dependencies",
94
+ },
95
+ ...installable.map((skill) => ({
96
+ value: skill.name,
97
+ label: `${skill.emoji ?? "🧩"} ${skill.name}`,
98
+ hint: formatSkillHint(skill),
99
+ })),
100
+ ],
101
+ });
102
+ const selected = toInstall.filter((name) => name !== "__skip__");
103
+ for (const name of selected) {
104
+ const target = installable.find((s) => s.name === name);
105
+ if (!target || target.install.length === 0)
106
+ continue;
107
+ const installId = target.install[0]?.id;
108
+ if (!installId)
109
+ continue;
110
+ const spin = prompter.progress(`Installing ${name}…`);
111
+ const result = await installSkill({
112
+ workspaceDir,
113
+ skillName: target.name,
114
+ installId,
115
+ config: next,
116
+ });
117
+ if (result.ok) {
118
+ spin.stop(`Installed ${name}`);
119
+ }
120
+ else {
121
+ const code = result.code == null ? "" : ` (exit ${result.code})`;
122
+ const detail = summarizeInstallFailure(result.message);
123
+ spin.stop(`Install failed: ${name}${code}${detail ? ` — ${detail}` : ""}`);
124
+ if (result.stderr)
125
+ runtime.log(result.stderr.trim());
126
+ else if (result.stdout)
127
+ runtime.log(result.stdout.trim());
128
+ runtime.log("Tip: run `clawdbot doctor` to review skills + requirements.");
129
+ }
130
+ }
131
+ }
132
+ for (const skill of missing) {
133
+ if (!skill.primaryEnv || skill.missing.env.length === 0)
134
+ continue;
135
+ const wantsKey = await prompter.confirm({
136
+ message: `Set ${skill.primaryEnv} for ${skill.name}?`,
137
+ initialValue: false,
138
+ });
139
+ if (!wantsKey)
140
+ continue;
141
+ const apiKey = String(await prompter.text({
142
+ message: `Enter ${skill.primaryEnv}`,
143
+ validate: (value) => (value?.trim() ? undefined : "Required"),
144
+ }));
145
+ next = upsertSkillEntry(next, skill.skillKey, { apiKey: apiKey.trim() });
146
+ }
147
+ return next;
148
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { assertSupportedRuntime } from "../infra/runtime-guard.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
+ import { runInteractiveOnboarding } from "./onboard-interactive.js";
4
+ import { runNonInteractiveOnboarding } from "./onboard-non-interactive.js";
5
+ export async function onboardCommand(opts, runtime = defaultRuntime) {
6
+ assertSupportedRuntime(runtime);
7
+ if (opts.nonInteractive) {
8
+ await runNonInteractiveOnboarding(opts, runtime);
9
+ return;
10
+ }
11
+ await runInteractiveOnboarding(opts, runtime);
12
+ }
@@ -0,0 +1,124 @@
1
+ import { loadConfig } from "../config/config.js";
2
+ import { callGateway, randomIdempotencyKey } from "../gateway/call.js";
3
+ import { success } from "../globals.js";
4
+ import { resolveTelegramToken } from "../telegram/token.js";
5
+ export async function sendCommand(opts, deps, runtime) {
6
+ const provider = (opts.provider ?? "whatsapp").toLowerCase();
7
+ if (opts.dryRun) {
8
+ runtime.log(`[dry-run] would send via ${provider} -> ${opts.to}: ${opts.message}${opts.media ? ` (media ${opts.media})` : ""}`);
9
+ return;
10
+ }
11
+ if (provider === "telegram") {
12
+ const { token } = resolveTelegramToken(loadConfig());
13
+ const result = await deps.sendMessageTelegram(opts.to, opts.message, {
14
+ token: token || undefined,
15
+ mediaUrl: opts.media,
16
+ });
17
+ runtime.log(success(`✅ Sent via telegram. Message ID: ${result.messageId} (chat ${result.chatId})`));
18
+ if (opts.json) {
19
+ runtime.log(JSON.stringify({
20
+ provider: "telegram",
21
+ via: "direct",
22
+ to: opts.to,
23
+ chatId: result.chatId,
24
+ messageId: result.messageId,
25
+ mediaUrl: opts.media ?? null,
26
+ }, null, 2));
27
+ }
28
+ return;
29
+ }
30
+ if (provider === "discord") {
31
+ const result = await deps.sendMessageDiscord(opts.to, opts.message, {
32
+ token: process.env.DISCORD_BOT_TOKEN,
33
+ mediaUrl: opts.media,
34
+ });
35
+ runtime.log(success(`✅ Sent via discord. Message ID: ${result.messageId} (channel ${result.channelId})`));
36
+ if (opts.json) {
37
+ runtime.log(JSON.stringify({
38
+ provider: "discord",
39
+ via: "direct",
40
+ to: opts.to,
41
+ channelId: result.channelId,
42
+ messageId: result.messageId,
43
+ mediaUrl: opts.media ?? null,
44
+ }, null, 2));
45
+ }
46
+ return;
47
+ }
48
+ if (provider === "slack") {
49
+ const result = await deps.sendMessageSlack(opts.to, opts.message, {
50
+ mediaUrl: opts.media,
51
+ });
52
+ runtime.log(success(`✅ Sent via slack. Message ID: ${result.messageId} (channel ${result.channelId})`));
53
+ if (opts.json) {
54
+ runtime.log(JSON.stringify({
55
+ provider: "slack",
56
+ via: "direct",
57
+ to: opts.to,
58
+ channelId: result.channelId,
59
+ messageId: result.messageId,
60
+ mediaUrl: opts.media ?? null,
61
+ }, null, 2));
62
+ }
63
+ return;
64
+ }
65
+ if (provider === "signal") {
66
+ const result = await deps.sendMessageSignal(opts.to, opts.message, {
67
+ mediaUrl: opts.media,
68
+ });
69
+ runtime.log(success(`✅ Sent via signal. Message ID: ${result.messageId}`));
70
+ if (opts.json) {
71
+ runtime.log(JSON.stringify({
72
+ provider: "signal",
73
+ via: "direct",
74
+ to: opts.to,
75
+ messageId: result.messageId,
76
+ mediaUrl: opts.media ?? null,
77
+ }, null, 2));
78
+ }
79
+ return;
80
+ }
81
+ if (provider === "imessage" || provider === "imsg") {
82
+ const result = await deps.sendMessageIMessage(opts.to, opts.message, {
83
+ mediaUrl: opts.media,
84
+ });
85
+ runtime.log(success(`✅ Sent via iMessage. Message ID: ${result.messageId}`));
86
+ if (opts.json) {
87
+ runtime.log(JSON.stringify({
88
+ provider: "imessage",
89
+ via: "direct",
90
+ to: opts.to,
91
+ messageId: result.messageId,
92
+ mediaUrl: opts.media ?? null,
93
+ }, null, 2));
94
+ }
95
+ return;
96
+ }
97
+ // Always send via gateway over WS to avoid multi-session corruption.
98
+ const sendViaGateway = async () => callGateway({
99
+ url: "ws://127.0.0.1:18789",
100
+ method: "send",
101
+ params: {
102
+ to: opts.to,
103
+ message: opts.message,
104
+ mediaUrl: opts.media,
105
+ gifPlayback: opts.gifPlayback,
106
+ provider,
107
+ idempotencyKey: randomIdempotencyKey(),
108
+ },
109
+ timeoutMs: 10_000,
110
+ clientName: "cli",
111
+ mode: "cli",
112
+ });
113
+ const result = await sendViaGateway();
114
+ runtime.log(success(`✅ Sent via gateway. Message ID: ${result.messageId ?? "unknown"}`));
115
+ if (opts.json) {
116
+ runtime.log(JSON.stringify({
117
+ provider: "web",
118
+ via: "gateway",
119
+ to: opts.to,
120
+ messageId: result.messageId,
121
+ mediaUrl: opts.media ?? null,
122
+ }, null, 2));
123
+ }
124
+ }
@@ -0,0 +1,212 @@
1
+ import chalk from "chalk";
2
+ import { lookupContextTokens } from "../agents/context.js";
3
+ import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL, DEFAULT_PROVIDER, } from "../agents/defaults.js";
4
+ import { resolveConfiguredModelRef } from "../agents/model-selection.js";
5
+ import { loadConfig } from "../config/config.js";
6
+ import { loadSessionStore, resolveStorePath, } from "../config/sessions.js";
7
+ import { info } from "../globals.js";
8
+ const KIND_PAD = 6;
9
+ const KEY_PAD = 26;
10
+ const AGE_PAD = 9;
11
+ const MODEL_PAD = 14;
12
+ const TOKENS_PAD = 20;
13
+ const isRich = () => Boolean(process.stdout.isTTY && chalk.level > 0);
14
+ const formatKTokens = (value) => `${(value / 1000).toFixed(value >= 10_000 ? 0 : 1)}k`;
15
+ const truncateKey = (key) => {
16
+ if (key.length <= KEY_PAD)
17
+ return key;
18
+ const head = Math.max(4, KEY_PAD - 10);
19
+ return `${key.slice(0, head)}...${key.slice(-6)}`;
20
+ };
21
+ const colorByPct = (label, pct, rich) => {
22
+ if (!rich || pct === null)
23
+ return label;
24
+ if (pct >= 95)
25
+ return chalk.red(label);
26
+ if (pct >= 80)
27
+ return chalk.yellow(label);
28
+ if (pct >= 60)
29
+ return chalk.green(label);
30
+ return chalk.gray(label);
31
+ };
32
+ const formatTokensCell = (total, contextTokens, rich) => {
33
+ if (!total)
34
+ return "-".padEnd(TOKENS_PAD);
35
+ const totalLabel = formatKTokens(total);
36
+ const ctxLabel = contextTokens ? formatKTokens(contextTokens) : "?";
37
+ const pct = contextTokens
38
+ ? Math.min(999, Math.round((total / contextTokens) * 100))
39
+ : null;
40
+ const label = `${totalLabel}/${ctxLabel} (${pct ?? "?"}%)`;
41
+ const padded = label.padEnd(TOKENS_PAD);
42
+ return colorByPct(padded, pct, rich);
43
+ };
44
+ const formatKindCell = (kind, rich) => {
45
+ const label = kind.padEnd(KIND_PAD);
46
+ if (!rich)
47
+ return label;
48
+ if (kind === "group")
49
+ return chalk.magenta(label);
50
+ if (kind === "global")
51
+ return chalk.yellow(label);
52
+ if (kind === "direct")
53
+ return chalk.cyan(label);
54
+ return chalk.gray(label);
55
+ };
56
+ const formatAgeCell = (updatedAt, rich) => {
57
+ const ageLabel = updatedAt ? formatAge(Date.now() - updatedAt) : "unknown";
58
+ const padded = ageLabel.padEnd(AGE_PAD);
59
+ return rich ? chalk.gray(padded) : padded;
60
+ };
61
+ const formatModelCell = (model, rich) => {
62
+ const label = (model ?? "unknown").padEnd(MODEL_PAD);
63
+ return rich ? chalk.white(label) : label;
64
+ };
65
+ const formatFlagsCell = (row, rich) => {
66
+ const flags = [
67
+ row.thinkingLevel ? `think:${row.thinkingLevel}` : null,
68
+ row.verboseLevel ? `verbose:${row.verboseLevel}` : null,
69
+ row.groupActivation ? `activation:${row.groupActivation}` : null,
70
+ row.systemSent ? "system" : null,
71
+ row.abortedLastRun ? "aborted" : null,
72
+ row.sessionId ? `id:${row.sessionId}` : null,
73
+ ].filter(Boolean);
74
+ const label = flags.join(" ");
75
+ return label.length === 0 ? "" : rich ? chalk.gray(label) : label;
76
+ };
77
+ const formatAge = (ms) => {
78
+ if (!ms || ms < 0)
79
+ return "unknown";
80
+ const minutes = Math.round(ms / 60_000);
81
+ if (minutes < 1)
82
+ return "just now";
83
+ if (minutes < 60)
84
+ return `${minutes}m ago`;
85
+ const hours = Math.round(minutes / 60);
86
+ if (hours < 48)
87
+ return `${hours}h ago`;
88
+ const days = Math.round(hours / 24);
89
+ return `${days}d ago`;
90
+ };
91
+ function classifyKey(key, entry) {
92
+ if (key === "global")
93
+ return "global";
94
+ if (key === "unknown")
95
+ return "unknown";
96
+ if (entry?.chatType === "group" || entry?.chatType === "room")
97
+ return "group";
98
+ if (key.startsWith("group:") ||
99
+ key.includes(":group:") ||
100
+ key.includes(":channel:")) {
101
+ return "group";
102
+ }
103
+ return "direct";
104
+ }
105
+ function toRows(store) {
106
+ return Object.entries(store)
107
+ .map(([key, entry]) => {
108
+ const updatedAt = entry?.updatedAt ?? null;
109
+ return {
110
+ key,
111
+ kind: classifyKey(key, entry),
112
+ updatedAt,
113
+ ageMs: updatedAt ? Date.now() - updatedAt : null,
114
+ sessionId: entry?.sessionId,
115
+ systemSent: entry?.systemSent,
116
+ abortedLastRun: entry?.abortedLastRun,
117
+ thinkingLevel: entry?.thinkingLevel,
118
+ verboseLevel: entry?.verboseLevel,
119
+ groupActivation: entry?.groupActivation,
120
+ inputTokens: entry?.inputTokens,
121
+ outputTokens: entry?.outputTokens,
122
+ totalTokens: entry?.totalTokens,
123
+ model: entry?.model,
124
+ contextTokens: entry?.contextTokens,
125
+ };
126
+ })
127
+ .sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
128
+ }
129
+ export async function sessionsCommand(opts, runtime) {
130
+ const cfg = loadConfig();
131
+ const resolved = resolveConfiguredModelRef({
132
+ cfg,
133
+ defaultProvider: DEFAULT_PROVIDER,
134
+ defaultModel: DEFAULT_MODEL,
135
+ });
136
+ const configContextTokens = cfg.agent?.contextTokens ??
137
+ lookupContextTokens(resolved.model) ??
138
+ DEFAULT_CONTEXT_TOKENS;
139
+ const configModel = resolved.model ?? DEFAULT_MODEL;
140
+ const storePath = resolveStorePath(opts.store ?? cfg.session?.store);
141
+ const store = loadSessionStore(storePath);
142
+ let activeMinutes;
143
+ if (opts.active !== undefined) {
144
+ const parsed = Number.parseInt(String(opts.active), 10);
145
+ if (Number.isNaN(parsed) || parsed <= 0) {
146
+ runtime.error("--active must be a positive integer (minutes)");
147
+ runtime.exit(1);
148
+ return;
149
+ }
150
+ activeMinutes = parsed;
151
+ }
152
+ const rows = toRows(store).filter((row) => {
153
+ if (activeMinutes === undefined)
154
+ return true;
155
+ if (!row.updatedAt)
156
+ return false;
157
+ return Date.now() - row.updatedAt <= activeMinutes * 60_000;
158
+ });
159
+ if (opts.json) {
160
+ runtime.log(JSON.stringify({
161
+ path: storePath,
162
+ count: rows.length,
163
+ activeMinutes: activeMinutes ?? null,
164
+ sessions: rows.map((r) => ({
165
+ ...r,
166
+ contextTokens: r.contextTokens ??
167
+ lookupContextTokens(r.model) ??
168
+ configContextTokens ??
169
+ null,
170
+ model: r.model ?? configModel ?? null,
171
+ })),
172
+ }, null, 2));
173
+ return;
174
+ }
175
+ runtime.log(info(`Session store: ${storePath}`));
176
+ runtime.log(info(`Sessions listed: ${rows.length}`));
177
+ if (activeMinutes) {
178
+ runtime.log(info(`Filtered to last ${activeMinutes} minute(s)`));
179
+ }
180
+ if (rows.length === 0) {
181
+ runtime.log("No sessions found.");
182
+ return;
183
+ }
184
+ const rich = isRich();
185
+ const header = [
186
+ "Kind".padEnd(KIND_PAD),
187
+ "Key".padEnd(KEY_PAD),
188
+ "Age".padEnd(AGE_PAD),
189
+ "Model".padEnd(MODEL_PAD),
190
+ "Tokens (ctx %)".padEnd(TOKENS_PAD),
191
+ "Flags",
192
+ ].join(" ");
193
+ runtime.log(rich ? chalk.bold(header) : header);
194
+ for (const row of rows) {
195
+ const model = row.model ?? configModel;
196
+ const contextTokens = row.contextTokens ?? lookupContextTokens(model) ?? configContextTokens;
197
+ const input = row.inputTokens ?? 0;
198
+ const output = row.outputTokens ?? 0;
199
+ const total = row.totalTokens ?? input + output;
200
+ const keyLabel = truncateKey(row.key).padEnd(KEY_PAD);
201
+ const keyCell = rich ? chalk.cyan(keyLabel) : keyLabel;
202
+ const line = [
203
+ formatKindCell(row.kind, rich),
204
+ keyCell,
205
+ formatAgeCell(row.updatedAt, rich),
206
+ formatModelCell(model, rich),
207
+ formatTokensCell(total, contextTokens ?? null, rich),
208
+ formatFlagsCell(row, rich),
209
+ ].join(" ");
210
+ runtime.log(line.trimEnd());
211
+ }
212
+ }
@@ -0,0 +1,58 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import JSON5 from "json5";
4
+ import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace, } from "../agents/workspace.js";
5
+ import { CONFIG_PATH_CLAWDBOT } from "../config/config.js";
6
+ import { resolveSessionTranscriptsDir } from "../config/sessions.js";
7
+ import { defaultRuntime } from "../runtime.js";
8
+ async function readConfigFileRaw() {
9
+ try {
10
+ const raw = await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf-8");
11
+ const parsed = JSON5.parse(raw);
12
+ if (parsed && typeof parsed === "object") {
13
+ return { exists: true, parsed: parsed };
14
+ }
15
+ return { exists: true, parsed: {} };
16
+ }
17
+ catch {
18
+ return { exists: false, parsed: {} };
19
+ }
20
+ }
21
+ async function writeConfigFile(cfg) {
22
+ await fs.mkdir(path.dirname(CONFIG_PATH_CLAWDBOT), { recursive: true });
23
+ const json = JSON.stringify(cfg, null, 2).trimEnd().concat("\n");
24
+ await fs.writeFile(CONFIG_PATH_CLAWDBOT, json, "utf-8");
25
+ }
26
+ export async function setupCommand(opts, runtime = defaultRuntime) {
27
+ const desiredWorkspace = typeof opts?.workspace === "string" && opts.workspace.trim()
28
+ ? opts.workspace.trim()
29
+ : undefined;
30
+ const existingRaw = await readConfigFileRaw();
31
+ const cfg = existingRaw.parsed;
32
+ const agent = cfg.agent ?? {};
33
+ const workspace = desiredWorkspace ?? agent.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR;
34
+ const next = {
35
+ ...cfg,
36
+ agent: {
37
+ ...agent,
38
+ workspace,
39
+ },
40
+ };
41
+ if (!existingRaw.exists || agent.workspace !== workspace) {
42
+ await writeConfigFile(next);
43
+ runtime.log(!existingRaw.exists
44
+ ? `Wrote ${CONFIG_PATH_CLAWDBOT}`
45
+ : `Updated ${CONFIG_PATH_CLAWDBOT} (set agent.workspace)`);
46
+ }
47
+ else {
48
+ runtime.log(`Config OK: ${CONFIG_PATH_CLAWDBOT}`);
49
+ }
50
+ const ws = await ensureAgentWorkspace({
51
+ dir: workspace,
52
+ ensureBootstrapFiles: true,
53
+ });
54
+ runtime.log(`Workspace OK: ${ws.dir}`);
55
+ const sessionsDir = resolveSessionTranscriptsDir();
56
+ await fs.mkdir(sessionsDir, { recursive: true });
57
+ runtime.log(`Sessions OK: ${sessionsDir}`);
58
+ }