discoclaw 0.1.0

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 (393) hide show
  1. package/.context/README.md +42 -0
  2. package/.context/architecture.md +58 -0
  3. package/.context/bot-setup.md +24 -0
  4. package/.context/dev.md +230 -0
  5. package/.context/discord.md +144 -0
  6. package/.context/memory.md +257 -0
  7. package/.context/ops.md +59 -0
  8. package/.context/pa-safety.md +47 -0
  9. package/.context/pa.md +118 -0
  10. package/.context/project.md +43 -0
  11. package/.context/runtime.md +253 -0
  12. package/.context/tasks.md +71 -0
  13. package/.context/tools.md +75 -0
  14. package/.env.example +88 -0
  15. package/.env.example.full +378 -0
  16. package/LICENSE +21 -0
  17. package/README.md +220 -0
  18. package/dist/beads/auto-tag.js +2 -0
  19. package/dist/beads/auto-tag.test.js +62 -0
  20. package/dist/beads/bd-cli.js +9 -0
  21. package/dist/beads/bd-cli.test.js +495 -0
  22. package/dist/beads/bead-hooks-cli.js +149 -0
  23. package/dist/beads/bead-sync-cli.js +5 -0
  24. package/dist/beads/bead-sync-cli.test.js +72 -0
  25. package/dist/beads/bead-sync-coordinator.js +4 -0
  26. package/dist/beads/bead-sync-coordinator.test.js +239 -0
  27. package/dist/beads/bead-sync-watcher.js +2 -0
  28. package/dist/beads/bead-sync-watcher.test.js +96 -0
  29. package/dist/beads/bead-sync.js +7 -0
  30. package/dist/beads/bead-sync.test.js +876 -0
  31. package/dist/beads/bead-thread-cache.js +8 -0
  32. package/dist/beads/bead-thread-cache.test.js +91 -0
  33. package/dist/beads/discord-sync.js +18 -0
  34. package/dist/beads/discord-sync.test.js +782 -0
  35. package/dist/beads/find-bead-by-thread.test.js +36 -0
  36. package/dist/beads/forum-guard.js +2 -0
  37. package/dist/beads/forum-guard.test.js +204 -0
  38. package/dist/beads/initialize.js +3 -0
  39. package/dist/beads/initialize.test.js +304 -0
  40. package/dist/beads/types.js +10 -0
  41. package/dist/cli/daemon-installer.js +225 -0
  42. package/dist/cli/daemon-installer.test.js +289 -0
  43. package/dist/cli/index.js +42 -0
  44. package/dist/cli/init-wizard.js +374 -0
  45. package/dist/cli/init-wizard.test.js +191 -0
  46. package/dist/config.js +385 -0
  47. package/dist/config.test.js +589 -0
  48. package/dist/cron/auto-tag.js +100 -0
  49. package/dist/cron/auto-tag.test.js +91 -0
  50. package/dist/cron/cadence.js +74 -0
  51. package/dist/cron/cadence.test.js +53 -0
  52. package/dist/cron/cron-sync-coordinator.js +66 -0
  53. package/dist/cron/cron-sync-coordinator.test.js +118 -0
  54. package/dist/cron/cron-sync.js +165 -0
  55. package/dist/cron/cron-sync.test.js +228 -0
  56. package/dist/cron/cron-tag-map-watcher.js +128 -0
  57. package/dist/cron/cron-tag-map-watcher.test.js +155 -0
  58. package/dist/cron/default-timezone.js +23 -0
  59. package/dist/cron/default-timezone.test.js +30 -0
  60. package/dist/cron/discord-sync.js +205 -0
  61. package/dist/cron/discord-sync.test.js +353 -0
  62. package/dist/cron/executor.js +303 -0
  63. package/dist/cron/executor.test.js +614 -0
  64. package/dist/cron/forum-sync.js +347 -0
  65. package/dist/cron/forum-sync.test.js +539 -0
  66. package/dist/cron/job-lock.js +164 -0
  67. package/dist/cron/job-lock.test.js +178 -0
  68. package/dist/cron/parser.js +68 -0
  69. package/dist/cron/parser.test.js +115 -0
  70. package/dist/cron/run-control.js +24 -0
  71. package/dist/cron/run-control.test.js +27 -0
  72. package/dist/cron/run-stats.js +265 -0
  73. package/dist/cron/run-stats.test.js +160 -0
  74. package/dist/cron/scheduler.js +97 -0
  75. package/dist/cron/scheduler.test.js +112 -0
  76. package/dist/cron/tag-map.js +47 -0
  77. package/dist/cron/tag-map.test.js +64 -0
  78. package/dist/cron/types.js +1 -0
  79. package/dist/discoclaw-plan-format.test.js +137 -0
  80. package/dist/discoclaw-recipe-format.test.js +137 -0
  81. package/dist/discord/abort-registry.js +70 -0
  82. package/dist/discord/action-categories.js +36 -0
  83. package/dist/discord/action-types.js +1 -0
  84. package/dist/discord/action-utils.js +58 -0
  85. package/dist/discord/action-utils.test.js +58 -0
  86. package/dist/discord/actions-beads.js +1 -0
  87. package/dist/discord/actions-beads.test.js +372 -0
  88. package/dist/discord/actions-bot-profile.js +107 -0
  89. package/dist/discord/actions-bot-profile.test.js +138 -0
  90. package/dist/discord/actions-channels.js +427 -0
  91. package/dist/discord/actions-channels.test.js +697 -0
  92. package/dist/discord/actions-config.js +173 -0
  93. package/dist/discord/actions-config.test.js +322 -0
  94. package/dist/discord/actions-crons.js +586 -0
  95. package/dist/discord/actions-crons.test.js +499 -0
  96. package/dist/discord/actions-defer.js +60 -0
  97. package/dist/discord/actions-defer.test.js +134 -0
  98. package/dist/discord/actions-forge.js +134 -0
  99. package/dist/discord/actions-forge.test.js +206 -0
  100. package/dist/discord/actions-guild.js +301 -0
  101. package/dist/discord/actions-guild.test.js +386 -0
  102. package/dist/discord/actions-memory.js +106 -0
  103. package/dist/discord/actions-memory.test.js +248 -0
  104. package/dist/discord/actions-messaging.js +401 -0
  105. package/dist/discord/actions-messaging.test.js +738 -0
  106. package/dist/discord/actions-moderation.js +65 -0
  107. package/dist/discord/actions-moderation.test.js +88 -0
  108. package/dist/discord/actions-plan.js +445 -0
  109. package/dist/discord/actions-plan.test.js +610 -0
  110. package/dist/discord/actions-poll.js +38 -0
  111. package/dist/discord/actions-poll.test.js +93 -0
  112. package/dist/discord/actions-tasks.js +3 -0
  113. package/dist/discord/actions-tasks.test.js +418 -0
  114. package/dist/discord/actions.js +600 -0
  115. package/dist/discord/actions.test.js +522 -0
  116. package/dist/discord/allowed-mentions.js +3 -0
  117. package/dist/discord/allowed-mentions.test.js +17 -0
  118. package/dist/discord/allowlist.js +29 -0
  119. package/dist/discord/allowlist.test.js +24 -0
  120. package/dist/discord/audit-handler.js +191 -0
  121. package/dist/discord/audit-handler.test.js +361 -0
  122. package/dist/discord/bot.js +141 -0
  123. package/dist/discord/channel-context.js +181 -0
  124. package/dist/discord/defer-scheduler.js +45 -0
  125. package/dist/discord/destructive-confirmation.js +128 -0
  126. package/dist/discord/destructive-confirmation.test.js +49 -0
  127. package/dist/discord/discord-plan-auto-implement.test.js +18 -0
  128. package/dist/discord/durable-memory.js +145 -0
  129. package/dist/discord/durable-memory.test.js +281 -0
  130. package/dist/discord/durable-write-queue.js +4 -0
  131. package/dist/discord/file-download.js +308 -0
  132. package/dist/discord/file-download.test.js +303 -0
  133. package/dist/discord/forge-audit-verdict.js +140 -0
  134. package/dist/discord/forge-auto-implement.js +80 -0
  135. package/dist/discord/forge-auto-implement.test.js +110 -0
  136. package/dist/discord/forge-commands.js +698 -0
  137. package/dist/discord/forge-commands.test.js +1606 -0
  138. package/dist/discord/forge-plan-registry.js +68 -0
  139. package/dist/discord/forge-plan-registry.test.js +127 -0
  140. package/dist/discord/forum-count-sync.js +130 -0
  141. package/dist/discord/forum-count-sync.test.js +200 -0
  142. package/dist/discord/health-command.js +98 -0
  143. package/dist/discord/health-command.test.js +195 -0
  144. package/dist/discord/help-command.js +22 -0
  145. package/dist/discord/help-command.test.js +49 -0
  146. package/dist/discord/image-download.js +201 -0
  147. package/dist/discord/image-download.test.js +499 -0
  148. package/dist/discord/inflight-replies.js +228 -0
  149. package/dist/discord/inflight-replies.test.js +295 -0
  150. package/dist/discord/json-extract.js +110 -0
  151. package/dist/discord/keyed-queue.js +22 -0
  152. package/dist/discord/memory-commands.js +85 -0
  153. package/dist/discord/memory-commands.test.js +159 -0
  154. package/dist/discord/memory-timing.integration.test.js +159 -0
  155. package/dist/discord/message-coordinator.js +2347 -0
  156. package/dist/discord/message-coordinator.onboarding.test.js +183 -0
  157. package/dist/discord/message-coordinator.plan-run.test.js +264 -0
  158. package/dist/discord/message-history.js +53 -0
  159. package/dist/discord/message-history.test.js +95 -0
  160. package/dist/discord/models-command.js +59 -0
  161. package/dist/discord/models-command.test.js +150 -0
  162. package/dist/discord/nickname.test.js +76 -0
  163. package/dist/discord/onboarding-completion.js +55 -0
  164. package/dist/discord/onboarding-completion.test.js +176 -0
  165. package/dist/discord/output-common.js +178 -0
  166. package/dist/discord/output-common.test.js +198 -0
  167. package/dist/discord/output-utils.js +156 -0
  168. package/dist/discord/parse-identity-name.test.js +129 -0
  169. package/dist/discord/plan-commands.js +612 -0
  170. package/dist/discord/plan-commands.test.js +1622 -0
  171. package/dist/discord/plan-manager.js +1491 -0
  172. package/dist/discord/plan-manager.test.js +2380 -0
  173. package/dist/discord/plan-parser.js +110 -0
  174. package/dist/discord/plan-parser.test.js +63 -0
  175. package/dist/discord/plan-run-phase-start.js +20 -0
  176. package/dist/discord/plan-run-phase-start.test.js +29 -0
  177. package/dist/discord/platform-message.js +45 -0
  178. package/dist/discord/platform-message.test.js +110 -0
  179. package/dist/discord/prompt-common.js +240 -0
  180. package/dist/discord/prompt-common.test.js +423 -0
  181. package/dist/discord/reaction-handler.js +691 -0
  182. package/dist/discord/reaction-handler.test.js +1574 -0
  183. package/dist/discord/reaction-prompts.js +118 -0
  184. package/dist/discord/reaction-prompts.test.js +253 -0
  185. package/dist/discord/reply-reference.js +66 -0
  186. package/dist/discord/reply-reference.test.js +125 -0
  187. package/dist/discord/restart-command.js +143 -0
  188. package/dist/discord/restart-command.test.js +196 -0
  189. package/dist/discord/runtime-utils.js +43 -0
  190. package/dist/discord/runtime-utils.test.js +112 -0
  191. package/dist/discord/session-key.js +7 -0
  192. package/dist/discord/session-key.test.js +13 -0
  193. package/dist/discord/shortterm-memory.js +166 -0
  194. package/dist/discord/shortterm-memory.test.js +345 -0
  195. package/dist/discord/shutdown-context.js +122 -0
  196. package/dist/discord/shutdown-context.test.js +279 -0
  197. package/dist/discord/startup-profile.test.js +214 -0
  198. package/dist/discord/status-channel.js +190 -0
  199. package/dist/discord/status-channel.test.js +282 -0
  200. package/dist/discord/status-command.js +206 -0
  201. package/dist/discord/status-command.test.js +341 -0
  202. package/dist/discord/streaming-progress.js +107 -0
  203. package/dist/discord/streaming-progress.test.js +93 -0
  204. package/dist/discord/summarizer.js +89 -0
  205. package/dist/discord/summarizer.test.js +245 -0
  206. package/dist/discord/system-bootstrap.js +396 -0
  207. package/dist/discord/system-bootstrap.test.js +724 -0
  208. package/dist/discord/thread-context.js +169 -0
  209. package/dist/discord/thread-context.test.js +386 -0
  210. package/dist/discord/tool-aware-queue.js +116 -0
  211. package/dist/discord/tool-aware-queue.test.js +180 -0
  212. package/dist/discord/update-command.js +127 -0
  213. package/dist/discord/update-command.test.js +275 -0
  214. package/dist/discord/user-errors.js +40 -0
  215. package/dist/discord/user-errors.test.js +31 -0
  216. package/dist/discord/user-turn-to-durable.js +111 -0
  217. package/dist/discord/user-turn-to-durable.test.js +273 -0
  218. package/dist/discord-followup.test.js +677 -0
  219. package/dist/discord.channel-context.test.js +95 -0
  220. package/dist/discord.fail-closed.test.js +199 -0
  221. package/dist/discord.health-command.integration.test.js +140 -0
  222. package/dist/discord.js +190 -0
  223. package/dist/discord.prompt-context.test.js +1431 -0
  224. package/dist/discord.render.test.js +621 -0
  225. package/dist/discord.status-wiring.test.js +187 -0
  226. package/dist/engine/claudeCli.js +137 -0
  227. package/dist/engine/types.js +1 -0
  228. package/dist/group-queue.js +25 -0
  229. package/dist/health/credential-check.js +175 -0
  230. package/dist/health/credential-check.test.js +401 -0
  231. package/dist/health/startup-healing.js +139 -0
  232. package/dist/health/startup-healing.test.js +298 -0
  233. package/dist/identity.js +36 -0
  234. package/dist/index.js +1378 -0
  235. package/dist/logging/logger-like.js +1 -0
  236. package/dist/observability/memory-sampler.js +51 -0
  237. package/dist/observability/memory-sampler.test.js +93 -0
  238. package/dist/observability/metrics.js +88 -0
  239. package/dist/observability/metrics.test.js +42 -0
  240. package/dist/onboarding/onboarding-flow.js +246 -0
  241. package/dist/onboarding/onboarding-flow.test.js +238 -0
  242. package/dist/onboarding/onboarding-writer.js +102 -0
  243. package/dist/onboarding/onboarding-writer.test.js +143 -0
  244. package/dist/pidlock.js +187 -0
  245. package/dist/pidlock.test.js +128 -0
  246. package/dist/pipeline/engine.js +206 -0
  247. package/dist/pipeline/engine.test.js +771 -0
  248. package/dist/root-policy.js +21 -0
  249. package/dist/root-policy.test.js +55 -0
  250. package/dist/runtime/claude-code-cli.js +35 -0
  251. package/dist/runtime/claude-code-cli.test.js +1199 -0
  252. package/dist/runtime/cli-adapter.js +584 -0
  253. package/dist/runtime/cli-output-parsers.js +108 -0
  254. package/dist/runtime/cli-shared.js +96 -0
  255. package/dist/runtime/cli-shared.test.js +104 -0
  256. package/dist/runtime/cli-strategy.js +6 -0
  257. package/dist/runtime/codex-cli.js +16 -0
  258. package/dist/runtime/codex-cli.test.js +862 -0
  259. package/dist/runtime/concurrency-limit.js +80 -0
  260. package/dist/runtime/concurrency-limit.test.js +137 -0
  261. package/dist/runtime/gemini-cli.js +16 -0
  262. package/dist/runtime/gemini-cli.test.js +413 -0
  263. package/dist/runtime/long-running-process.js +415 -0
  264. package/dist/runtime/long-running-process.test.js +318 -0
  265. package/dist/runtime/model-smoke-helpers.js +160 -0
  266. package/dist/runtime/model-smoke.test.js +194 -0
  267. package/dist/runtime/model-tiers.js +33 -0
  268. package/dist/runtime/model-tiers.test.js +65 -0
  269. package/dist/runtime/openai-auth.js +151 -0
  270. package/dist/runtime/openai-auth.test.js +361 -0
  271. package/dist/runtime/openai-compat.js +178 -0
  272. package/dist/runtime/openai-compat.test.js +449 -0
  273. package/dist/runtime/process-pool.js +93 -0
  274. package/dist/runtime/process-pool.test.js +148 -0
  275. package/dist/runtime/registry.js +15 -0
  276. package/dist/runtime/registry.test.js +47 -0
  277. package/dist/runtime/session-scanner.js +186 -0
  278. package/dist/runtime/session-scanner.test.js +257 -0
  279. package/dist/runtime/strategies/claude-strategy.js +193 -0
  280. package/dist/runtime/strategies/codex-strategy.js +161 -0
  281. package/dist/runtime/strategies/gemini-strategy.js +64 -0
  282. package/dist/runtime/strategies/template-strategy.js +85 -0
  283. package/dist/runtime/tool-capabilities.js +27 -0
  284. package/dist/runtime/tool-capabilities.test.js +24 -0
  285. package/dist/runtime/tool-labels.js +48 -0
  286. package/dist/runtime/types.js +2 -0
  287. package/dist/sessionManager.js +47 -0
  288. package/dist/sessions.js +18 -0
  289. package/dist/tasks/architecture-contract.js +33 -0
  290. package/dist/tasks/architecture-contract.test.js +90 -0
  291. package/dist/tasks/auto-tag.js +50 -0
  292. package/dist/tasks/auto-tag.test.js +64 -0
  293. package/dist/tasks/bd-cli.js +164 -0
  294. package/dist/tasks/bd-cli.test.js +359 -0
  295. package/dist/tasks/bead-sync.js +1 -0
  296. package/dist/tasks/context-summary.js +27 -0
  297. package/dist/tasks/discord-sync.js +3 -0
  298. package/dist/tasks/discord-sync.test.js +685 -0
  299. package/dist/tasks/discord-types.js +4 -0
  300. package/dist/tasks/find-task-by-thread.test.js +36 -0
  301. package/dist/tasks/forum-guard.js +81 -0
  302. package/dist/tasks/forum-guard.test.js +192 -0
  303. package/dist/tasks/initialize.js +77 -0
  304. package/dist/tasks/initialize.test.js +263 -0
  305. package/dist/tasks/logger-types.js +1 -0
  306. package/dist/tasks/metrics-types.js +3 -0
  307. package/dist/tasks/migrate.js +33 -0
  308. package/dist/tasks/migrate.test.js +156 -0
  309. package/dist/tasks/path-defaults.js +67 -0
  310. package/dist/tasks/path-defaults.test.js +73 -0
  311. package/dist/tasks/runtime-types.js +1 -0
  312. package/dist/tasks/service.js +33 -0
  313. package/dist/tasks/service.test.js +51 -0
  314. package/dist/tasks/store.js +238 -0
  315. package/dist/tasks/store.test.js +417 -0
  316. package/dist/tasks/sync-context.js +1 -0
  317. package/dist/tasks/sync-contract.js +24 -0
  318. package/dist/tasks/sync-contract.test.js +25 -0
  319. package/dist/tasks/sync-coordinator-metrics.js +41 -0
  320. package/dist/tasks/sync-coordinator-retries.js +71 -0
  321. package/dist/tasks/sync-coordinator.js +96 -0
  322. package/dist/tasks/sync-coordinator.test.js +501 -0
  323. package/dist/tasks/sync-types.js +1 -0
  324. package/dist/tasks/sync-watcher.js +27 -0
  325. package/dist/tasks/sync-watcher.test.js +92 -0
  326. package/dist/tasks/tag-map.js +36 -0
  327. package/dist/tasks/tag-map.test.js +54 -0
  328. package/dist/tasks/task-action-contract.js +16 -0
  329. package/dist/tasks/task-action-contract.test.js +16 -0
  330. package/dist/tasks/task-action-executor.js +18 -0
  331. package/dist/tasks/task-action-executor.test.js +420 -0
  332. package/dist/tasks/task-action-mutation-helpers.js +17 -0
  333. package/dist/tasks/task-action-mutations.js +151 -0
  334. package/dist/tasks/task-action-prompt.js +62 -0
  335. package/dist/tasks/task-action-read-ops.js +73 -0
  336. package/dist/tasks/task-action-runner-types.js +1 -0
  337. package/dist/tasks/task-action-thread-sync.js +82 -0
  338. package/dist/tasks/task-actions.js +3 -0
  339. package/dist/tasks/task-cli.js +227 -0
  340. package/dist/tasks/task-context.js +1 -0
  341. package/dist/tasks/task-lifecycle.js +46 -0
  342. package/dist/tasks/task-lifecycle.test.js +35 -0
  343. package/dist/tasks/task-sync-apply-plan.js +95 -0
  344. package/dist/tasks/task-sync-apply-types.js +12 -0
  345. package/dist/tasks/task-sync-apply.js +319 -0
  346. package/dist/tasks/task-sync-cli.js +89 -0
  347. package/dist/tasks/task-sync-cli.test.js +70 -0
  348. package/dist/tasks/task-sync-engine.js +88 -0
  349. package/dist/tasks/task-sync-engine.test.js +934 -0
  350. package/dist/tasks/task-sync-phase-apply.js +171 -0
  351. package/dist/tasks/task-sync-pipeline.js +2 -0
  352. package/dist/tasks/task-sync-pipeline.test.js +265 -0
  353. package/dist/tasks/task-sync-reconcile-plan.js +182 -0
  354. package/dist/tasks/task-sync-reconcile.js +144 -0
  355. package/dist/tasks/task-sync.js +56 -0
  356. package/dist/tasks/task-sync.test.js +86 -0
  357. package/dist/tasks/thread-cache.js +42 -0
  358. package/dist/tasks/thread-cache.test.js +89 -0
  359. package/dist/tasks/thread-contracts.test.js +711 -0
  360. package/dist/tasks/thread-forum-ops.js +68 -0
  361. package/dist/tasks/thread-helpers.js +86 -0
  362. package/dist/tasks/thread-helpers.test.js +33 -0
  363. package/dist/tasks/thread-lifecycle-ops.js +144 -0
  364. package/dist/tasks/thread-ops-shared.js +21 -0
  365. package/dist/tasks/thread-ops.js +2 -0
  366. package/dist/tasks/types.js +20 -0
  367. package/dist/tasks/types.test.js +60 -0
  368. package/dist/test-setup.js +11 -0
  369. package/dist/test-setup.test.js +42 -0
  370. package/dist/transport/types.js +1 -0
  371. package/dist/validate.js +41 -0
  372. package/dist/validate.test.js +94 -0
  373. package/dist/version.js +15 -0
  374. package/dist/version.test.js +31 -0
  375. package/dist/webhook/server.js +199 -0
  376. package/dist/webhook/server.test.js +460 -0
  377. package/dist/workspace-bootstrap.js +135 -0
  378. package/dist/workspace-bootstrap.test.js +514 -0
  379. package/dist/workspace-permissions.js +134 -0
  380. package/dist/workspace-permissions.test.js +181 -0
  381. package/package.json +74 -0
  382. package/scripts/cron/cron-tag-map.json +9 -0
  383. package/scripts/tasks/tag-map.json +10 -0
  384. package/systemd/discoclaw.service +19 -0
  385. package/templates/recipes/integration.discoclaw-recipe.md +171 -0
  386. package/templates/workspace/AGENTS.md +217 -0
  387. package/templates/workspace/BOOTSTRAP.md +1 -0
  388. package/templates/workspace/HEARTBEAT.md +10 -0
  389. package/templates/workspace/IDENTITY.md +16 -0
  390. package/templates/workspace/MEMORY.md +24 -0
  391. package/templates/workspace/SOUL.md +52 -0
  392. package/templates/workspace/TOOLS.md +304 -0
  393. package/templates/workspace/USER.md +37 -0
@@ -0,0 +1,253 @@
1
+ # runtime.md — Runtimes & Adapters
2
+
3
+ ## Model Names & IDs
4
+
5
+ **Always research official documentation** when referencing model names, IDs, or parameters — never guess or rely on training data alone. Model names change frequently across providers.
6
+
7
+ Sources to check:
8
+ - **Anthropic:** https://platform.claude.com/docs/en/about-claude/models/overview
9
+ - **OpenAI/Codex:** https://developers.openai.com/codex/models/
10
+ - **Claude Code CLI shorthand:** `sonnet`, `opus`, `haiku` resolve to the latest version of each model family
11
+
12
+ Current model IDs (as of 2026-02-17):
13
+ | Provider | Model | API/CLI ID |
14
+ |----------|-------|-----------|
15
+ | Anthropic | Claude Opus 4.6 | `claude-opus-4-6` (CLI shorthand: `opus`) |
16
+ | Anthropic | Claude Sonnet 4.6 | `claude-sonnet-4-6` (CLI shorthand: `sonnet`) |
17
+ | Anthropic | Claude Haiku 4.5 | `claude-haiku-4-5-20251001` (CLI shorthand: `haiku`) |
18
+ | OpenAI | GPT-5.3-Codex | `gpt-5.3-codex` |
19
+ | OpenAI | GPT-5.3-Codex-Spark | `gpt-5.3-codex-spark` |
20
+ | OpenAI | GPT-5-Codex-Mini | `gpt-5-codex-mini` |
21
+
22
+ ## Runtime Adapter Interface
23
+ - The orchestrator consumes a provider-agnostic event stream (`EngineEvent`) from any adapter.
24
+ - Each runtime adapter implements `RuntimeAdapter.invoke()` and declares capabilities.
25
+ - The orchestrator routes to adapters based on context: message handling, forge drafting/auditing, cron execution.
26
+
27
+ See: `src/runtime/types.ts`
28
+
29
+ ## Strategy Pattern (CLI Adapters)
30
+
31
+ All CLI-based runtime adapters share a universal factory (`src/runtime/cli-adapter.ts`) parameterized by a thin strategy object. New models only need ~40-80 lines of model-specific logic.
32
+
33
+ ```
34
+ createCliRuntime(strategy, opts) → RuntimeAdapter
35
+ ```
36
+
37
+ The strategy provides: arg building, stdin formatting, output parsing, error handling.
38
+ The factory provides: subprocess tracking, process pool, stall detection, session scanning, JSONL parsing, image dedup, event queue.
39
+
40
+ | Strategy | File | Multi-turn | Notes |
41
+ |----------|------|------------|-------|
42
+ | Claude Code | `strategies/claude-strategy.ts` | process-pool | Default JSONL parsing, image support |
43
+ | Codex CLI | `strategies/codex-strategy.ts` | session-resume | Custom JSONL (thread.started, item.completed), error sanitization; reasoning items surface in the Discord preview during streaming but are excluded from the final reply |
44
+ | Template | `strategies/template-strategy.ts` | — | Commented starting point for new models |
45
+
46
+ Thin wrappers (`claude-code-cli.ts`, `codex-cli.ts`) map legacy opts and re-export for backward compatibility. Shared utilities live in `cli-shared.ts` and `cli-output-parsers.ts`. Strategy types are in `cli-strategy.ts`.
47
+
48
+ Shutdown: `killAllSubprocesses()` from `cli-adapter.ts` kills all tracked subprocesses across all adapters.
49
+
50
+ ## Claude Code CLI Runtime (Current)
51
+ - Adapter: `src/runtime/claude-code-cli.ts` (thin wrapper around `cli-adapter.ts` + `strategies/claude-strategy.ts`)
52
+ - Invocation shape (full):
53
+ ```
54
+ claude -p --model <id|alias>
55
+ [--dangerously-skip-permissions] # when CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=1
56
+ [--strict-mcp-config] # when CLAUDE_STRICT_MCP_CONFIG=1
57
+ [--fallback-model <alias>] # when RUNTIME_FALLBACK_MODEL is set
58
+ [--max-budget-usd <number>] # when RUNTIME_MAX_BUDGET_USD is set
59
+ [--append-system-prompt <text>] # when CLAUDE_APPEND_SYSTEM_PROMPT is set
60
+ [--debug-file <path>] # when CLAUDE_DEBUG_FILE is set
61
+ [--session-id <uuid>] # when sessions are enabled
62
+ [--add-dir <dir> ...] # group CWD mode
63
+ [--output-format text|stream-json] # always passed
64
+ [--include-partial-messages] # when format is stream-json
65
+ [--tools <comma-list>] # configurable tool surface
66
+ -- <prompt> # POSIX terminator before prompt
67
+ ```
68
+ - The `--` terminator prevents variadic flags (e.g. `--tools`, `--add-dir`) from consuming the positional prompt argument.
69
+ - Output modes:
70
+ - `CLAUDE_OUTPUT_FORMAT=stream-json` (preferred; DiscoClaw parses JSONL and streams text)
71
+ - `CLAUDE_OUTPUT_FORMAT=text` (fallback if your local CLI doesn't support stream-json)
72
+
73
+ ## Tool Surface
74
+ - Default tools: `Bash, Read, Write, Edit, Glob, Grep, WebSearch, WebFetch` (8 tools).
75
+ - `Glob` + `Grep` are purpose-built for file search — faster than `find`/`grep` via Bash.
76
+ - `Write` enables proper file creation (previously required Bash echo/cat workarounds).
77
+ - Non-Claude adapters use a **capability gate** (`tools_fs`) to determine tool access:
78
+ - Codex CLI adapter: declares `tools_fs` — receives read-only tools (Read, Glob, Grep) in auditor role.
79
+ - OpenAI HTTP adapter: text-only (`streaming_text` only) — no tool execution.
80
+ - Future adapters (Gemini, etc.): declare capabilities as appropriate.
81
+
82
+ ## Per-Workspace Permissions
83
+ - `workspace/PERMISSIONS.json` controls the tool surface per workspace.
84
+ - Loaded per-invocation from `src/workspace-permissions.ts`.
85
+ - If the file doesn't exist, falls back to the `RUNTIME_TOOLS` env var (fully backward compatible).
86
+
87
+ Tiers:
88
+ | Tier | Tools |
89
+ |------|-------|
90
+ | `readonly` | `Read, Glob, Grep, WebSearch, WebFetch` |
91
+ | `standard` | `Read, Edit, Glob, Grep, WebSearch, WebFetch` |
92
+ | `full` | `Bash, Read, Write, Edit, Glob, Grep, WebSearch, WebFetch` |
93
+ | `custom` | User-specified `tools` array in the JSON |
94
+
95
+ Note: `Write` is excluded from `standard` tier (non-destructive). Included in `full` alongside Bash.
96
+
97
+ Example: `{ "tier": "standard", "note": "Never modify files outside workspace." }`
98
+
99
+ The optional `note` field is injected into the prompt as a soft behavioral constraint.
100
+ Custom tier example: `{ "tier": "custom", "tools": ["Read", "Edit", "Bash"] }`
101
+
102
+ ## Streaming & Reply Pacing (Discord)
103
+
104
+ Key settings for block streaming:
105
+ - `blockStreaming: true` — chunks output so user sees progress instead of silence then wall of text
106
+ - `blockStreamingCoalesce: {minChars:100, maxChars:600, idleMs:800}` — merges tiny fragments; 800ms idle = natural paragraph breaks
107
+ - `blockStreamingBreak: text_end` — flushes after each text block (between paragraphs, before/after tool calls)
108
+ - `toolStatusUpdates: true` — shows "Running tool..." during tool calls
109
+ - `reasoningStreaming: false` — reasoning tokens stay hidden for casual use
110
+
111
+ Tuning: too chattery? increase `minChars` or `idleMs`. Too slow? decrease `maxChars` or `idleMs`.
112
+
113
+ ## Stream Stall Detection
114
+
115
+ Two-layer protection against hung Claude Code processes:
116
+
117
+ | Env Var | Default | Purpose |
118
+ |---------|---------|---------|
119
+ | `DISCOCLAW_STREAM_STALL_TIMEOUT_MS` | `120000` | Kill one-shot process if no stdout/stderr for this long. `0` disables. |
120
+ | `DISCOCLAW_STREAM_STALL_WARNING_MS` | `60000` | Show user-visible warning in Discord after this many ms of no events. `0` disables. |
121
+
122
+ **Runtime layer** (`src/runtime/cli-adapter.ts`): resets a timer on every stdout/stderr `data` event. On timeout, emits a `stream stall: no output for ${ms}ms` error and kills the process. Applies to both `text` and `stream-json` output formats.
123
+
124
+ **Discord layer** (`src/discord.ts`, `src/discord/reaction-handler.ts`): both message and reaction handlers track `lastEventAt` and `activeToolCount` in their streaming loops. When stall threshold is exceeded and no tools are active, appends a warning to `deltaText`. Enable `DISCOCLAW_SESSION_SCANNING=1` for tool-aware stall suppression (warnings suppressed during tool execution).
125
+
126
+ ## Session Scanning & Tool-Aware Streaming
127
+
128
+ Two opt-in features for better Discord UX during tool-heavy invocations:
129
+
130
+ | Env Var | Default | Purpose |
131
+ |---------|---------|---------|
132
+ | `DISCOCLAW_SESSION_SCANNING` | `0` | Tail Claude Code's JSONL session log to emit `tool_start`/`tool_end` events |
133
+ | `DISCOCLAW_TOOL_AWARE_STREAMING` | `0` | Buffer text during tool execution, show activity indicators, stream final answer cleanly |
134
+
135
+ Both require `CLAUDE_OUTPUT_FORMAT=stream-json` for structured events.
136
+
137
+ ## Resilience & Cost Controls
138
+
139
+ | Env Var | Default | Purpose |
140
+ |---------|---------|---------|
141
+ | `RUNTIME_FALLBACK_MODEL` | *(unset)* | Auto-fallback model when primary is overloaded (e.g. `sonnet`) |
142
+ | `RUNTIME_MAX_BUDGET_USD` | *(unset)* | Max USD per CLI process. One-shot = per invocation. Multi-turn = per session lifetime |
143
+ | `CLAUDE_APPEND_SYSTEM_PROMPT` | *(unset)* | Append text to Claude's system prompt (max 4000 chars) |
144
+
145
+ **Budget semantics:** For multi-turn sessions, budget accumulates across turns and cannot be reset mid-session. Recommend $5-10 for multi-turn.
146
+
147
+ **Append system prompt:** When set, workspace PA files (SOUL.md, IDENTITY.md, USER.md, TOOLS.md) are skipped from the context file list (their content is already in the system prompt). PA context modules (`.context/pa.md`, `.context/pa-safety.md`) and channel-specific context are unaffected. **Note:** Do not set this on first run before `workspace/BOOTSTRAP.md` has been consumed — the skip logic also bypasses BOOTSTRAP.md loading.
148
+
149
+ - **Session scanner** (`src/runtime/session-scanner.ts`): watches `~/.claude/projects/<escaped-cwd>/<session-id>.jsonl`, skips pre-existing content, degrades gracefully if the file never appears.
150
+ - **Tool-aware queue** (`src/discord/tool-aware-queue.ts`): state machine that suppresses narration text before tools, shows human-readable activity labels (from `src/runtime/tool-labels.ts`), and streams the final answer after all tool use completes.
151
+ - **Tool labels** (`src/runtime/tool-labels.ts`): maps tool names to labels like "Reading .../file.ts", "Running command...", etc.
152
+
153
+ ## Multi-Turn (Long-Running Process)
154
+
155
+ Opt-in feature that keeps a long-running Claude Code subprocess alive per Discord session key using `--input-format stream-json`. Follow-up messages are pushed to the same process via stdin NDJSON, giving Claude Code native multi-turn context (tool results, file reads, edits persist across turns).
156
+
157
+ | Env Var | Default | Purpose |
158
+ |---------|---------|---------|
159
+ | `DISCOCLAW_MULTI_TURN` | `1` | Enable long-running process pool |
160
+ | `DISCOCLAW_MULTI_TURN_HANG_TIMEOUT_MS` | `60000` | Kill process if no stdout output for this long |
161
+ | `DISCOCLAW_MULTI_TURN_IDLE_TIMEOUT_MS` | `300000` | Kill idle process after 5 min of no messages |
162
+ | `DISCOCLAW_MULTI_TURN_MAX_PROCESSES` | `5` | Max concurrent long-running processes |
163
+
164
+ Key files:
165
+ - **Long-running process** (`src/runtime/long-running-process.ts`): manages a single subprocess with state machine (`idle` -> `busy` -> `idle` or `dead`), hang detection, idle timeout.
166
+ - **Process pool** (`src/runtime/process-pool.ts`): pool of `LongRunningProcess` instances keyed by session key, with LRU eviction.
167
+
168
+ Behavior:
169
+ - When enabled, `invoke()` tries the long-running process first for any call with a `sessionKey`.
170
+ - On hang detection or process crash, automatically falls back to the existing one-shot mode (unchanged).
171
+ - On shutdown, `killAllSubprocesses()` cleans up the pool.
172
+
173
+ Known limitations:
174
+ - GitHub issue #3187 reports that multi-turn stdin can hang after the first message. Mitigated by automatic hang detection + fallback.
175
+ - Prompt construction is unchanged (full context sent every turn). Optimizing to skip redundant context is a follow-up.
176
+
177
+ ## Image Input (Discord → Claude)
178
+
179
+ When a Discord message or reaction target has image attachments (PNG, JPEG, WebP, GIF), they are downloaded and sent to Claude Code as base64-encoded image content blocks via `--input-format stream-json` stdin.
180
+
181
+ ### How it works
182
+
183
+ 1. **Filtering** — `resolveMediaType()` checks the attachment's `contentType` (lowercased) or falls back to file extension. Non-image attachments are surfaced as plain URLs in the prompt text.
184
+ 2. **Validation** — Host allowlist (`cdn.discordapp.com`, `media.discordapp.net`), HTTPS-only, redirect rejection (`redirect: 'error'`), per-image and total size caps.
185
+ 3. **Download** — `downloadAttachment()` fetches the image with a 10 s timeout, post-checks actual size, and returns base64.
186
+ 4. **Delivery** — The runtime adapter writes a `stream-json` stdin message containing `[{ type: 'text', text: prompt }, { type: 'image', source: { type: 'base64', ... } }, ...]`. When images are present, `--output-format` is forced to `stream-json` regardless of the configured format.
187
+
188
+ ### Security controls
189
+
190
+ | Control | Detail |
191
+ |---------|--------|
192
+ | Host allowlist | Only Discord CDN hosts are permitted (SSRF protection) |
193
+ | HTTPS only | HTTP URLs are rejected |
194
+ | Redirect rejection | `fetch()` uses `redirect: 'error'` — no following redirects to internal hosts |
195
+ | Per-image size cap | 20 MB (`MAX_IMAGE_BYTES`), checked from metadata pre-download and from buffer post-download |
196
+ | Total size cap | 50 MB across all images in one message (`MAX_TOTAL_BYTES`) |
197
+ | Per-invocation cap | 10 images (`MAX_IMAGES_PER_INVOCATION`) |
198
+ | Download timeout | 10 s per image (`DOWNLOAD_TIMEOUT_MS`) |
199
+ | Filename sanitization | Control chars stripped, truncated to 100 chars in error messages |
200
+
201
+ ### Key files
202
+
203
+ | File | Role |
204
+ |------|------|
205
+ | `src/discord/image-download.ts` | Download, validate, base64-encode Discord attachments |
206
+ | `src/runtime/claude-code-cli.ts` | Stdin pipe construction, `effectiveOutputFormat` override |
207
+ | `src/discord.ts` | Message handler: download images, pass to runtime, images only on initial turn |
208
+ | `src/discord/reaction-handler.ts` | Reaction handler: same download flow, also surfaces non-image attachment URLs |
209
+
210
+ ### Follow-up depth gating
211
+
212
+ Images are only sent on the initial invocation (`followUpDepth === 0`). Auto-follow-up turns (triggered by query actions) are text-only — re-downloading images would waste time and bandwidth.
213
+
214
+ ## Image Output (Claude → Discord)
215
+
216
+ Any `image` content block in Claude Code's stream-json output is automatically captured and delivered as a Discord file attachment. Claude models don't natively generate images — images only appear when an MCP tool returns image content blocks.
217
+
218
+ ### How it works
219
+
220
+ 1. **Extraction** — `extractImageFromUnknownEvent()` in `claude-code-cli.ts` recognizes direct `{ type: 'image', source: { type: 'base64', media_type, data } }` blocks and `content_block_start` wrappers. `extractResultContentBlocks()` handles result events containing mixed text + image arrays.
221
+ 2. **Dedup** — `imageDedupeKey()` builds a key from media type + base64 length + 64-char prefix. Each consumer tracks a `Set<string>` of seen keys so duplicates (common with multi-turn mirrors) are dropped.
222
+ 3. **Delivery** — `buildAttachments()` in `output-common.ts` converts each `ImageData` to a Discord `AttachmentBuilder` (named `image-1.png`, etc.). The three consumer paths — message (`discord.ts`), reaction (`reaction-handler.ts`), and cron (`executor.ts`) — all collect images into an `ImageData[]` during streaming and pass them to the shared send helpers.
223
+
224
+ ### Key files
225
+
226
+ | File | Role |
227
+ |------|------|
228
+ | `src/runtime/types.ts` | `ImageData` type, `image_data` EngineEvent variant |
229
+ | `src/runtime/cli-output-parsers.ts` | Extraction, dedup key functions |
230
+ | `src/runtime/cli-adapter.ts` | Per-invocation image counting, dedup via strategy |
231
+ | `src/runtime/long-running-process.ts` | Multi-turn mirror: dedup + emit for long-running sessions |
232
+ | `src/discord/output-common.ts` | `buildAttachments()`, attachment slicing across message chunks |
233
+ | `src/discord.ts` | Message path consumer |
234
+ | `src/discord/reaction-handler.ts` | Reaction path consumer |
235
+ | `src/cron/executor.ts` | Cron path consumer |
236
+
237
+ ### Limits
238
+
239
+ | Limit | Value | Source |
240
+ |-------|-------|--------|
241
+ | Max base64 size per image | 25 MB | `MAX_IMAGE_BASE64_LEN` |
242
+ | Max images per invocation | 10 | `MAX_IMAGES_PER_INVOCATION` |
243
+ | Max attachments per Discord message | 10 | Discord API limit |
244
+
245
+ ### Enabling image generation
246
+
247
+ Since Claude can't generate images directly, you need an MCP server that wraps an external image API (DALL-E, Replicate, Stability, etc.).
248
+
249
+ 1. **Set up an MCP server** that exposes a tool (e.g. `generate_image`) returning an `image` content block with `{ type: 'base64', media_type, data }`. Any MCP server that returns image content blocks will work — the pipeline is format-driven, not tool-name-driven.
250
+ 2. **Register it** in the workspace `.mcp.json` so Claude Code loads it on invocation.
251
+ 3. **Add workspace instructions** (in `workspace/SOUL.md` or system prompt) telling the bot it can generate images and when to use the tool.
252
+
253
+ The rest is automatic: the runtime adapter extracts the image blocks, deduplicates them, and the Discord layer attaches them to the reply.
@@ -0,0 +1,71 @@
1
+ # tasks.md — Task Tracking
2
+
3
+ Tasks are backed by an in-process `TaskStore` and synced to Discord forum threads.
4
+
5
+ Ground-zero post-hard-cut refactor tracker: `docs/tasks-ground-zero-post-hard-cut-plan.md`
6
+ Ground-zero task architecture refactor status: COMPLETE (FROZEN), verified on 2026-02-21.
7
+
8
+ ## Data Model
9
+
10
+ Canonical type: `TaskData` in `src/tasks/types.ts`.
11
+
12
+ Statuses: `open` | `in_progress` | `blocked` | `closed`
13
+
14
+ ## Task Store
15
+
16
+ Implementation: `src/tasks/store.ts`
17
+
18
+ Architecture contract: `src/tasks/architecture-contract.ts`
19
+ Mutation entrypoint service: `src/tasks/service.ts`
20
+
21
+ - Synchronous in-memory writes
22
+ - Event emission on mutations (`created`, `updated`, `closed`, `labeled`)
23
+ - Optional JSONL persistence (`tasks.jsonl`)
24
+
25
+ ## Discord Sync
26
+
27
+ Canonical runtime sync implementation lives in `src/tasks/*`:
28
+
29
+ - `src/tasks/task-sync-engine.ts`
30
+ - `src/tasks/task-sync-pipeline.ts`
31
+ - `src/tasks/task-sync-apply-plan.ts`
32
+ - `src/tasks/task-sync-reconcile-plan.ts`
33
+ - `src/tasks/task-sync-apply-types.ts`
34
+ - `src/tasks/task-sync-phase-apply.ts`
35
+ - `src/tasks/task-sync-reconcile.ts`
36
+ - `src/tasks/sync-coordinator.ts`
37
+ - `src/tasks/sync-coordinator-metrics.ts`
38
+ - `src/tasks/sync-coordinator-retries.ts`
39
+ - `src/tasks/thread-helpers.ts`
40
+ - `src/tasks/thread-forum-ops.ts`
41
+ - `src/tasks/thread-lifecycle-ops.ts`
42
+ - `src/tasks/thread-ops.ts` (facade)
43
+ - `src/tasks/tag-map.ts`
44
+ - `src/tasks/thread-cache.ts`
45
+ - `src/tasks/forum-guard.ts`
46
+
47
+ Legacy runtime compatibility shims under `src/beads/` have been removed.
48
+
49
+ Primary action trigger is `taskSync` via `src/tasks/task-action-executor.ts`.
50
+
51
+ ## Auto-Tagging
52
+
53
+ Auto-tagging runs through `src/tasks/auto-tag.ts` and is controlled by the tasks env surface:
54
+
55
+ - `DISCOCLAW_TASKS_AUTO_TAG`
56
+ - `DISCOCLAW_TASKS_AUTO_TAG_MODEL`
57
+
58
+ ## Config Surface
59
+
60
+ Primary names:
61
+
62
+ - `DISCOCLAW_TASKS_ENABLED`
63
+ - `DISCOCLAW_TASKS_FORUM`
64
+ - `DISCOCLAW_TASKS_CWD`
65
+ - `DISCOCLAW_TASKS_TAG_MAP`
66
+ - `DISCOCLAW_TASKS_MENTION_USER`
67
+ - `DISCOCLAW_TASKS_SIDEBAR`
68
+ - `DISCOCLAW_TASKS_AUTO_TAG`
69
+ - `DISCOCLAW_TASKS_AUTO_TAG_MODEL`
70
+ - `DISCOCLAW_TASKS_SYNC_SKIP_PHASE5`
71
+ - `DISCOCLAW_TASKS_PREFIX`
@@ -0,0 +1,75 @@
1
+ # tools.md — Tool Capabilities
2
+
3
+ Canonical reference for tools available to the discoclaw agent.
4
+ `agent-browser` is optional — it requires a separate `npm install -g @anthropic/agent-browser` and is not bundled with discoclaw.
5
+
6
+ ## WebFetch / Browser Escalation Ladder
7
+
8
+ Use the lightest tool that works. Escalate only when a lighter level fails.
9
+
10
+ 1. **WebFetch (read-only)** — Built-in. Fetches raw page content. No JS rendering, no interaction. Try this first for any URL.
11
+ 2. **Playwright headless** — `agent-browser` launches a fresh, isolated browser with no saved state. Good for JS-rendered pages, simple form fills, screenshots. No extensions, no cookies from real sessions.
12
+ 3. **Playwright headed** — Same as above but with a visible browser window. Useful for debugging or when a site blocks headless user agents.
13
+ 4. **CDP headless (connect)** — Connects to an already-running Chrome instance via Chrome DevTools Protocol. Persistent state: logged-in sessions, cookies, extensions. Use when Playwright can't get past auth walls or bot detection.
14
+ 5. **CDP headed (connect)** — Same as CDP headless but with a visible window. Use for initial login flows where you need to watch what's happening, then switch to CDP headless for ongoing automation.
15
+
16
+ Key distinction: Playwright = fresh/isolated (no persistent state). CDP = persistent (real browser session with real cookies and extensions).
17
+
18
+ ## agent-browser Commands
19
+
20
+ These are `agent-browser`-specific commands, not generic browser automation.
21
+
22
+ | Command | Purpose |
23
+ |---------|---------|
24
+ | `navigate` | Go to a URL |
25
+ | `snapshot` | Get an accessibility snapshot of the current page |
26
+ | `interact` | Click, fill, select, check/uncheck elements |
27
+ | `keyboard` | Type text, press keys, keyboard shortcuts |
28
+ | `scroll` | Scroll the page or a specific element |
29
+ | `read` | Extract text content from elements |
30
+ | `wait` | Wait for elements, navigation, or a timeout |
31
+ | `capture` | Take a screenshot of the page or an element |
32
+
33
+ ## Playwright Modes
34
+
35
+ - **Headless (default):** No visible browser window. Faster, works on servers without a display.
36
+ - **Headed:** Visible browser window. Requires a display (or Xvfb). Use when debugging or when headless is detected/blocked.
37
+
38
+ ## CDP Connect
39
+
40
+ Use CDP when you need persistent browser state that Playwright can't provide.
41
+
42
+ **When to use:**
43
+ - Auth walls that require a real logged-in session
44
+ - Bot detection that blocks Playwright's browser fingerprint
45
+ - Sites that require specific extensions
46
+ - Reusing an existing session (e.g., already logged into a service)
47
+
48
+ **Setup — headed (for initial login):**
49
+
50
+ Launch Chrome with remote debugging enabled. The binary name varies by platform (`google-chrome`, `chromium`, `chrome`, `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`, etc.).
51
+
52
+ ```bash
53
+ google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-cdp-profile
54
+ ```
55
+
56
+ Use a dedicated profile directory (`--user-data-dir`) to avoid clobbering your daily browser profile.
57
+
58
+ **Setup — headless (for automation after login):**
59
+
60
+ ```bash
61
+ google-chrome --headless --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-cdp-profile
62
+ ```
63
+
64
+ **Workflow:**
65
+ 1. Launch Chrome headed with `--remote-debugging-port=9222`
66
+ 2. Log in manually or let the agent navigate the login flow
67
+ 3. Verify the connection: `agent-browser` connects to `http://localhost:9222`
68
+ 4. For ongoing automation, relaunch headless with the same `--user-data-dir`
69
+ 5. Shut down Chrome when done — don't leave debug ports open
70
+
71
+ ## Security Guardrails
72
+
73
+ - **CDP is ask-first.** Never connect to a real browser session without explicit user consent. CDP exposes the user's live cookies, passwords, and session tokens.
74
+ - **No browsing internal networks.** Don't navigate to `localhost`, `127.0.0.1`, `::1`, or RFC 1918 addresses (`10.*`, `172.16-31.*`, `192.168.*`) — except the CDP connect port itself (`localhost:9222`).
75
+ - **No saving auth state to tracked locations.** Cookies, tokens, screenshots with sensitive data, and browser profiles must not be saved anywhere that gets committed or pushed. Use `/tmp/` or the workspace's gitignored directories.
package/.env.example ADDED
@@ -0,0 +1,88 @@
1
+ # ============================================================
2
+ # Discoclaw — Quick Start Configuration
3
+ # ============================================================
4
+ # Copy this file to .env and fill in the REQUIRED values.
5
+ # Primary guided setup: run `discoclaw init` (global install).
6
+ # From source: run `pnpm setup` for guided interactive configuration.
7
+ # For all ~90 options, see .env.example.full
8
+ # ============================================================
9
+
10
+ # ----------------------------------------------------------
11
+ # REQUIRED — the bot won't start without these
12
+ # ----------------------------------------------------------
13
+
14
+ # Your Discord bot token (from https://discord.com/developers/applications)
15
+ # Important: Enable Message Content Intent in Developer Portal
16
+ # (Bot → Privileged Gateway Intents) or the bot receives empty messages.
17
+ DISCORD_TOKEN=
18
+
19
+ # Comma-separated Discord user IDs allowed to talk to the bot.
20
+ # Empty = nobody can use it (fail-closed).
21
+ DISCORD_ALLOW_USER_IDS=
22
+
23
+ # Tasks forum channel ID (required when DISCOCLAW_TASKS_ENABLED=1; default on).
24
+ DISCOCLAW_TASKS_FORUM=
25
+
26
+ # Automations forum channel ID (cron subsystem; required when DISCOCLAW_CRON_ENABLED=1; default on).
27
+ DISCOCLAW_CRON_FORUM=
28
+
29
+ # ----------------------------------------------------------
30
+ # CORE — most users will want to review these
31
+ # ----------------------------------------------------------
32
+
33
+ # Guild (server) ID — used for task sync and system channel bootstrap.
34
+ DISCORD_GUILD_ID=
35
+
36
+ # Where the Claude CLI runs (its working directory).
37
+ # Default: ./workspace (or $DISCOCLAW_DATA_DIR/workspace if DATA_DIR is set)
38
+ #WORKSPACE_CWD=
39
+
40
+ # Primary runtime adapter: claude | gemini | codex | openai | openrouter
41
+ # Notes:
42
+ # - openai requires OPENAI_API_KEY
43
+ # - claude requires a working Claude CLI
44
+ # - gemini requires the Gemini CLI (GEMINI_BIN)
45
+ #PRIMARY_RUNTIME=claude
46
+ # If PRIMARY_RUNTIME=codex and you want full-access mode (no approvals/sandbox):
47
+ #CODEX_DANGEROUSLY_BYPASS_APPROVALS_AND_SANDBOX=1
48
+ # Optional: isolate Codex state/sessions from ~/.codex (helps avoid stale rollout DB issues):
49
+ #CODEX_HOME=/absolute/path/to/.codex-home-discoclaw
50
+ # Disable Codex session persistence/resume (workaround for session DB issues):
51
+ #CODEX_DISABLE_SESSIONS=1
52
+
53
+ # Model tier: fast | capable (provider-agnostic).
54
+ # Concrete model names (e.g. opus, sonnet, gpt-4o) are still accepted as passthrough.
55
+ #RUNTIME_MODEL=capable
56
+
57
+ # Output format for the Claude CLI. stream-json gives smoother streaming.
58
+ #CLAUDE_OUTPUT_FORMAT=stream-json
59
+
60
+ # Allow Claude to run without permission prompts. This is what makes
61
+ # headless/Discord operation possible — the Discord allowlist above
62
+ # is the security boundary instead.
63
+ #CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=1
64
+
65
+ # Gemini CLI adapter
66
+ # Path to the Gemini CLI binary (default: gemini).
67
+ #GEMINI_BIN=gemini
68
+ # Default model for the Gemini CLI adapter.
69
+ #GEMINI_MODEL=gemini-2.5-pro
70
+
71
+ # --- OpenRouter adapter ---
72
+ #OPENROUTER_API_KEY=
73
+ #OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
74
+ #OPENROUTER_MODEL=anthropic/claude-sonnet-4
75
+
76
+ # Log level: trace | debug | info | warn | error | fatal
77
+ #LOG_LEVEL=info
78
+
79
+ # Override the default platform-detected restart command used by !restart and
80
+ # !update apply. Useful for custom setups (e.g. Docker, non-standard service
81
+ # managers, or running under a different user). If unset, the command is
82
+ # auto-selected: systemctl --user on Linux, launchctl on macOS.
83
+ #DC_RESTART_CMD=
84
+
85
+ # ----------------------------------------------------------
86
+ # For all ~90 options (subsystems, actions, memory, identity,
87
+ # observability, advanced/debug), see .env.example.full
88
+ # ----------------------------------------------------------