clawmini 0.0.8 → 0.0.9

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 (367) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +14 -0
  3. package/.github/workflows/release.yml +49 -0
  4. package/CHANGELOG.md +36 -0
  5. package/README.md +5 -4
  6. package/dist/adapter-discord/index.d.mts.map +1 -1
  7. package/dist/adapter-discord/index.mjs +465 -282
  8. package/dist/adapter-discord/index.mjs.map +1 -1
  9. package/dist/adapter-google-chat/index.mjs +367 -243
  10. package/dist/adapter-google-chat/index.mjs.map +1 -1
  11. package/dist/cli/index.mjs +684 -24
  12. package/dist/cli/index.mjs.map +1 -1
  13. package/dist/cli/lite.mjs +43 -13
  14. package/dist/cli/lite.mjs.map +1 -1
  15. package/dist/cli/{propose-policy.mjs → manage-policies.mjs} +270 -47
  16. package/dist/cli/manage-policies.mjs.map +1 -0
  17. package/dist/cli/run-host.d.mts +1 -0
  18. package/dist/cli/run-host.mjs +3090 -0
  19. package/dist/cli/run-host.mjs.map +1 -0
  20. package/dist/config-CPFQIGdG.mjs +57 -0
  21. package/dist/config-CPFQIGdG.mjs.map +1 -0
  22. package/dist/config-Dvl-Pov4.mjs +76 -0
  23. package/dist/config-Dvl-Pov4.mjs.map +1 -0
  24. package/dist/daemon/index.d.mts.map +1 -1
  25. package/dist/daemon/index.mjs +970 -332
  26. package/dist/daemon/index.mjs.map +1 -1
  27. package/dist/supervisor-actions-CiW56eLi.mjs +843 -0
  28. package/dist/supervisor-actions-CiW56eLi.mjs.map +1 -0
  29. package/dist/turn-log-buffer-DRgW53gl.mjs +767 -0
  30. package/dist/turn-log-buffer-DRgW53gl.mjs.map +1 -0
  31. package/dist/web/_app/immutable/chunks/{Drm9vgeP.js → 3AZlWB6U.js} +1 -1
  32. package/dist/web/_app/immutable/chunks/BhRSsUCh.js +2 -0
  33. package/dist/web/_app/immutable/chunks/BiLeM2i1.js +1 -0
  34. package/{web/.svelte-kit/output/client/_app/immutable/chunks/CME08kGM.js → dist/web/_app/immutable/chunks/BmBj85Ll.js} +1 -1
  35. package/dist/web/_app/immutable/chunks/BrERcKAH.js +1 -0
  36. package/dist/web/_app/immutable/chunks/Bv9252RM.js +1 -0
  37. package/dist/web/_app/immutable/chunks/CIXNBPKi.js +1 -0
  38. package/dist/web/_app/immutable/chunks/DISKL3GN.js +2 -0
  39. package/dist/web/_app/immutable/chunks/{Zeh-C-mx.js → DcpaLzmX.js} +1 -1
  40. package/dist/web/_app/immutable/chunks/DnQ3vS13.js +1 -0
  41. package/dist/web/_app/immutable/chunks/KsloHTKS.js +1 -0
  42. package/{web/.svelte-kit/output/client/_app/immutable/chunks/Ck-be5J2.js → dist/web/_app/immutable/chunks/RsHsUj-8.js} +2 -2
  43. package/dist/web/_app/immutable/chunks/{vDehDcuJ.js → wpfV79dV.js} +1 -1
  44. package/dist/web/_app/immutable/entry/app.CIw1Qj0n.js +2 -0
  45. package/dist/web/_app/immutable/entry/start.Di0-Jhte.js +1 -0
  46. package/dist/web/_app/immutable/nodes/{0.CUGC2p-K.js → 0.DYyUA1au.js} +1 -1
  47. package/dist/web/_app/immutable/nodes/1.D-3QEMMZ.js +1 -0
  48. package/dist/web/_app/immutable/nodes/{2.BnwnD1Ki.js → 2.4olHnH7U.js} +1 -1
  49. package/{web/.svelte-kit/output/client/_app/immutable/nodes/3.0arZe_Uf.js → dist/web/_app/immutable/nodes/3.4w0bE-m2.js} +3 -3
  50. package/dist/web/_app/immutable/nodes/4.CZvjhVHt.js +60 -0
  51. package/dist/web/_app/immutable/nodes/{5.Bq2JzCEj.js → 5.DLbPVJY2.js} +1 -1
  52. package/dist/web/_app/version.json +1 -1
  53. package/dist/web/index.html +12 -12
  54. package/dist/workspace-oWmVh5mi.mjs +1001 -0
  55. package/dist/workspace-oWmVh5mi.mjs.map +1 -0
  56. package/docs/23_adapter_slash_autocomplete/development_log.md +19 -0
  57. package/docs/23_adapter_slash_autocomplete/notes.md +18 -0
  58. package/docs/23_adapter_slash_autocomplete/prd.md +46 -0
  59. package/docs/23_adapter_slash_autocomplete/questions.md +6 -0
  60. package/docs/23_adapter_slash_autocomplete/tickets.md +21 -0
  61. package/docs/24_subagent_job_policy_fixes/development_log.md +22 -0
  62. package/docs/24_subagent_job_policy_fixes/notes.md +28 -0
  63. package/docs/24_subagent_job_policy_fixes/prd.md +59 -0
  64. package/docs/24_subagent_job_policy_fixes/questions.md +3 -0
  65. package/docs/24_subagent_job_policy_fixes/tickets.md +49 -0
  66. package/docs/25_e2e_test_improvements/development_log.md +30 -0
  67. package/docs/25_e2e_test_improvements/notes.md +29 -0
  68. package/docs/25_e2e_test_improvements/prd.md +43 -0
  69. package/docs/25_e2e_test_improvements/questions.md +12 -0
  70. package/docs/25_e2e_test_improvements/tickets-2.md +22 -0
  71. package/docs/25_e2e_test_improvements/tickets.md +22 -0
  72. package/docs/25_policy_cwd/development_log.md +30 -0
  73. package/docs/25_policy_cwd/notes.md +28 -0
  74. package/docs/25_policy_cwd/prd.md +77 -0
  75. package/docs/25_policy_cwd/questions.md +6 -0
  76. package/docs/25_policy_cwd/tickets.md +77 -0
  77. package/docs/CLI_REFERENCE.md +3 -1
  78. package/docs/PHILOSOPHY.md +35 -0
  79. package/docs/adapter-visibility/SPEC.md +461 -0
  80. package/docs/adapter-visibility/SPEC_v2.md +202 -0
  81. package/docs/auto-update/SPEC.md +344 -0
  82. package/docs/backups/SPEC.md +296 -0
  83. package/docs/backups/clawmini.gitignore +69 -0
  84. package/docs/guides/assets/clawmini-avatar.png +0 -0
  85. package/docs/guides/backups.md +332 -0
  86. package/docs/guides/discord_adapter_setup.md +1 -1
  87. package/docs/guides/google_chat_adapter_setup.md +81 -0
  88. package/docs/unified-startup/SPEC.md +203 -0
  89. package/e2e/_helpers/test-environment.test.ts +49 -0
  90. package/e2e/_helpers/test-environment.ts +548 -0
  91. package/e2e/adapters/_google-chat-fixtures.ts +340 -0
  92. package/{src/cli/e2e → e2e/adapters}/adapter-discord.test.ts +22 -23
  93. package/e2e/adapters/adapter-google-chat-downtime.test.ts +157 -0
  94. package/e2e/adapters/adapter-google-chat-inbound.test.ts +697 -0
  95. package/e2e/adapters/adapter-google-chat-outbound.test.ts +297 -0
  96. package/e2e/adapters/adapter-google-chat-roundtrip.test.ts +56 -0
  97. package/e2e/adapters/adapter-google-chat-threads.test.ts +1078 -0
  98. package/e2e/agents/custom-api-env.test.ts +80 -0
  99. package/e2e/agents/export-lite-func.test.ts +104 -0
  100. package/e2e/agents/fallbacks.test.ts +124 -0
  101. package/e2e/agents/interrupt.test.ts +50 -0
  102. package/e2e/agents/no-reply-necessary.test.ts +57 -0
  103. package/e2e/agents/session-timeout-subagents.test.ts +76 -0
  104. package/e2e/agents/subagent-authorization.test.ts +246 -0
  105. package/e2e/agents/subagent-env.test.ts +49 -0
  106. package/e2e/agents/subagent-lifecycle.test.ts +782 -0
  107. package/e2e/agents/subagents-depth.test.ts +47 -0
  108. package/e2e/cli/agents.test.ts +176 -0
  109. package/e2e/cli/auto-update.test.ts +741 -0
  110. package/e2e/cli/basic.test.ts +44 -0
  111. package/{src/cli/e2e → e2e/cli}/export-lite.test.ts +16 -12
  112. package/e2e/cli/init-gitignore.test.ts +86 -0
  113. package/e2e/cli/init.test.ts +76 -0
  114. package/e2e/cli/messages.test.ts +363 -0
  115. package/e2e/cli/serve.test.ts +76 -0
  116. package/{src/cli/e2e → e2e/cli}/skills.test.ts +11 -10
  117. package/{src/cli/e2e → e2e/daemon}/daemon.test.ts +57 -195
  118. package/e2e/jobs/agent-jobs.test.ts +216 -0
  119. package/e2e/jobs/cron.test.ts +64 -0
  120. package/e2e/jobs/restart.test.ts +108 -0
  121. package/e2e/policies/approval-session.test.ts +69 -0
  122. package/e2e/policies/auto-create-policies-file.test.ts +35 -0
  123. package/e2e/policies/builtin-manage-policies.test.ts +184 -0
  124. package/e2e/policies/builtin-run-host.test.ts +180 -0
  125. package/e2e/policies/environment-policies.test.ts +177 -0
  126. package/e2e/policies/manage-policies.test.ts +566 -0
  127. package/e2e/policies/output-size.test.ts +98 -0
  128. package/e2e/policies/policies-context-cwd.test.ts +160 -0
  129. package/e2e/policies/relative-script-path.test.ts +60 -0
  130. package/e2e/policies/requests-show.test.ts +135 -0
  131. package/e2e/policies/requests.test.ts +208 -0
  132. package/e2e/policies/slash-policies.test.ts +308 -0
  133. package/e2e/policies/startup-cleanup.test.ts +48 -0
  134. package/e2e/routers/session-timeout.test.ts +106 -0
  135. package/e2e/routers/slash-model.test.ts +152 -0
  136. package/e2e/routers/slash-new.test.ts +50 -0
  137. package/e2e/routers/slash-restart-adapter.test.ts +96 -0
  138. package/e2e/routers/slash-restart.test.ts +114 -0
  139. package/e2e/routers/slash-shutdown.test.ts +55 -0
  140. package/e2e/routers/slash-stop.test.ts +232 -0
  141. package/e2e/routers/slash-upgrade.test.ts +88 -0
  142. package/{src/cli/e2e → e2e/sandbox}/environments.test.ts +14 -13
  143. package/eslint.config.js +6 -0
  144. package/napkin.md +1 -1
  145. package/package.json +8 -3
  146. package/src/adapter-discord/commands.test.ts +42 -0
  147. package/src/adapter-discord/commands.ts +33 -0
  148. package/src/adapter-discord/config.ts +12 -0
  149. package/src/adapter-discord/forwarder.test.ts +499 -21
  150. package/src/adapter-discord/forwarder.ts +343 -124
  151. package/src/adapter-discord/inbound-cache.test.ts +47 -0
  152. package/src/adapter-discord/inbound-cache.ts +37 -0
  153. package/src/adapter-discord/index.test.ts +67 -2
  154. package/src/adapter-discord/index.ts +84 -216
  155. package/src/adapter-discord/interactions.test.ts +54 -3
  156. package/src/adapter-discord/interactions.ts +97 -53
  157. package/src/adapter-discord/processMessage.ts +239 -0
  158. package/src/adapter-discord/state.ts +1 -0
  159. package/src/adapter-google-chat/auth.test.ts +9 -5
  160. package/src/adapter-google-chat/auth.ts +29 -23
  161. package/src/adapter-google-chat/cards.ts +7 -2
  162. package/src/adapter-google-chat/client.test.ts +37 -2
  163. package/src/adapter-google-chat/client.ts +138 -38
  164. package/src/adapter-google-chat/config.ts +19 -0
  165. package/src/adapter-google-chat/forwarder.test.ts +81 -56
  166. package/src/adapter-google-chat/forwarder.ts +394 -185
  167. package/src/adapter-google-chat/inbound-cache.test.ts +61 -0
  168. package/src/adapter-google-chat/inbound-cache.ts +36 -0
  169. package/src/adapter-google-chat/state.test.ts +1 -0
  170. package/src/adapter-google-chat/state.ts +9 -1
  171. package/src/adapter-google-chat/subscriptions.ts +8 -6
  172. package/src/cli/builtin-policies.ts +44 -0
  173. package/src/cli/commands/agents.ts +59 -5
  174. package/src/cli/commands/down.ts +54 -2
  175. package/src/cli/commands/environments.ts +8 -2
  176. package/src/cli/commands/init.ts +31 -0
  177. package/src/cli/commands/logs.ts +116 -0
  178. package/src/cli/commands/policies.ts +6 -4
  179. package/src/cli/commands/serve.test.ts +67 -0
  180. package/src/cli/commands/serve.ts +284 -0
  181. package/src/cli/commands/up.ts +122 -2
  182. package/src/cli/commands/web-api/agents.ts +3 -2
  183. package/src/cli/index.ts +4 -0
  184. package/src/cli/install-detection.test.ts +72 -0
  185. package/src/cli/install-detection.ts +48 -0
  186. package/src/cli/lite.ts +54 -22
  187. package/src/cli/manage-policies-utils.ts +104 -0
  188. package/src/cli/manage-policies.ts +291 -0
  189. package/src/cli/run-host.ts +45 -0
  190. package/src/cli/supervisor-actions.ts +267 -0
  191. package/src/cli/supervisor-control.test.ts +129 -0
  192. package/src/cli/supervisor-control.ts +155 -0
  193. package/src/cli/supervisor-pid.ts +68 -0
  194. package/src/cli/supervisor.ts +277 -0
  195. package/src/daemon/agent/agent-context.ts +11 -11
  196. package/src/daemon/agent/agent-session.ts +8 -1
  197. package/src/daemon/agent/chat-logger.test.ts +78 -9
  198. package/src/daemon/agent/chat-logger.ts +25 -5
  199. package/src/daemon/agent/turn-registry.test.ts +89 -0
  200. package/src/daemon/agent/turn-registry.ts +94 -0
  201. package/src/daemon/agent/types.ts +2 -0
  202. package/src/daemon/api/agent-policy-endpoints.ts +263 -0
  203. package/src/daemon/api/agent-router.ts +47 -126
  204. package/src/daemon/api/index.test.ts +1 -0
  205. package/src/daemon/api/policy-request.test.ts +7 -5
  206. package/src/daemon/api/router-utils.ts +6 -5
  207. package/src/daemon/api/subagent-router.ts +110 -74
  208. package/src/daemon/api/subagent-utils.test.ts +60 -0
  209. package/src/daemon/api/subagent-utils.ts +113 -87
  210. package/src/daemon/api/user-router.ts +34 -8
  211. package/src/daemon/auth.ts +1 -0
  212. package/src/daemon/cron.test.ts +62 -4
  213. package/src/daemon/cron.ts +42 -16
  214. package/src/daemon/events.ts +65 -0
  215. package/src/daemon/index.ts +24 -1
  216. package/src/daemon/message-interruption.test.ts +1 -0
  217. package/src/daemon/message-jobs.test.ts +1 -0
  218. package/src/daemon/message.ts +78 -14
  219. package/src/daemon/observation.test.ts +26 -18
  220. package/src/daemon/pending-replies.test.ts +112 -0
  221. package/src/daemon/pending-replies.ts +162 -0
  222. package/src/daemon/policy-request-service.ts +3 -1
  223. package/src/daemon/policy-utils.test.ts +66 -1
  224. package/src/daemon/policy-utils.ts +126 -1
  225. package/src/daemon/request-store.ts +31 -0
  226. package/src/daemon/routers/session-timeout.ts +4 -0
  227. package/src/daemon/routers/slash-model.test.ts +344 -0
  228. package/src/daemon/routers/slash-model.ts +207 -0
  229. package/src/daemon/routers/slash-policies.test.ts +38 -32
  230. package/src/daemon/routers/slash-policies.ts +84 -33
  231. package/src/daemon/routers/slash-restart.test.ts +69 -0
  232. package/src/daemon/routers/slash-restart.ts +36 -0
  233. package/src/daemon/routers/slash-shutdown.test.ts +50 -0
  234. package/src/daemon/routers/slash-shutdown.ts +28 -0
  235. package/src/daemon/routers/slash-upgrade.test.ts +116 -0
  236. package/src/daemon/routers/slash-upgrade.ts +76 -0
  237. package/src/daemon/routers/types.ts +7 -0
  238. package/src/daemon/routers.ts +16 -0
  239. package/src/shared/adapters/blockquote.test.ts +28 -0
  240. package/src/shared/adapters/blockquote.ts +20 -0
  241. package/src/shared/adapters/filtering.test.ts +224 -10
  242. package/src/shared/adapters/filtering.ts +95 -7
  243. package/src/shared/adapters/inbound-cache.test.ts +48 -0
  244. package/src/shared/adapters/inbound-cache.ts +54 -0
  245. package/src/shared/adapters/turn-log-buffer.ts +266 -0
  246. package/src/shared/adapters/turn-log.test.ts +389 -0
  247. package/src/shared/adapters/turn-log.ts +357 -0
  248. package/src/shared/agent-utils.ts +12 -5
  249. package/src/shared/chats.test.ts +4 -0
  250. package/src/shared/chats.ts +9 -0
  251. package/src/shared/config.ts +16 -1
  252. package/src/shared/lite.ts +76 -2
  253. package/src/shared/policies.ts +26 -0
  254. package/src/shared/template-manifest.ts +267 -0
  255. package/src/shared/utils/shell.ts +61 -0
  256. package/src/shared/version.ts +34 -0
  257. package/src/shared/workspace.test.ts +217 -0
  258. package/src/shared/workspace.ts +626 -48
  259. package/templates/environments/cladding/allowlist-domain.mjs +125 -0
  260. package/templates/environments/cladding/env.json +21 -1
  261. package/templates/environments/cladding/run-with-network.mjs +54 -0
  262. package/templates/environments/macos-proxy/allowlist-domain.mjs +95 -0
  263. package/templates/environments/macos-proxy/env.json +8 -1
  264. package/templates/environments/macos-proxy/proxy.mjs +0 -1
  265. package/templates/gemini/template.json +5 -0
  266. package/templates/gemini-claw/template.json +13 -0
  267. package/templates/skills/clawmini-requests/SKILL.md +69 -10
  268. package/templates/skills/run-host/SKILL.md +51 -0
  269. package/templates/skills/skill-creator/SKILL.md +4 -3
  270. package/templates/skills/skill-creator/scripts/validate.sh +52 -0
  271. package/tsdown.config.ts +10 -1
  272. package/vitest.config.ts +2 -2
  273. package/web/.svelte-kit/ambient.d.ts +292 -118
  274. package/web/.svelte-kit/generated/server/internal.js +1 -1
  275. package/web/.svelte-kit/output/client/.vite/manifest.json +126 -136
  276. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Drm9vgeP.js → 3AZlWB6U.js} +1 -1
  277. package/web/.svelte-kit/output/client/_app/immutable/chunks/BhRSsUCh.js +2 -0
  278. package/web/.svelte-kit/output/client/_app/immutable/chunks/BiLeM2i1.js +1 -0
  279. package/{dist/web/_app/immutable/chunks/CME08kGM.js → web/.svelte-kit/output/client/_app/immutable/chunks/BmBj85Ll.js} +1 -1
  280. package/web/.svelte-kit/output/client/_app/immutable/chunks/BrERcKAH.js +1 -0
  281. package/web/.svelte-kit/output/client/_app/immutable/chunks/Bv9252RM.js +1 -0
  282. package/web/.svelte-kit/output/client/_app/immutable/chunks/CIXNBPKi.js +1 -0
  283. package/web/.svelte-kit/output/client/_app/immutable/chunks/DISKL3GN.js +2 -0
  284. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Zeh-C-mx.js → DcpaLzmX.js} +1 -1
  285. package/web/.svelte-kit/output/client/_app/immutable/chunks/DnQ3vS13.js +1 -0
  286. package/web/.svelte-kit/output/client/_app/immutable/chunks/KsloHTKS.js +1 -0
  287. package/{dist/web/_app/immutable/chunks/Ck-be5J2.js → web/.svelte-kit/output/client/_app/immutable/chunks/RsHsUj-8.js} +2 -2
  288. package/web/.svelte-kit/output/client/_app/immutable/chunks/{vDehDcuJ.js → wpfV79dV.js} +1 -1
  289. package/web/.svelte-kit/output/client/_app/immutable/entry/app.CIw1Qj0n.js +2 -0
  290. package/web/.svelte-kit/output/client/_app/immutable/entry/start.Di0-Jhte.js +1 -0
  291. package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.CUGC2p-K.js → 0.DYyUA1au.js} +1 -1
  292. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.D-3QEMMZ.js +1 -0
  293. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.BnwnD1Ki.js → 2.4olHnH7U.js} +1 -1
  294. package/{dist/web/_app/immutable/nodes/3.0arZe_Uf.js → web/.svelte-kit/output/client/_app/immutable/nodes/3.4w0bE-m2.js} +3 -3
  295. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.CZvjhVHt.js +60 -0
  296. package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.Bq2JzCEj.js → 5.DLbPVJY2.js} +1 -1
  297. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  298. package/web/.svelte-kit/output/server/.vite/manifest.json +12 -10
  299. package/web/.svelte-kit/output/server/chunks/Icon.js +1 -1
  300. package/web/.svelte-kit/output/server/chunks/client.js +1 -1
  301. package/web/.svelte-kit/output/server/chunks/exports.js +1 -1
  302. package/web/.svelte-kit/output/server/chunks/index-server.js +2 -1
  303. package/web/.svelte-kit/output/server/chunks/internal.js +1 -1
  304. package/web/.svelte-kit/output/server/chunks/render-context.js +77 -0
  305. package/web/.svelte-kit/output/server/chunks/root.js +739 -788
  306. package/web/.svelte-kit/output/server/chunks/shared.js +234 -21
  307. package/web/.svelte-kit/output/server/index.js +126 -90
  308. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  309. package/web/.svelte-kit/output/server/manifest.js +1 -1
  310. package/web/.svelte-kit/output/server/nodes/0.js +1 -1
  311. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  312. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  313. package/web/.svelte-kit/output/server/nodes/3.js +1 -1
  314. package/web/.svelte-kit/output/server/nodes/4.js +1 -1
  315. package/web/.svelte-kit/output/server/nodes/5.js +1 -1
  316. package/web/.svelte-kit/output/server/remote-entry.js +245 -81
  317. package/web/.svelte-kit/tsconfig.json +4 -1
  318. package/dist/cli/propose-policy.mjs.map +0 -1
  319. package/dist/lite-CBxOT1y5.mjs +0 -241
  320. package/dist/lite-CBxOT1y5.mjs.map +0 -1
  321. package/dist/routing-D8rTxtaV.mjs +0 -245
  322. package/dist/routing-D8rTxtaV.mjs.map +0 -1
  323. package/dist/web/_app/immutable/chunks/B6YN0Nuq.js +0 -1
  324. package/dist/web/_app/immutable/chunks/BmRlVmv6.js +0 -1
  325. package/dist/web/_app/immutable/chunks/CK9JZLaG.js +0 -2
  326. package/dist/web/_app/immutable/chunks/Ck3rYNON.js +0 -1
  327. package/dist/web/_app/immutable/chunks/D5iV40bG.js +0 -1
  328. package/dist/web/_app/immutable/chunks/DMtIqaiV.js +0 -2
  329. package/dist/web/_app/immutable/chunks/DhD271EB.js +0 -1
  330. package/dist/web/_app/immutable/chunks/DpuLqk8d.js +0 -1
  331. package/dist/web/_app/immutable/chunks/DsIToJCP.js +0 -1
  332. package/dist/web/_app/immutable/entry/app.BCSV3nrG.js +0 -2
  333. package/dist/web/_app/immutable/entry/start.D4eLEZUM.js +0 -1
  334. package/dist/web/_app/immutable/nodes/1.CGC_42IQ.js +0 -1
  335. package/dist/web/_app/immutable/nodes/4.ClM1bXLE.js +0 -60
  336. package/dist/workspace-BJmJBfKi.mjs +0 -456
  337. package/dist/workspace-BJmJBfKi.mjs.map +0 -1
  338. package/src/cli/e2e/agents.test.ts +0 -140
  339. package/src/cli/e2e/basic.test.ts +0 -43
  340. package/src/cli/e2e/cron.test.ts +0 -132
  341. package/src/cli/e2e/export-lite-func.test.ts +0 -206
  342. package/src/cli/e2e/fallbacks.test.ts +0 -175
  343. package/src/cli/e2e/init.test.ts +0 -77
  344. package/src/cli/e2e/messages.test.ts +0 -332
  345. package/src/cli/e2e/propose-policy.test.ts +0 -203
  346. package/src/cli/e2e/requests.test.ts +0 -180
  347. package/src/cli/e2e/session-timeout.test.ts +0 -192
  348. package/src/cli/e2e/slash-new.test.ts +0 -93
  349. package/src/cli/e2e/subagents.test.ts +0 -106
  350. package/src/cli/e2e/utils.ts +0 -66
  351. package/src/cli/propose-policy.ts +0 -91
  352. package/web/.svelte-kit/output/client/_app/immutable/chunks/B6YN0Nuq.js +0 -1
  353. package/web/.svelte-kit/output/client/_app/immutable/chunks/BmRlVmv6.js +0 -1
  354. package/web/.svelte-kit/output/client/_app/immutable/chunks/CK9JZLaG.js +0 -2
  355. package/web/.svelte-kit/output/client/_app/immutable/chunks/Ck3rYNON.js +0 -1
  356. package/web/.svelte-kit/output/client/_app/immutable/chunks/D5iV40bG.js +0 -1
  357. package/web/.svelte-kit/output/client/_app/immutable/chunks/DMtIqaiV.js +0 -2
  358. package/web/.svelte-kit/output/client/_app/immutable/chunks/DhD271EB.js +0 -1
  359. package/web/.svelte-kit/output/client/_app/immutable/chunks/DpuLqk8d.js +0 -1
  360. package/web/.svelte-kit/output/client/_app/immutable/chunks/DsIToJCP.js +0 -1
  361. package/web/.svelte-kit/output/client/_app/immutable/entry/app.BCSV3nrG.js +0 -2
  362. package/web/.svelte-kit/output/client/_app/immutable/entry/start.D4eLEZUM.js +0 -1
  363. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.CGC_42IQ.js +0 -1
  364. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.ClM1bXLE.js +0 -60
  365. package/web/.svelte-kit/output/server/chunks/false.js +0 -4
  366. /package/dist/cli/{propose-policy.d.mts → manage-policies.d.mts} +0 -0
  367. /package/{src/cli/e2e → e2e/_helpers}/global-setup.ts +0 -0
@@ -0,0 +1,296 @@
1
+ # `.clawmini` Backup — what's safe, what's not, and how to do it
2
+
3
+ ## Goal
4
+
5
+ Decide what under a workspace's `.clawmini/` directory can safely be pushed
6
+ to a private git remote (or any external backup target) for disaster
7
+ recovery, and what must stay on the local machine.
8
+
9
+ "Private repo" is not the same as "secret store". Even a private GitHub
10
+ repo:
11
+
12
+ - Stores everything in plaintext on Anthropic's, GitHub's, and any
13
+ collaborator's disks.
14
+ - Keeps a permanent history — once a token is committed, rotation is the
15
+ only real remediation.
16
+ - Gets cloned to CI, other workstations, and any future tooling you wire
17
+ up. Each clone is a copy of every secret it contains.
18
+ - Is reachable by anyone with read access to the repo (org admins, future
19
+ teammates, leaked SSH keys, stolen laptops).
20
+
21
+ So the bar for "safe to back up" is: would I be comfortable if this file
22
+ were posted in a private channel that 5 people will eventually read? Not
23
+ "is the repo private right now?".
24
+
25
+ ---
26
+
27
+ ## Inventory of `.clawmini/`
28
+
29
+ Sensitivity ratings: **LOW** = config/metadata, **MED** = may contain
30
+ secrets depending on user, **HIGH** = routinely contains secrets or
31
+ private content, **CRIT** = always contains live credentials.
32
+
33
+ ### Stable, user-authored config
34
+
35
+ | Path | Sensitivity | Notes |
36
+ | --- | --- | --- |
37
+ | `settings.json` | LOW | Default chat id, environment-to-path map. |
38
+ | `policies.json` | LOW | Policy command/args definitions. |
39
+ | `policy-scripts/*.js` | LOW–MED | User code; treat like any source file. |
40
+ | `commands/*.{md,txt}` | LOW–MED | Slash-command text. May contain prompts/snippets. |
41
+ | `templates/*` | LOW–MED | Mirrors built-in templates; rarely sensitive. |
42
+ | `chats/<id>/settings.json` | LOW | Per-chat metadata. |
43
+ | `agents/<id>/installed-files.json` | LOW | SHA manifest only. |
44
+
45
+ ### Per-agent / per-environment config (mostly safe, leaks via `env`)
46
+
47
+ | Path | Sensitivity | Notes |
48
+ | --- | --- | --- |
49
+ | `agents/<id>/settings.json` | MED | `env` and `subagentEnv` may hold API keys. |
50
+ | `agents/<id>/sessions/<sid>/settings.json` | MED | Same shape, per session. |
51
+ | `environments/<name>/env.json` | MED | `env` block may hold secrets; `init` script may reference them. |
52
+ | `environments/<name>/*` | MED | Whatever the user dropped in. |
53
+
54
+ ### Conversation + execution history (private content, sometimes secrets)
55
+
56
+ | Path | Sensitivity | Notes |
57
+ | --- | --- | --- |
58
+ | `chats/<id>/chat.jsonl` | HIGH | Full transcript: user prompts, model output, tool I/O, command stdout/stderr, file contents pasted in. Routinely contains code, internal docs, occasionally credentials echoed by a misbehaving script. Append-only, can be very large. |
59
+
60
+ ### Adapter config + state (credential central)
61
+
62
+ | Path | Sensitivity | Notes |
63
+ | --- | --- | --- |
64
+ | `adapters/discord/config.json` | **CRIT** | `botToken` is a live Discord bot token (required field). |
65
+ | `adapters/discord/state.json` | LOW | Sync cursors + channel→chat map. No secrets. |
66
+ | `adapters/google-chat/config.json` | **CRIT** | `oauthClientId` / `oauthClientSecret` for Drive. |
67
+ | `adapters/google-chat/state.json` | **CRIT** | `oauthTokens` — live refresh + access tokens. |
68
+
69
+ ### Runtime / ephemeral / IPC
70
+
71
+ | Path | Sensitivity | Notes |
72
+ | --- | --- | --- |
73
+ | `daemon.sock` (a.k.a. `server.sock` in older builds) | n/a | Unix socket — not a real file, can't be copied. Exclude. |
74
+ | `daemon.log` | MED | Stderr from the daemon. Paths, errors, sometimes argv. |
75
+ | `logs/*.log` (`web.log`, `adapter-*.log`) | MED | Same shape, per service. |
76
+ | `supervisor.pid` | LOW | `<pid>:<startTime>`. Worthless on another machine. |
77
+ | `tmp/requests/<rid>.json` | HIGH | Pending policy requests, including `executionResult.{stdout,stderr}`. |
78
+ | `tmp/snapshots/*` | HIGH | Up-to-5MB copies of files a policy is about to touch. |
79
+ | `tmp/discord/*`, `tmp/google-chat/*` | HIGH | Downloaded chat attachments. |
80
+ | `tmp/<agentId>/stdout-<rid>.txt`, `stderr-<rid>.txt` | HIGH | Truncated command output (>500 chars). |
81
+ | `*.<pid>.<hex>.tmp` | n/a | Atomic-write scratch files. Exclude. |
82
+
83
+ ### "There may be more"
84
+
85
+ The user explicitly flagged this. Things that are likely or known to
86
+ appear over time and aren't enumerated above:
87
+
88
+ - New adapter directories as new adapters land (each tends to follow the
89
+ `config.json` + `state.json` pattern — assume CRIT until proven LOW).
90
+ - Hooks / skills installed under `agents/<id>/` by templates.
91
+ - Future cache directories.
92
+
93
+ The backup policy below is therefore **allow-list**, not deny-list — new
94
+ unknown files default to *not backed up* until a human looks at them.
95
+
96
+ ---
97
+
98
+ ## Options considered
99
+
100
+ ### A. Back up `.clawmini/` wholesale to a private git repo
101
+
102
+ Easiest. One `git init` inside `.clawmini`, push to a private remote,
103
+ done.
104
+
105
+ - **Pro:** zero ongoing thought; everything recovers.
106
+ - **Con:** ships every Discord bot token, every OAuth refresh token, and
107
+ every chat transcript to the remote in plaintext, forever. Any future
108
+ collaborator, CI runner, or leaked deploy key gets all of it. Token
109
+ rotation requires git-history rewriting.
110
+ - **Verdict:** rejected. The credential exposure is not acceptable even
111
+ for a single-user "private" repo.
112
+
113
+ ### B. Wholesale backup with `git-crypt` / `git-secret` / `age` for sensitive files
114
+
115
+ Same as A, but adapter configs, state, and chat history are encrypted at
116
+ rest in the repo with a key kept locally.
117
+
118
+ - **Pro:** one repo covers everything; secrets are encrypted; you can
119
+ share the repo without sharing the key.
120
+ - **Con:** adds a key-management problem (you now must back up the key
121
+ separately, or losing the laptop also loses the backup). `git-crypt`
122
+ in particular smudge/cleans on every checkout — easy to misconfigure
123
+ and accidentally commit plaintext. Encrypting an append-only JSONL
124
+ blows up diffs.
125
+ - **Verdict:** viable, but heavier than the user's needs and trades one
126
+ problem (secret leakage) for another (key custody). Worth it only if
127
+ full chat history backup is a hard requirement.
128
+
129
+ ### C. Allow-list backup of low-risk config only
130
+
131
+ A `.gitignore` inside `.clawmini/` that excludes by default and includes
132
+ a known-safe set: `settings.json`, `policies.json`, `policy-scripts/`,
133
+ `commands/`, `templates/`, `chats/*/settings.json`,
134
+ `agents/*/settings.json`, `agents/*/installed-files.json`,
135
+ `environments/*/env.json`, `adapters/*/state.json` *except* google-chat.
136
+
137
+ Per-agent/env settings sometimes contain `env` API keys — still risky.
138
+ This option drops them or asks the user to inline-strip them.
139
+
140
+ - **Pro:** simple, no encryption, no key. Restoring on a new machine
141
+ gives back the *shape* of the workspace (chats, agents, environments,
142
+ policies) immediately.
143
+ - **Con:** chat transcripts are not backed up. Adapter credentials are
144
+ not backed up — you have to re-do `clawmini init` for each adapter on
145
+ restore. `agents/*/settings.json` may still leak if the user put keys
146
+ in `env`.
147
+ - **Verdict:** strong default. Matches "back up the things that are a
148
+ pain to recreate, accept that secrets get rotated."
149
+
150
+ ### D. Allow-list config (option C) **plus** encrypted bundle for chats and adapters
151
+
152
+ Option C handles the durable config in cleartext. Sensitive content goes
153
+ into an encrypted tarball committed alongside.
154
+
155
+ - **Pro:** chats and adapter creds *are* recoverable; the encrypted
156
+ blob keeps them out of plain git history.
157
+ - **Con:** key management again; the tar grows; restore is a two-step.
158
+ - **Verdict:** the right answer if the user wants real DR, not just
159
+ config preservation.
160
+
161
+ ### E. Don't use git at all — use a backup tool (restic, borg, time machine)
162
+
163
+ `restic` to a private S3 bucket / B2 / SSH host with a passphrase, or
164
+ just include `.clawmini` in Time Machine.
165
+
166
+ - **Pro:** purpose-built for this; encryption, dedup, point-in-time
167
+ snapshots, prune. Handles binary growth (chat.jsonl) far better than
168
+ git. No accidental plaintext credentials in a permanent history.
169
+ - **Con:** not a git repo, so no easy diffing or merging across
170
+ machines. You don't get the "view my settings on github.com" niceness.
171
+ - **Verdict:** technically the cleanest answer for the "avoid data loss"
172
+ framing the user mentioned at the end. Worth recommending alongside.
173
+
174
+ ---
175
+
176
+ ## Recommendation
177
+
178
+ Two-track approach. Pick based on what the user actually wants out of
179
+ the backup.
180
+
181
+ ### Track 1 — config-only git backup (recommended default)
182
+
183
+ Use **Option C** for the version-controlled, shareable, "I want to see
184
+ my workspace settings on a new laptop" backup.
185
+
186
+ Concretely: put a `.gitignore` at the root of `.clawmini/` that opts
187
+ out of everything and re-opts-in only the safe set. Suggested contents:
188
+
189
+ ```gitignore
190
+ # default: ignore everything
191
+ *
192
+
193
+ # re-include known-safe config
194
+ !.gitignore
195
+ !settings.json
196
+ !policies.json
197
+ !policy-scripts/
198
+ !policy-scripts/**
199
+ !commands/
200
+ !commands/**
201
+ !templates/
202
+ !templates/**
203
+
204
+ # chat *metadata* only — not transcripts
205
+ !chats/
206
+ chats/*
207
+ !chats/*/
208
+ !chats/*/settings.json
209
+
210
+ # agents: settings + manifest, no sessions, no tmp
211
+ !agents/
212
+ agents/*
213
+ !agents/*/
214
+ !agents/*/settings.json
215
+ !agents/*/installed-files.json
216
+
217
+ # environments: env.json only
218
+ !environments/
219
+ environments/*
220
+ !environments/*/
221
+ !environments/*/env.json
222
+
223
+ # adapters: state only, and only for adapters known not to hold creds
224
+ # (discord state is safe; google-chat state holds OAuth tokens — exclude)
225
+ !adapters/
226
+ adapters/*
227
+ !adapters/discord/
228
+ adapters/discord/*
229
+ !adapters/discord/state.json
230
+
231
+ # everything else stays ignored: chat.jsonl, tmp/, logs/, daemon.log,
232
+ # daemon.sock, supervisor.pid, *.tmp, adapters/*/config.json,
233
+ # adapters/google-chat/state.json, agents/*/sessions/, agents/*/tmp/
234
+ ```
235
+
236
+ Caveats the user should accept up front:
237
+
238
+ 1. **Re-check `agents/*/settings.json` and `environments/*/env.json`
239
+ before the first push** — if the user has put API keys into `env`,
240
+ they'll go to the remote. Either move them out (e.g. into shell env
241
+ or a separate uncommitted file) or downgrade this track to manual
242
+ review.
243
+ 2. **Adapter credentials are not backed up.** On a new machine, re-run
244
+ `clawmini init` for each adapter. This is a feature, not a bug:
245
+ token rotation is the standard fix for "laptop lost".
246
+ 3. **Chat history is not backed up.** If that's a problem, add Track 2.
247
+
248
+ ### Track 2 — full disaster-recovery backup (optional, for chats + creds)
249
+
250
+ Use **Option E** (`restic` or similar) for the "I don't want to lose my
251
+ chat history if my disk dies" backup. Point it at the entire
252
+ `.clawmini/` directory excluding only `daemon.sock` and `*.tmp`
253
+ scratch files. The tool handles encryption, incremental snapshots, and
254
+ the inevitable size growth of `chat.jsonl`.
255
+
256
+ Rough sketch:
257
+
258
+ ```sh
259
+ restic -r <repo> backup \
260
+ ~/path/to/workspace/.clawmini \
261
+ --exclude '*.sock' --exclude '*.tmp' \
262
+ --exclude '.clawmini/tmp/snapshots/*' # optional: skip large file snapshots
263
+ ```
264
+
265
+ This is the right tool for opaque, mutable, occasionally-sensitive
266
+ runtime state. Don't try to make git do it.
267
+
268
+ ### What about Option D (encrypted bundle in the same git repo)?
269
+
270
+ Only worth the complexity if the user specifically wants *one* repo
271
+ that contains both the config and the sensitive bits. Otherwise Track 1
272
+ + Track 2 separates concerns cleanly: git for the human-readable
273
+ config, restic for the runtime data.
274
+
275
+ ---
276
+
277
+ ## Summary table — what goes where
278
+
279
+ | Path | Track 1 (git) | Track 2 (restic) |
280
+ | --- | --- | --- |
281
+ | `settings.json`, `policies.json` | ✅ | ✅ |
282
+ | `policy-scripts/`, `commands/`, `templates/` | ✅ | ✅ |
283
+ | `chats/*/settings.json` | ✅ | ✅ |
284
+ | `chats/*/chat.jsonl` | ❌ | ✅ |
285
+ | `agents/*/settings.json` (review for `env` secrets!) | ⚠️ | ✅ |
286
+ | `agents/*/installed-files.json` | ✅ | ✅ |
287
+ | `agents/*/sessions/*`, `agents/*/tmp/*` | ❌ | ✅ |
288
+ | `environments/*/env.json` (review for `env` secrets!) | ⚠️ | ✅ |
289
+ | `adapters/discord/config.json` | ❌ | ✅ |
290
+ | `adapters/discord/state.json` | ✅ | ✅ |
291
+ | `adapters/google-chat/config.json` | ❌ | ✅ |
292
+ | `adapters/google-chat/state.json` | ❌ | ✅ |
293
+ | `daemon.log`, `logs/*.log` | ❌ | optional |
294
+ | `tmp/**`, `*.tmp`, `*.sock`, `supervisor.pid` | ❌ | ❌ |
295
+
296
+ ⚠️ = include only after auditing the file for inline secrets.
@@ -0,0 +1,69 @@
1
+ # Allow-list `.gitignore` for a Clawmini workspace's `.clawmini/` directory.
2
+ #
3
+ # Installed automatically by `clawmini init`, and also available as a
4
+ # template at <clawmini>/docs/backups/clawmini.gitignore for retrofitting
5
+ # an existing workspace.
6
+ #
7
+ # Everything is ignored by default; the entries below opt specific paths
8
+ # back in. New unknown files therefore stay out of the backup until a
9
+ # human reviews them. See the Clawmini `docs/guides/backups.md` for the
10
+ # rationale and `docs/backups/SPEC.md` for the full tradeoff analysis.
11
+
12
+ # default: ignore everything
13
+ *
14
+
15
+ # re-include known-safe config
16
+ !.gitignore
17
+ !settings.json
18
+ !policies.json
19
+ !policy-scripts/
20
+ !policy-scripts/**
21
+ !commands/
22
+ !commands/**
23
+ !templates/
24
+ !templates/**
25
+
26
+ # chat *metadata* only — NOT transcripts (chat.jsonl is excluded)
27
+ !chats/
28
+ chats/*
29
+ !chats/*/
30
+ !chats/*/settings.json
31
+
32
+ # agents: settings + manifest only — no sessions, no tmp
33
+ # WARNING: review settings.json for inline `env` secrets before committing.
34
+ !agents/
35
+ agents/*
36
+ !agents/*/
37
+ !agents/*/settings.json
38
+ !agents/*/installed-files.json
39
+
40
+ # environments: env.json only
41
+ # WARNING: review env.json for inline `env` secrets before committing.
42
+ !environments/
43
+ environments/*
44
+ !environments/*/
45
+ !environments/*/env.json
46
+
47
+ # adapters: state only, and only for adapters known not to hold creds.
48
+ # - discord/state.json is sync metadata (safe).
49
+ # - discord/config.json holds the bot token (excluded).
50
+ # - google-chat/config.json holds the OAuth client secret (excluded).
51
+ # - google-chat/state.json holds live OAuth tokens (excluded).
52
+ !adapters/
53
+ adapters/*
54
+ !adapters/discord/
55
+ adapters/discord/*
56
+ !adapters/discord/state.json
57
+
58
+ # Everything below stays ignored by default. Listed here for clarity:
59
+ # chats/*/chat.jsonl - full transcripts (private content)
60
+ # adapters/*/config.json - credentials
61
+ # adapters/google-chat/state.json - OAuth tokens
62
+ # agents/*/sessions/ - per-session state (may contain env secrets)
63
+ # agents/*/tmp/ - command stdout/stderr captures
64
+ # tmp/ - policy requests, file snapshots, attachments
65
+ # logs/ - service logs
66
+ # daemon.log - daemon stderr
67
+ # daemon.sock, server.sock - Unix sockets (not real files)
68
+ # supervisor.pid - process metadata
69
+ # *.tmp - atomic-write scratch files
@@ -0,0 +1,332 @@
1
+ # Backing up your Clawmini workspace
2
+
3
+ Clawmini stores everything that matters about a workspace under
4
+ `.clawmini/`: chats, agents, environments, policies, and adapter
5
+ credentials. Losing that directory loses your chat history and forces
6
+ you to re-authenticate every adapter. This guide explains how to back
7
+ it up without leaking secrets.
8
+
9
+ ## How to think about it
10
+
11
+ `.clawmini/` is a mix of three things, and they want different
12
+ treatment:
13
+
14
+ 1. **Durable config** — `settings.json`, `policies.json`,
15
+ `policy-scripts/`, `commands/`, `templates/`, per-chat metadata,
16
+ per-agent settings, per-environment settings. Hand-written, slowly
17
+ evolving, useful to review on github.com.
18
+ 2. **Runtime state and history** — `chats/<id>/chat.jsonl`, logs,
19
+ policy requests, file snapshots, command stdout/stderr captures.
20
+ Mutable, sometimes large, sometimes contains private content (code
21
+ you pasted, command output, files the agent looked at).
22
+ 3. **Credentials** — `adapters/discord/config.json` (bot token),
23
+ `adapters/google-chat/config.json` (OAuth client secret),
24
+ `adapters/google-chat/state.json` (live OAuth refresh tokens).
25
+ Sometimes also embedded in `agents/*/settings.json` or
26
+ `environments/*/env.json` if you put API keys in their `env` block.
27
+
28
+ The first one wants version control. The second wants opaque
29
+ incremental snapshots. The third doesn't want to be in any backup that
30
+ will ever be cloned, shared, or pushed to a remote in plaintext.
31
+
32
+ A "private" git repo is **not** a credential vault: history is forever,
33
+ clones are unencrypted, and read access tends to widen over time
34
+ (collaborators, CI, leaked deploy keys). Treat it like a private Slack
35
+ channel — fine for config, wrong for tokens.
36
+
37
+ ## The two tracks
38
+
39
+ Most users want both of these, for different reasons.
40
+
41
+ ### Track 1 — Git for config (recommended)
42
+
43
+ Put `.clawmini/` itself under git, with a strict allow-list
44
+ `.gitignore` that ships only the safe-to-share config. Push to a
45
+ private remote. You get diffs, history, and a way to restore your
46
+ workspace shape on a new machine in one clone.
47
+
48
+ What's included: `settings.json`, `policies.json`, `policy-scripts/`,
49
+ `commands/`, `templates/`, chat metadata (not transcripts), agent
50
+ settings, environment settings, Discord adapter sync state.
51
+
52
+ What's excluded: chat transcripts, adapter credentials, OAuth tokens,
53
+ logs, tmp files, sockets. On restore you re-run `clawmini init` for
54
+ each adapter to rotate creds.
55
+
56
+ **Setup:**
57
+
58
+ `clawmini init` installs `.clawmini/.gitignore` automatically using the
59
+ allow-list template at
60
+ [`docs/backups/clawmini.gitignore`](../backups/clawmini.gitignore).
61
+ Workspaces created before this behaviour landed can retrofit it by
62
+ copying that template manually:
63
+
64
+ ```sh
65
+ cp /path/to/clawmini/docs/backups/clawmini.gitignore .clawmini/.gitignore
66
+ ```
67
+
68
+ Then push it to a private remote:
69
+
70
+ ```sh
71
+ cd .clawmini
72
+ git init
73
+ git add .
74
+ git status # *** review carefully before the first commit ***
75
+ git commit -m "Initial clawmini workspace backup"
76
+ git remote add origin <your-private-remote>
77
+ git push -u origin main
78
+ ```
79
+
80
+ **Audit before your first push.** Two files are included by the
81
+ allow-list but can leak secrets if you've put API keys into them:
82
+
83
+ - `agents/*/settings.json` — check the `env` and `subagentEnv`
84
+ blocks.
85
+ - `environments/*/env.json` — check the `env` block.
86
+
87
+ If you have inline secrets there, move them out (shell environment, a
88
+ separate uncommitted file, your OS keychain) before committing.
89
+
90
+ ### Track 2 — Restic for everything else (optional but recommended)
91
+
92
+ If you want chat history and adapter credentials to survive a disk
93
+ failure, use a real backup tool. Restic, Borg, and Time Machine all
94
+ work; the walkthrough below uses restic because it's cross-platform,
95
+ encrypts at rest, dedupes between snapshots, and handles the unbounded
96
+ growth of `chat.jsonl` far better than git would.
97
+
98
+ The setup below backs up to **another local folder on the same
99
+ machine** every day. That protects you from `rm -rf`, agents going
100
+ sideways, and accidental git operations — but **not** from disk
101
+ failure or theft. Point the repo at an external drive or a remote
102
+ target (`b2:`, `sftp:`, `s3:`, …) when you want real off-device
103
+ durability; everything else in this section stays the same.
104
+
105
+ #### 1. Install restic
106
+
107
+ macOS:
108
+
109
+ ```sh
110
+ brew install restic
111
+ ```
112
+
113
+ Linux (pick whichever your distro uses):
114
+
115
+ ```sh
116
+ sudo apt install restic # Debian / Ubuntu
117
+ sudo dnf install restic # Fedora / RHEL
118
+ sudo pacman -S restic # Arch
119
+ ```
120
+
121
+ #### 2. Pick a destination and a passphrase
122
+
123
+ Choose a folder *outside* your workspace — ideally on a different disk
124
+ or partition, but any local path works for a baseline.
125
+
126
+ ```sh
127
+ export RESTIC_REPOSITORY="$HOME/Backups/clawmini-restic"
128
+ mkdir -p "$RESTIC_REPOSITORY"
129
+ ```
130
+
131
+ Restic encrypts every snapshot with a passphrase. If you lose it, the
132
+ backup is unrecoverable — store it somewhere you'll still have after
133
+ your laptop dies (password manager, paper in a drawer, etc.). Save it
134
+ to a 0600-mode file so the scheduled job can read it without a prompt:
135
+
136
+ ```sh
137
+ umask 077
138
+ printf '%s\n' 'your-long-passphrase-here' > "$HOME/.config/restic/clawmini.pw"
139
+ ```
140
+
141
+ Initialize the repo (one time only):
142
+
143
+ ```sh
144
+ restic init --password-file "$HOME/.config/restic/clawmini.pw"
145
+ ```
146
+
147
+ #### 3. Write the backup script
148
+
149
+ Save this as `~/bin/clawmini-backup.sh` and `chmod +x` it. Edit
150
+ `WORKSPACE` to point at your workspace.
151
+
152
+ ```sh
153
+ #!/usr/bin/env bash
154
+ set -euo pipefail
155
+
156
+ WORKSPACE="$HOME/path/to/workspace"
157
+ export RESTIC_REPOSITORY="$HOME/Backups/clawmini-restic"
158
+ export RESTIC_PASSWORD_FILE="$HOME/.config/restic/clawmini.pw"
159
+
160
+ RESTIC_BIN="$(command -v restic)"
161
+
162
+ "$RESTIC_BIN" backup "$WORKSPACE/.clawmini" \
163
+ --tag clawmini \
164
+ --exclude '*.sock' \
165
+ --exclude '*.tmp' \
166
+ --exclude '.clawmini/tmp/snapshots/*'
167
+
168
+ "$RESTIC_BIN" forget \
169
+ --tag clawmini \
170
+ --keep-daily 30 --keep-weekly 8 --keep-monthly 12 \
171
+ --prune
172
+ ```
173
+
174
+ The retention policy keeps the last 30 daily snapshots, 8 weekly, and
175
+ 12 monthly — roughly a year of history with a long tail of dailies for
176
+ recent recovery. `--prune` reclaims the space from forgotten snapshots
177
+ in the same run.
178
+
179
+ Verify the script works manually before scheduling it:
180
+
181
+ ```sh
182
+ ~/bin/clawmini-backup.sh
183
+ restic snapshots # should list a snapshot
184
+ ```
185
+
186
+ #### 4. Schedule it daily
187
+
188
+ ##### macOS — launchd
189
+
190
+ Save this as `~/Library/LaunchAgents/com.clawmini.backup.plist`,
191
+ replacing `YOURUSER` with your home-directory username:
192
+
193
+ ```xml
194
+ <?xml version="1.0" encoding="UTF-8"?>
195
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
196
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
197
+ <plist version="1.0">
198
+ <dict>
199
+ <key>Label</key><string>com.clawmini.backup</string>
200
+ <key>ProgramArguments</key>
201
+ <array>
202
+ <string>/Users/YOURUSER/bin/clawmini-backup.sh</string>
203
+ </array>
204
+ <key>StartCalendarInterval</key>
205
+ <dict>
206
+ <key>Hour</key><integer>3</integer>
207
+ <key>Minute</key><integer>15</integer>
208
+ </dict>
209
+ <key>StandardOutPath</key>
210
+ <string>/Users/YOURUSER/Library/Logs/clawmini-backup.log</string>
211
+ <key>StandardErrorPath</key>
212
+ <string>/Users/YOURUSER/Library/Logs/clawmini-backup.log</string>
213
+ </dict>
214
+ </plist>
215
+ ```
216
+
217
+ Load it and verify:
218
+
219
+ ```sh
220
+ launchctl load ~/Library/LaunchAgents/com.clawmini.backup.plist
221
+ launchctl list | grep clawmini # confirms it's registered
222
+ launchctl start com.clawmini.backup # run once now
223
+ tail ~/Library/Logs/clawmini-backup.log
224
+ ```
225
+
226
+ To remove it later: `launchctl unload ~/Library/LaunchAgents/com.clawmini.backup.plist`.
227
+
228
+ If your laptop is asleep at the scheduled time, launchd runs the job
229
+ on the next wake. Good enough for a daily backup.
230
+
231
+ ##### Linux — systemd timer
232
+
233
+ Create the service unit at `~/.config/systemd/user/clawmini-backup.service`:
234
+
235
+ ```ini
236
+ [Unit]
237
+ Description=Clawmini workspace restic backup
238
+
239
+ [Service]
240
+ Type=oneshot
241
+ ExecStart=%h/bin/clawmini-backup.sh
242
+ Nice=10
243
+ IOSchedulingClass=idle
244
+ ```
245
+
246
+ Create the timer at `~/.config/systemd/user/clawmini-backup.timer`:
247
+
248
+ ```ini
249
+ [Unit]
250
+ Description=Daily Clawmini restic backup
251
+
252
+ [Timer]
253
+ OnCalendar=*-*-* 03:15:00
254
+ Persistent=true
255
+ RandomizedDelaySec=15m
256
+
257
+ [Install]
258
+ WantedBy=timers.target
259
+ ```
260
+
261
+ `Persistent=true` makes systemd run a missed backup on next boot
262
+ (important for laptops). Enable and start:
263
+
264
+ ```sh
265
+ systemctl --user daemon-reload
266
+ systemctl --user enable --now clawmini-backup.timer
267
+ systemctl --user list-timers clawmini-backup.timer
268
+ ```
269
+
270
+ To run a backup immediately:
271
+ `systemctl --user start clawmini-backup.service`. Logs:
272
+ `journalctl --user -u clawmini-backup.service`.
273
+
274
+ If you want the timer to fire while you're logged out, run
275
+ `loginctl enable-linger $USER` once.
276
+
277
+ If you don't have systemd (or prefer cron), the equivalent crontab
278
+ entry is:
279
+
280
+ ```cron
281
+ 15 3 * * * /home/YOURUSER/bin/clawmini-backup.sh >> /home/YOURUSER/.local/share/clawmini-backup.log 2>&1
282
+ ```
283
+
284
+ #### 5. Restore
285
+
286
+ ```sh
287
+ restic snapshots # list backups
288
+ restic restore latest --target /tmp/restore # pull latest into /tmp/restore
289
+ ```
290
+
291
+ The restored tree contains a `.clawmini/` directory you can copy back
292
+ into a fresh workspace.
293
+
294
+ If you don't want a separate tool, Time Machine on macOS or your
295
+ distro's equivalent covers the same use case at coarser granularity;
296
+ just make sure `.clawmini/` is included.
297
+
298
+ ## Common questions
299
+
300
+ **"Can I just push the whole `.clawmini/` to a private repo?"** Don't.
301
+ Your Discord bot token, Google OAuth client secret, and live OAuth
302
+ refresh tokens would go to the remote in plaintext, in permanent
303
+ history. Rotation (not deletion) is the only fix once that happens.
304
+
305
+ **"What about `git-crypt` so I can keep one repo?"** It works but adds
306
+ a key-management problem (lose the key, lose the backup) and easy
307
+ misconfigurations (smudge/clean filters silently fail). Worth it only
308
+ if you specifically want one combined repo. Otherwise Track 1 + Track 2
309
+ separates concerns more cleanly.
310
+
311
+ **"Will Track 1 let me move my workspace to a new laptop?"** Yes for
312
+ config; no for credentials and chat history. After cloning, you re-run
313
+ `clawmini init` for each adapter (which rotates the bot token / OAuth
314
+ grant — generally what you want when moving machines anyway). Track 2
315
+ restores the rest.
316
+
317
+ **"What if I add a new adapter or some new file appears under
318
+ `.clawmini/`?"** The `.gitignore` is allow-list, so new files default
319
+ to *not* tracked. Inspect `git status --ignored`, decide whether the
320
+ new file is safe, and add an explicit `!path/to/file` if it is.
321
+
322
+ **"Can I trust `agents/*/settings.json` to be safe?"** Mostly yes —
323
+ it's template-derived config — but the `env` block is a free-form map
324
+ where users sometimes drop API keys. Audit before each commit, or
325
+ adopt a habit of keeping secrets out of that file entirely.
326
+
327
+ ## Reference
328
+
329
+ - Allow-list `.gitignore` template:
330
+ [`docs/backups/clawmini.gitignore`](../backups/clawmini.gitignore)
331
+ - Full sensitivity inventory and option analysis:
332
+ [`docs/backups/SPEC.md`](../backups/SPEC.md)