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,378 @@
1
+ # ============================================================
2
+ # Discoclaw — Complete Environment Reference
3
+ # ============================================================
4
+ # This is the full reference for all ~90 env vars.
5
+ # For quick start, see .env.example (only the essentials).
6
+ # Primary guided setup: run `discoclaw init` (global install).
7
+ # From source: run `pnpm setup` for guided interactive configuration.
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: You must also enable Message Content Intent in the Discord Developer Portal
16
+ # (Bot page → Privileged Gateway Intents). Without it, the bot silently 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
+ # Where the Claude CLI runs (its working directory).
34
+ # Default: ./workspace (or $DISCOCLAW_DATA_DIR/workspace if DATA_DIR is set)
35
+ #WORKSPACE_CWD=
36
+
37
+ # Primary runtime adapter for bot messages, crons, summaries, and plan execution.
38
+ # Valid values: claude | gemini | codex | openai | openrouter
39
+ # - openai requires OPENAI_API_KEY
40
+ # - openrouter requires OPENROUTER_API_KEY
41
+ # - claude requires a working Claude CLI
42
+ # - gemini requires the Gemini CLI (GEMINI_BIN)
43
+ #PRIMARY_RUNTIME=claude
44
+
45
+ # --- Primary models ---
46
+ # Model tier: fast | capable (provider-agnostic).
47
+ # Concrete model names (e.g. opus, sonnet, gpt-4o) are still accepted as passthrough.
48
+ #RUNTIME_MODEL=capable
49
+
50
+ # --- Fast-tier default ---
51
+ # Sets the default model for all "small" tasks (summary, cron, cron auto-tag, task auto-tag).
52
+ # Individual overrides (DISCOCLAW_SUMMARY_MODEL, etc.) still win when set.
53
+ #DISCOCLAW_FAST_MODEL=fast
54
+
55
+ # Output format for the Claude CLI. stream-json gives smoother streaming.
56
+ #CLAUDE_OUTPUT_FORMAT=stream-json
57
+
58
+ # Allow Claude to run without permission prompts. This is what makes
59
+ # headless/Discord operation possible — the Discord allowlist above
60
+ # is the security boundary instead.
61
+ #CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=1
62
+
63
+ # --- Gemini CLI adapter ---
64
+ # Path to the Gemini CLI binary (default: gemini).
65
+ #GEMINI_BIN=gemini
66
+ # Default model for the Gemini CLI adapter.
67
+ #GEMINI_MODEL=gemini-2.5-pro
68
+
69
+ # Log level: trace | debug | info | warn | error | fatal
70
+ #LOG_LEVEL=info
71
+
72
+ # ============================================================
73
+ # CORE SUBSYSTEMS — enabled by default, configure as needed
74
+ # ============================================================
75
+
76
+ # ----------------------------------------------------------
77
+ # Cron — forum-based scheduled tasks (enabled by default)
78
+ # ----------------------------------------------------------
79
+ # Forum channel ID is configured above in REQUIRED.
80
+ # Model tier for cron execution: fast | capable (concrete names accepted as passthrough).
81
+ #DISCOCLAW_CRON_MODEL=fast
82
+ # Enable cron Discord actions (CRUD via Discord action blocks).
83
+ #DISCOCLAW_DISCORD_ACTIONS_CRONS=1
84
+ # Persistent stats directory (run counts, last run time, status).
85
+ #DISCOCLAW_CRON_STATS_DIR=
86
+ # AI auto-tagging for cron purpose + model tier (off until tags bootstrapped).
87
+ #DISCOCLAW_CRON_AUTO_TAG=0
88
+ #DISCOCLAW_CRON_AUTO_TAG_MODEL=fast
89
+ # Runtime tag-map file (seeded from scripts/cron/cron-tag-map.json on first boot).
90
+ #DISCOCLAW_CRON_TAG_MAP=
91
+ # Set to 0 to disable cron entirely.
92
+ #DISCOCLAW_CRON_ENABLED=1
93
+
94
+ # ----------------------------------------------------------
95
+ # Tasks — task tracking (enabled by default)
96
+ # ----------------------------------------------------------
97
+ # Forum channel ID is configured above in REQUIRED.
98
+ # Guild ID — used for task sync bootstrap and system channel bootstrap.
99
+ # Also used for System channel bootstrap when the bot is in multiple servers.
100
+ DISCORD_GUILD_ID=
101
+ # Runtime tag-map file (seeded from scripts/tasks/tag-map.json on first boot).
102
+ #DISCOCLAW_TASKS_TAG_MAP=
103
+ # Skip Phase 5 (thread reconciliation) during task sync. Useful for shared-forum deployments
104
+ # where multiple instances share the same forum and you don't want cross-instance archival.
105
+ #DISCOCLAW_TASKS_SYNC_SKIP_PHASE5=0
106
+ # Enable/disable retries after sync failures.
107
+ #DISCOCLAW_TASKS_SYNC_FAILURE_RETRY_ENABLED=1
108
+ # Delay before failure retries (ms).
109
+ #DISCOCLAW_TASKS_SYNC_FAILURE_RETRY_DELAY_MS=30000
110
+ # Delay before deferred-close retries (ms).
111
+ #DISCOCLAW_TASKS_SYNC_DEFERRED_RETRY_DELAY_MS=30000
112
+ #DISCOCLAW_TASKS_MENTION_USER=
113
+ # When 1 and MENTION_USER set, open task starters keep @mention for sidebar visibility; removed on close.
114
+ #DISCOCLAW_TASKS_SIDEBAR=0
115
+ #DISCOCLAW_TASKS_AUTO_TAG=1
116
+ #DISCOCLAW_TASKS_AUTO_TAG_MODEL=fast
117
+ # Set to 0 to disable tasks entirely.
118
+ #DISCOCLAW_TASKS_ENABLED=1
119
+ # Prefix for generated task IDs (e.g. ws-001).
120
+ #DISCOCLAW_TASKS_PREFIX=ws
121
+
122
+ # ----------------------------------------------------------
123
+ # Discord actions — let Claude manage your server (enabled by default)
124
+ # ----------------------------------------------------------
125
+ # Master switch — must be 1 for any action category to work (default: 1).
126
+ # Enabling it unlocks the defer command below (and all other action categories).
127
+ #DISCOCLAW_DISCORD_ACTIONS=1
128
+ # Per-category flags (only active when master switch is 1):
129
+ #DISCOCLAW_DISCORD_ACTIONS_CHANNELS=1
130
+ #DISCOCLAW_DISCORD_ACTIONS_MESSAGING=0
131
+ #DISCOCLAW_DISCORD_ACTIONS_GUILD=0
132
+ # Intentionally off — moderation actions require explicit opt-in.
133
+ #DISCOCLAW_DISCORD_ACTIONS_MODERATION=0
134
+ #DISCOCLAW_DISCORD_ACTIONS_POLLS=0
135
+ #DISCOCLAW_DISCORD_ACTIONS_TASKS=1
136
+ # Allow the AI to self-initiate forge runs (draft + audit loops) via action blocks.
137
+ # Requires DISCOCLAW_FORGE_COMMANDS_ENABLED=1. Only one forge at a time. Default: 1.
138
+ #DISCOCLAW_DISCORD_ACTIONS_FORGE=1
139
+ # Allow the AI to create, inspect, approve, run, and close plans via action blocks.
140
+ # Requires DISCOCLAW_PLAN_COMMANDS_ENABLED=1. Default: 1.
141
+ #DISCOCLAW_DISCORD_ACTIONS_PLAN=1
142
+ # Allow the AI to read/write durable memory (facts, preferences) via action blocks.
143
+ # Requires DISCOCLAW_DURABLE_MEMORY_ENABLED=1. Default: 1.
144
+ #DISCOCLAW_DISCORD_ACTIONS_MEMORY=1
145
+ # Allow the AI to change status, activity, and nickname at runtime.
146
+ #DISCOCLAW_DISCORD_ACTIONS_BOT_PROFILE=0
147
+
148
+ # Allow the AI to defer another invocation (e.g., "check on the forge run in 10 minutes").
149
+ # The scheduler enforces DISCOCLAW_DISCORD_ACTIONS=1, respects the requesting message's channel
150
+ # permissions, and prevents chaining by disabling defer during the follow-up run.
151
+ DISCOCLAW_DISCORD_ACTIONS_DEFER=1
152
+ # Optional guard rails keep deferred invocations within safe bounds.
153
+ # Maximum delay (seconds) the scheduler will accept for defer commands (default: 1800 / 30 min).
154
+ #DISCOCLAW_DISCORD_ACTIONS_DEFER_MAX_DELAY_SECONDS=1800
155
+ # Maximum number of pending deferred invocations allowed at once (default: 5).
156
+ #DISCOCLAW_DISCORD_ACTIONS_DEFER_MAX_CONCURRENT=5
157
+
158
+ # ============================================================
159
+ # OPTIONAL — uncomment sections you need
160
+ # ============================================================
161
+
162
+ # ----------------------------------------------------------
163
+ # Channel restrictions
164
+ # ----------------------------------------------------------
165
+ # Restrict the bot to specific guild channel IDs (comma/space-separated).
166
+ # DMs are still allowed. For threads, allowlist the parent channel ID.
167
+ #DISCORD_CHANNEL_IDS=
168
+ # Require a channel-context file to exist before responding in a channel.
169
+ #DISCORD_REQUIRE_CHANNEL_CONTEXT=1
170
+ # Auto-create channel context scaffold on first message in a new channel.
171
+ #DISCORD_AUTO_INDEX_CHANNEL_CONTEXT=1
172
+ # Auto-join threads so the bot can respond inside them.
173
+ # Note: private threads still require manually adding the bot.
174
+ #DISCORD_AUTO_JOIN_THREADS=0
175
+
176
+ # ----------------------------------------------------------
177
+ # Reaction handler (trigger AI via emoji reactions)
178
+ # ----------------------------------------------------------
179
+ # Master switch — when enabled, reacting to a message with any emoji
180
+ # triggers the AI to respond to that message (allowlist still applies).
181
+ #DISCOCLAW_REACTION_HANDLER=0
182
+ # Ignore reactions on messages older than this many hours (prevents
183
+ # accidental triggers when scrolling through old history).
184
+ #DISCOCLAW_REACTION_MAX_AGE_HOURS=24
185
+ # Reaction-remove handler — fires when a user removes a reaction.
186
+ # Disabled by default; useful for workflows where un-reacting has meaning.
187
+ #DISCOCLAW_REACTION_REMOVE_HANDLER=0
188
+ # Note: 🛑 reactions on bot in-progress messages are reserved for aborting the active stream and will never trigger an AI invocation.
189
+
190
+ # ----------------------------------------------------------
191
+ # Memory & summaries
192
+ # ----------------------------------------------------------
193
+ # Rolling AI-generated summaries of past conversations.
194
+ #DISCOCLAW_SUMMARY_ENABLED=1
195
+ #DISCOCLAW_SUMMARY_MODEL=fast
196
+ #DISCOCLAW_SUMMARY_MAX_CHARS=2000
197
+ #DISCOCLAW_SUMMARY_EVERY_N_TURNS=5
198
+ # Durable per-user facts/preferences (manual via !memory commands).
199
+ #DISCOCLAW_DURABLE_MEMORY_ENABLED=1
200
+ #DISCOCLAW_DURABLE_INJECT_MAX_CHARS=2000
201
+ #DISCOCLAW_DURABLE_MAX_ITEMS=200
202
+ #DISCOCLAW_MEMORY_COMMANDS_ENABLED=1
203
+ # Cross-channel short-term memory (per-guild, per-user ring buffer).
204
+ # Records recent exchanges across public channels for cross-channel awareness.
205
+ #DISCOCLAW_SHORTTERM_MEMORY_ENABLED=0
206
+ #DISCOCLAW_SHORTTERM_MAX_ENTRIES=20
207
+ #DISCOCLAW_SHORTTERM_MAX_AGE_HOURS=6
208
+ #DISCOCLAW_SHORTTERM_INJECT_MAX_CHARS=1000
209
+ # Auto-extract notable facts from user messages into durable memory.
210
+ # Runs after rolling summary generation. Default on.
211
+ #DISCOCLAW_SUMMARY_TO_DURABLE_ENABLED=1
212
+ # Character budget for recent conversation history in prompts (0 = disabled).
213
+ #DISCOCLAW_MESSAGE_HISTORY_BUDGET=3000
214
+
215
+ # ----------------------------------------------------------
216
+ # Bot identity
217
+ # ----------------------------------------------------------
218
+ # Bot display name (server nickname). Falls back to workspace/IDENTITY.md name, then "Discoclaw".
219
+ #DISCOCLAW_BOT_NAME=
220
+ # Presence status on startup: online | idle | dnd | invisible (default: don't set)
221
+ #DISCOCLAW_BOT_STATUS=
222
+ # Activity text on startup (empty = no activity)
223
+ #DISCOCLAW_BOT_ACTIVITY=
224
+ # Activity type: Playing (default) | Listening | Watching | Competing | Custom
225
+ #DISCOCLAW_BOT_ACTIVITY_TYPE=Playing
226
+ # Avatar image: absolute file path or URL (applied once on startup; empty = don't change)
227
+ #DISCOCLAW_BOT_AVATAR=
228
+
229
+ # ----------------------------------------------------------
230
+ # Status & observability
231
+ # ----------------------------------------------------------
232
+ # Channel name or ID to post status embeds (bot online/offline, errors).
233
+ #DISCOCLAW_STATUS_CHANNEL=
234
+ # Enable health commands (`!health`, `!health verbose`) for allowlisted users.
235
+ #DISCOCLAW_HEALTH_COMMANDS_ENABLED=1
236
+ # Optional subset allowlist for `!health verbose` (comma/space-separated IDs).
237
+ # Empty = any allowlisted user can use verbose mode.
238
+ #DISCOCLAW_HEALTH_VERBOSE_ALLOWLIST=
239
+
240
+ # ----------------------------------------------------------
241
+ # Advanced / debug
242
+ # ----------------------------------------------------------
243
+ # Data root — if set, workspace defaults to $DISCOCLAW_DATA_DIR/workspace.
244
+ #DISCOCLAW_DATA_DIR=
245
+ # Content directory override.
246
+ #DISCOCLAW_CONTENT_DIR=
247
+ # Enable per-session runtime isolation.
248
+ #DISCOCLAW_RUNTIME_SESSIONS=1
249
+ # Path to claude CLI binary (if not on $PATH).
250
+ #CLAUDE_BIN=claude
251
+ # Forward Claude CLI stderr to Discord (useful for debugging).
252
+ #CLAUDE_ECHO_STDIO=0
253
+ # Pass --verbose to the Claude CLI for increased output detail.
254
+ # Requires CLAUDE_OUTPUT_FORMAT=stream-json (auto-disabled with text format).
255
+ #CLAUDE_VERBOSE=0
256
+ # Write Claude CLI debug logs to this file.
257
+ #CLAUDE_DEBUG_FILE=
258
+ # Skip slow MCP plugin init in headless/systemd contexts.
259
+ #CLAUDE_STRICT_MCP_CONFIG=1
260
+ # Dump resolved runtime config at startup.
261
+ #DISCOCLAW_DEBUG_RUNTIME=0
262
+ # Per-group working directories.
263
+ #GROUPS_DIR=
264
+ #USE_GROUP_DIR_CWD=0
265
+ # Tools available to the runtime (Glob, Grep, Write now included by default).
266
+ #RUNTIME_TOOLS=Bash,Read,Write,Edit,Glob,Grep,WebSearch,WebFetch
267
+ # Fallback model tier when primary is overloaded (concrete names accepted as passthrough).
268
+ #RUNTIME_FALLBACK_MODEL=fast
269
+ # Max USD spend per Claude CLI process. One-shot: per invocation.
270
+ # Multi-turn: per session lifetime (accumulates across turns). Recommend $5-10.
271
+ #RUNTIME_MAX_BUDGET_USD=5.00
272
+ # Append to Claude's system prompt (pre-loads PA identity, skips workspace PA file reads).
273
+ # Max 4000 chars. Condense SOUL.md + IDENTITY.md + USER.md + TOOLS.md content here.
274
+ # Note: Do not set this on first run before workspace/BOOTSTRAP.md has been consumed,
275
+ # as the skip logic also bypasses BOOTSTRAP.md loading.
276
+ #CLAUDE_APPEND_SYSTEM_PROMPT=
277
+ # Override the default platform-detected restart command used by !restart and
278
+ # !update apply. Useful for custom setups (e.g. Docker, non-standard service
279
+ # managers, or running under a different user). If unset, the command is
280
+ # auto-selected: systemctl --user on Linux, launchctl on macOS.
281
+ #DC_RESTART_CMD=
282
+ # Global cap on parallel runtime invocations across all Discord sessions (0 = unlimited).
283
+ #DISCOCLAW_MAX_CONCURRENT_INVOCATIONS=3
284
+ # Timeout for runtime invocations (ms).
285
+ #RUNTIME_TIMEOUT_MS=1800000
286
+ # Stream stall detection: kill one-shot process if no stdout/stderr for this long (ms). 0 = disabled.
287
+ #DISCOCLAW_STREAM_STALL_TIMEOUT_MS=120000
288
+ # Stream stall warning: show user-visible warning in Discord after this many ms of no events. 0 = disabled.
289
+ # Enable DISCOCLAW_SESSION_SCANNING=1 for tool-aware stall suppression (warnings suppressed during tool execution).
290
+ #DISCOCLAW_STREAM_STALL_WARNING_MS=60000
291
+
292
+ # ----------------------------------------------------------
293
+ # Plan & Forge — AI-assisted planning and implementation
294
+ # ----------------------------------------------------------
295
+ # Enable/disable !plan and !forge commands.
296
+ #DISCOCLAW_PLAN_COMMANDS_ENABLED=1
297
+ #DISCOCLAW_FORGE_COMMANDS_ENABLED=1
298
+ # Phase decomposition for approved plans.
299
+ #PLAN_PHASES_ENABLED=1
300
+ # Max files per phase batch during decomposition.
301
+ #PLAN_PHASE_MAX_CONTEXT_FILES=5
302
+ # Per-phase execution timeout (ms). Default: 1800000 (30 min).
303
+ #PLAN_PHASE_TIMEOUT_MS=1800000
304
+ # Max audit-fix attempts per phase before marking failed.
305
+ #PLAN_PHASE_AUDIT_FIX_MAX=2
306
+ # Max draft-audit-revise loops before CAP_REACHED.
307
+ #FORGE_MAX_AUDIT_ROUNDS=5
308
+ # Model overrides for forge roles (fall back to RUNTIME_MODEL).
309
+ #FORGE_DRAFTER_MODEL=
310
+ #FORGE_AUDITOR_MODEL=
311
+ # Per-agent timeout within forge (ms).
312
+ #FORGE_TIMEOUT_MS=1800000
313
+ # Min interval between Discord progress message edits (ms).
314
+ #FORGE_PROGRESS_THROTTLE_MS=3000
315
+ # Enabling this immediately approves/runs clean plans (no blocking/medium/minor severity markers);
316
+ # disabling it keeps the manual `!plan approve` + `!plan run` prompts.
317
+ #FORGE_AUTO_IMPLEMENT=1
318
+
319
+ # ----------------------------------------------------------
320
+ # Multi-provider auditor
321
+ # ----------------------------------------------------------
322
+ # Route the forge auditor to a non-Claude runtime.
323
+ # Valid values: "codex" (Codex CLI), "openai" (OpenAI-compatible HTTP API), "openrouter" (OpenRouter).
324
+ #FORGE_AUDITOR_RUNTIME=codex
325
+
326
+ # --- Codex CLI adapter ---
327
+ # Path to the Codex CLI binary (default: codex).
328
+ #CODEX_BIN=codex
329
+ # Optional: isolate Codex state/sessions from ~/.codex (helps avoid stale rollout DB issues).
330
+ #CODEX_HOME=/absolute/path/to/.codex-home-discoclaw
331
+ # Default model for the Codex CLI adapter. Used when FORGE_AUDITOR_MODEL is not set.
332
+ #CODEX_MODEL=gpt-5.3-codex
333
+ # WARNING: disables Codex approval prompts and sandbox protections (full-access mode).
334
+ # Equivalent to passing --dangerously-bypass-approvals-and-sandbox to codex exec.
335
+ #CODEX_DANGEROUSLY_BYPASS_APPROVALS_AND_SANDBOX=0
336
+ # Disable Codex session persistence/resume (workaround for session DB issues).
337
+ #CODEX_DISABLE_SESSIONS=0
338
+
339
+ # --- OpenAI-compatible HTTP adapter ---
340
+ # API key for the OpenAI-compatible adapter. Required when FORGE_AUDITOR_RUNTIME=openai.
341
+ #OPENAI_API_KEY=
342
+ # Base URL (override for proxies, Azure OpenAI, Ollama, etc.).
343
+ #OPENAI_BASE_URL=https://api.openai.com/v1
344
+ # Default model when FORGE_AUDITOR_MODEL is not set.
345
+ #OPENAI_MODEL=gpt-4o
346
+
347
+ # --- OpenRouter adapter ---
348
+ # API key for OpenRouter. Required when PRIMARY_RUNTIME=openrouter or FORGE_*_RUNTIME=openrouter.
349
+ #OPENROUTER_API_KEY=
350
+ # Base URL (default: OpenRouter API endpoint).
351
+ #OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
352
+ # Default model for the OpenRouter adapter.
353
+ #OPENROUTER_MODEL=anthropic/claude-sonnet-4
354
+
355
+ # ----------------------------------------------------------
356
+ # Webhooks — inbound HTTP triggers from external services
357
+ # ----------------------------------------------------------
358
+ # TCP port the webhook server listens on (default: 9400).
359
+ #DISCOCLAW_WEBHOOK_PORT=9400
360
+ # Absolute path to the webhook source config file.
361
+ # JSON object mapping source names to their config:
362
+ # {
363
+ # "github": { "secret": "hmac-secret", "channel": "123456789" },
364
+ # "gms": { "secret": "hmac-secret", "channel": "987654321" }
365
+ # }
366
+ # - secret: HMAC-SHA256 secret used to verify the X-Hub-Signature-256 header.
367
+ # - channel: Discord channel name or ID where the webhook posts (reuses cron pipeline).
368
+ #DISCOCLAW_WEBHOOK_CONFIG=
369
+ # Set to 1 to enable the webhook server.
370
+ #DISCOCLAW_WEBHOOK_ENABLED=0
371
+ # To expose webhooks to external services, see docs/webhook-exposure.md
372
+
373
+ # ----------------------------------------------------------
374
+ # Browser automation (agent-browser)
375
+ # ----------------------------------------------------------
376
+ # Chromium path for agent-browser. Only needed if the bundled browser
377
+ # (from `agent-browser install`) doesn't work.
378
+ #AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium-browser
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Marsh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,220 @@
1
+ <p align="center">
2
+ <img src="discoclaw_splash.png" alt="DiscoClaw" width="700" />
3
+ </p>
4
+
5
+ # DiscoClaw
6
+
7
+ A personal AI orchestrator that turns Discord into a persistent workspace — built on three pillars: **Memory**, **Tasks**, and **Crons**.
8
+
9
+ DiscoClaw is an orchestrator: it coordinates between a user interface (Discord), one or more AI runtimes (Claude Code, OpenAI, Codex), and local system resources — managing conversation state, task routing, scheduling, and tool access. The intelligence is rented; the coordination is owned.
10
+
11
+ It turns a private Discord server into a persistent AI workspace. Your assistant remembers you across sessions, tracks work in forum threads, and runs scheduled tasks autonomously — all through natural conversation.
12
+
13
+ It's designed for a single user on a fresh, private server — your own sandbox. Not a shared bot, not a multi-user platform. Just you and your assistant in a space you control.
14
+
15
+ No gateways, no proxies, no web UI to deploy — Discord *is* the interface. Run DiscoClaw on a Linux or macOS machine (see [Platform support](#platform-support)) and talk to your assistant from anywhere Discord works: desktop, mobile, browser.
16
+
17
+ The codebase is intentionally small — small enough to read, audit, and modify directly. Customization means changing the code, not configuring a plugin system.
18
+
19
+ ## Why Discord?
20
+
21
+ Discord gives you channels, forum threads, DMs, mobile access, and rich formatting for free. DiscoClaw maps its three core features onto Discord primitives so there's nothing extra to learn — channels become context boundaries, forum threads become task cards and job definitions, and conversation history is the raw material for memory.
22
+
23
+ ## Memory — the bot knows you
24
+
25
+ Your assistant carries context across every conversation, channel, and restart.
26
+
27
+ - **Durable facts** — `!memory remember prefers dark mode` persists across sessions and channels
28
+ - **Rolling summaries** — Compresses earlier conversation so context carries forward, even across restarts
29
+ - **Per-channel context** — Each channel gets a markdown file shaping behavior (formal in #work, casual in #random)
30
+ - **Customizable identity** — Personality, name, and values defined in workspace files (`SOUL.md`, `IDENTITY.md`, etc.)
31
+ - **Group chat aware** — Knows when to speak up and when to stay quiet in shared channels
32
+
33
+ **Why Discord fits:** channels = context boundaries, DMs = private deep context, conversation history is the raw material.
34
+
35
+ ## Tasks — the bot tracks your work
36
+
37
+ A lightweight in-process task store that syncs bidirectionally with Discord forum threads.
38
+
39
+ - **Create from either side** — Ask your assistant in chat or use task commands
40
+ - **Bidirectional sync** — Status, priority, and tags stay in sync between the task store and Discord threads
41
+ - **Status emoji and auto-tagging** — Thread names show live status at a glance
42
+ - **Discord actions** — Your assistant manages tasks through conversation: create channels, send messages, search history, run polls, and more
43
+
44
+ **Why Discord fits:** forum threads = task cards, archive = done, thread names show live status.
45
+
46
+ ## Crons — the bot acts on its own
47
+
48
+ Recurring tasks defined as forum threads in plain language — no crontab, no separate scheduler UI.
49
+
50
+ - **Plain-language schedules** — "every weekday at 7am, check the weather and post to #general"
51
+ - **Edit to change, archive to pause, unarchive to resume**
52
+ - **Full workspace access** — File I/O, web search, browser automation, Discord actions
53
+ - **Multi-turn sessions** — A live process persists between runs, so context carries across executions
54
+
55
+ **Why Discord fits:** forum threads = job definitions, archive/unarchive = pause/resume, no separate scheduler UI needed.
56
+
57
+ ## How it works
58
+
59
+ DiscoClaw orchestrates the flow between Discord and AI runtimes (Claude Code by default, with OpenAI, Codex, and OpenRouter adapters available via `PRIMARY_RUNTIME`). It doesn't contain intelligence itself — it decides *when* to call the AI, *what context* to give it, and *what to do* with the output. When you send a message, the orchestrator:
60
+
61
+ 1. Checks the user allowlist (fail-closed — empty list means respond to nobody)
62
+ 2. Assembles context: per-channel rules, conversation history, rolling summary, and durable memory
63
+ 3. Routes to the appropriate runtime adapter, running in your workspace directory
64
+ 4. Streams the response back, chunked to fit Discord's message limits
65
+ 5. Parses and executes any Discord actions the assistant emitted
66
+
67
+ ### OpenRouter
68
+
69
+ Set `PRIMARY_RUNTIME=openrouter` to route requests through [OpenRouter](https://openrouter.ai), which provides access to models from Anthropic, OpenAI, Google, and others via a single API key — useful if you want to switch models without managing multiple provider accounts.
70
+
71
+ Required: `OPENROUTER_API_KEY`. Optional overrides: `OPENROUTER_BASE_URL` (default: `https://openrouter.ai/api/v1`) and `OPENROUTER_MODEL` (default: `anthropic/claude-sonnet-4`). See `.env.example` for the full reference.
72
+
73
+ ## Customization
74
+
75
+ ### Shareable integration recipes
76
+
77
+ DiscoClaw supports a shareable markdown recipe format for passing integrations between users:
78
+
79
+ - Spec: `docs/discoclaw-recipe-spec.md`
80
+ - Template: `templates/recipes/integration.discoclaw-recipe.md`
81
+ - Example files: `recipes/examples/*.discoclaw-recipe.md`
82
+ - Skills:
83
+ - `skills/discoclaw-recipe-generator/SKILL.md`
84
+ - `skills/discoclaw-recipe-consumer/SKILL.md`
85
+ - Install/refresh invocable skill symlinks:
86
+ - `pnpm claude:install-skills`
87
+
88
+ Author one recipe file for an integration, share it, then let another user's DiscoClaw agent consume it and produce a local implementation checklist before coding.
89
+
90
+ ## Prerequisites
91
+
92
+ **End users:**
93
+ - **Node.js >=20** — check with `node --version`
94
+ - One primary runtime:
95
+ - **Claude CLI** on your `PATH` — check with `claude --version` (see [Claude CLI docs](https://docs.anthropic.com/en/docs/claude-code) to install), or
96
+ - **Codex CLI** on your `PATH` — check with `codex --version`, or
97
+ - **OpenAI-compatible API key** via `OPENAI_API_KEY`, or
98
+ - **OpenRouter API key** via `OPENROUTER_API_KEY` (access to many providers)
99
+ - Runtime-specific access for your chosen provider (Anthropic plan/API credits for Claude, OpenAI access for Codex/OpenAI models)
100
+
101
+ **Contributors (from source):**
102
+ - Everything above, plus **pnpm** — enable via Corepack (`corepack enable`) or install separately
103
+
104
+ ## Quick start
105
+
106
+ ### Discord setup (private server + bot)
107
+
108
+ 1. Create a **private Discord server** dedicated to DiscoClaw (not a shared/public server).
109
+ 2. In the [Discord Developer Portal](https://discord.com/developers/applications), create an application, then go to **Bot** -> **Add Bot**.
110
+ 3. Under **Bot** -> **Privileged Gateway Intents**, enable **Message Content Intent**.
111
+ 4. Copy the bot token and set it in `.env` as `DISCORD_TOKEN=...`.
112
+ 5. Invite the bot to your server:
113
+ - Go to **OAuth2** -> **URL Generator**
114
+ - Under **Scopes**, tick `bot`
115
+ - A **Bot Permissions** grid appears below. For a private server, tick `Administrator` (top-left, under General Permissions) — it's one checkbox and covers everything. For tighter permissions, see the [permission profiles](docs/discord-bot-setup.md#permission-profiles-choose-intentionally) in the full guide.
116
+ - Copy the generated URL at the bottom, open it, pick your server, and authorize
117
+ 6. In Discord, enable **Developer Mode** (User Settings -> Advanced), then copy IDs and set:
118
+ - `DISCORD_ALLOW_USER_IDS=<your user id>` (required; fail-closed if empty)
119
+ - `DISCORD_GUILD_ID=<server id>` (recommended; required for auto-creating forum channels)
120
+
121
+ Full step-by-step guide: [docs/discord-bot-setup.md](docs/discord-bot-setup.md)
122
+
123
+ ### Install and run
124
+
125
+ 1. **Install globally:**
126
+ ```bash
127
+ npm install -g discoclaw
128
+ ```
129
+
130
+ 2. **Run the interactive setup wizard** (creates `.env` and scaffolds your workspace):
131
+ ```bash
132
+ discoclaw init
133
+ ```
134
+
135
+ 3. **Register the system service:**
136
+ ```bash
137
+ discoclaw install-daemon
138
+ ```
139
+
140
+ #### From source (contributors)
141
+
142
+ ```bash
143
+ git clone <repo-url> && cd discoclaw
144
+ pnpm install
145
+ pnpm setup # guided interactive setup
146
+ # Or manually: cp .env.example .env and fill in required vars:
147
+ # DISCORD_TOKEN
148
+ # DISCORD_ALLOW_USER_IDS
149
+ # For all ~90 options: cp .env.example.full .env
150
+ pnpm dev
151
+ ```
152
+
153
+ ## Updating
154
+
155
+ **Global install:**
156
+
157
+ ```bash
158
+ npm update -g discoclaw
159
+ discoclaw install-daemon # re-register the service after updating
160
+ ```
161
+
162
+ **From source:**
163
+
164
+ ```bash
165
+ git pull
166
+ pnpm install
167
+ pnpm build
168
+ ```
169
+
170
+ Run `pnpm preflight` — it flags configuration options from `.env.example` that aren't in your `.env` yet.
171
+
172
+ If running as a systemd service, restart it:
173
+
174
+ ```bash
175
+ systemctl --user restart discoclaw.service
176
+ ```
177
+
178
+ ## Platform support
179
+
180
+ - **All platforms** — `pnpm dev` works everywhere Node.js runs (Linux, macOS, Windows)
181
+ - **Linux** — systemd service file provided for production deployment (see `.context/ops.md`)
182
+ - **macOS / Windows** — use pm2, screen, or another process manager for long-running deployment; or just `pnpm dev` in a terminal
183
+
184
+ > Windows is not tested for production use in v0.x. The session scanner has known path-handling issues on Windows, and the Claude CLI primarily targets Linux and macOS.
185
+
186
+ ## Safety
187
+
188
+ DiscoClaw orchestrates powerful local tooling via AI runtimes, often with elevated permissions. Treat it like a local automation system connected to Discord.
189
+
190
+ - Use a **private Discord server** — don't start in a shared or public server
191
+ - Use **least-privilege** Discord permissions
192
+ - Keep `DISCORD_ALLOW_USER_IDS` tight — this is the primary security boundary
193
+ - Empty allowlist = respond to nobody (fail-closed)
194
+ - Optionally restrict channels with `DISCORD_CHANNEL_IDS`
195
+ - External content (Discord messages, web pages, files) is **data**, not instructions
196
+
197
+ ## Workspace layout
198
+
199
+ The orchestrator runs AI runtimes in a separate working directory (`WORKSPACE_CWD`), keeping the repo clean while giving your assistant a persistent workspace.
200
+
201
+ - Set `DISCOCLAW_DATA_DIR` to use `$DISCOCLAW_DATA_DIR/workspace` (good for Dropbox-backed setups)
202
+ - Or leave it unset to use `./workspace` relative to the repo
203
+ - Content (channel context, Discord config) defaults to `$DISCOCLAW_DATA_DIR/content`
204
+
205
+ ## Development
206
+
207
+ ```bash
208
+ pnpm preflight # preflight check (Node, pnpm, Claude CLI, .env)
209
+ pnpm dev # start dev mode
210
+ pnpm build # compile TypeScript
211
+ pnpm test # run tests
212
+ ```
213
+
214
+ ## Built with
215
+
216
+ [Claude Code](https://claude.ai/claude-code), [OpenAI Codex](https://openai.com/index/openai-codex/), [discord.js](https://discord.js.org), and [Croner](https://github.com/hexagon/croner).
217
+
218
+ ## License
219
+
220
+ [MIT](LICENSE). See [DISCLAIMER.md](DISCLAIMER.md) for important usage terms.
@@ -0,0 +1,2 @@
1
+ import { autoTagTask, } from '../tasks/auto-tag.js';
2
+ export const autoTagBead = autoTagTask;