clawmini 0.0.7 → 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.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/.github/workflows/release.yml +49 -0
- package/CHANGELOG.md +36 -0
- package/README.md +5 -4
- package/dist/adapter-discord/index.d.mts.map +1 -1
- package/dist/adapter-discord/index.mjs +465 -282
- package/dist/adapter-discord/index.mjs.map +1 -1
- package/dist/adapter-google-chat/index.mjs +367 -243
- package/dist/adapter-google-chat/index.mjs.map +1 -1
- package/dist/cli/index.mjs +684 -24
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lite.mjs +43 -13
- package/dist/cli/lite.mjs.map +1 -1
- package/dist/cli/{propose-policy.mjs → manage-policies.mjs} +270 -47
- package/dist/cli/manage-policies.mjs.map +1 -0
- package/dist/cli/run-host.d.mts +1 -0
- package/dist/cli/run-host.mjs +3090 -0
- package/dist/cli/run-host.mjs.map +1 -0
- package/dist/config-CPFQIGdG.mjs +57 -0
- package/dist/config-CPFQIGdG.mjs.map +1 -0
- package/dist/config-Dvl-Pov4.mjs +76 -0
- package/dist/config-Dvl-Pov4.mjs.map +1 -0
- package/dist/daemon/index.d.mts.map +1 -1
- package/dist/daemon/index.mjs +970 -332
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/supervisor-actions-CiW56eLi.mjs +843 -0
- package/dist/supervisor-actions-CiW56eLi.mjs.map +1 -0
- package/dist/turn-log-buffer-DRgW53gl.mjs +767 -0
- package/dist/turn-log-buffer-DRgW53gl.mjs.map +1 -0
- package/dist/web/_app/immutable/chunks/{Drm9vgeP.js → 3AZlWB6U.js} +1 -1
- package/dist/web/_app/immutable/chunks/BhRSsUCh.js +2 -0
- package/dist/web/_app/immutable/chunks/BiLeM2i1.js +1 -0
- package/{web/.svelte-kit/output/client/_app/immutable/chunks/CME08kGM.js → dist/web/_app/immutable/chunks/BmBj85Ll.js} +1 -1
- package/dist/web/_app/immutable/chunks/BrERcKAH.js +1 -0
- package/dist/web/_app/immutable/chunks/Bv9252RM.js +1 -0
- package/dist/web/_app/immutable/chunks/CIXNBPKi.js +1 -0
- package/dist/web/_app/immutable/chunks/DISKL3GN.js +2 -0
- package/dist/web/_app/immutable/chunks/{Zeh-C-mx.js → DcpaLzmX.js} +1 -1
- package/dist/web/_app/immutable/chunks/DnQ3vS13.js +1 -0
- package/dist/web/_app/immutable/chunks/KsloHTKS.js +1 -0
- package/{web/.svelte-kit/output/client/_app/immutable/chunks/Ck-be5J2.js → dist/web/_app/immutable/chunks/RsHsUj-8.js} +2 -2
- package/dist/web/_app/immutable/chunks/{G_zz-Gou.js → wpfV79dV.js} +1 -1
- package/dist/web/_app/immutable/entry/app.CIw1Qj0n.js +2 -0
- package/dist/web/_app/immutable/entry/start.Di0-Jhte.js +1 -0
- package/dist/web/_app/immutable/nodes/{0.CYS8iApT.js → 0.DYyUA1au.js} +1 -1
- package/dist/web/_app/immutable/nodes/1.D-3QEMMZ.js +1 -0
- package/dist/web/_app/immutable/nodes/{2.BnwnD1Ki.js → 2.4olHnH7U.js} +1 -1
- package/{web/.svelte-kit/output/client/_app/immutable/nodes/3.Dr0ot9sV.js → dist/web/_app/immutable/nodes/3.4w0bE-m2.js} +3 -3
- package/dist/web/_app/immutable/nodes/4.CZvjhVHt.js +60 -0
- package/dist/web/_app/immutable/nodes/{5.BBGQ_i84.js → 5.DLbPVJY2.js} +1 -1
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +12 -12
- package/dist/workspace-oWmVh5mi.mjs +1001 -0
- package/dist/workspace-oWmVh5mi.mjs.map +1 -0
- package/docs/23_adapter_slash_autocomplete/development_log.md +19 -0
- package/docs/23_adapter_slash_autocomplete/notes.md +18 -0
- package/docs/23_adapter_slash_autocomplete/prd.md +46 -0
- package/docs/23_adapter_slash_autocomplete/questions.md +6 -0
- package/docs/23_adapter_slash_autocomplete/tickets.md +21 -0
- package/docs/24_subagent_job_policy_fixes/development_log.md +22 -0
- package/docs/24_subagent_job_policy_fixes/notes.md +28 -0
- package/docs/24_subagent_job_policy_fixes/prd.md +59 -0
- package/docs/24_subagent_job_policy_fixes/questions.md +3 -0
- package/docs/24_subagent_job_policy_fixes/tickets.md +49 -0
- package/docs/25_e2e_test_improvements/development_log.md +30 -0
- package/docs/25_e2e_test_improvements/notes.md +29 -0
- package/docs/25_e2e_test_improvements/prd.md +43 -0
- package/docs/25_e2e_test_improvements/questions.md +12 -0
- package/docs/25_e2e_test_improvements/tickets-2.md +22 -0
- package/docs/25_e2e_test_improvements/tickets.md +22 -0
- package/docs/25_policy_cwd/development_log.md +30 -0
- package/docs/25_policy_cwd/notes.md +28 -0
- package/docs/25_policy_cwd/prd.md +77 -0
- package/docs/25_policy_cwd/questions.md +6 -0
- package/docs/25_policy_cwd/tickets.md +77 -0
- package/docs/CLI_REFERENCE.md +3 -1
- package/docs/PHILOSOPHY.md +35 -0
- package/docs/adapter-visibility/SPEC.md +461 -0
- package/docs/adapter-visibility/SPEC_v2.md +202 -0
- package/docs/auto-update/SPEC.md +344 -0
- package/docs/backups/SPEC.md +296 -0
- package/docs/backups/clawmini.gitignore +69 -0
- package/docs/guides/assets/clawmini-avatar.png +0 -0
- package/docs/guides/backups.md +332 -0
- package/docs/guides/discord_adapter_setup.md +1 -1
- package/docs/guides/google_chat_adapter_setup.md +81 -0
- package/docs/unified-startup/SPEC.md +203 -0
- package/e2e/_helpers/test-environment.test.ts +49 -0
- package/e2e/_helpers/test-environment.ts +548 -0
- package/e2e/adapters/_google-chat-fixtures.ts +340 -0
- package/{src/cli/e2e → e2e/adapters}/adapter-discord.test.ts +22 -23
- package/e2e/adapters/adapter-google-chat-downtime.test.ts +157 -0
- package/e2e/adapters/adapter-google-chat-inbound.test.ts +697 -0
- package/e2e/adapters/adapter-google-chat-outbound.test.ts +297 -0
- package/e2e/adapters/adapter-google-chat-roundtrip.test.ts +56 -0
- package/e2e/adapters/adapter-google-chat-threads.test.ts +1078 -0
- package/e2e/agents/custom-api-env.test.ts +80 -0
- package/e2e/agents/export-lite-func.test.ts +104 -0
- package/e2e/agents/fallbacks.test.ts +124 -0
- package/e2e/agents/interrupt.test.ts +50 -0
- package/e2e/agents/no-reply-necessary.test.ts +57 -0
- package/e2e/agents/session-timeout-subagents.test.ts +76 -0
- package/e2e/agents/subagent-authorization.test.ts +246 -0
- package/e2e/agents/subagent-env.test.ts +49 -0
- package/e2e/agents/subagent-lifecycle.test.ts +782 -0
- package/e2e/agents/subagents-depth.test.ts +47 -0
- package/e2e/cli/agents.test.ts +176 -0
- package/e2e/cli/auto-update.test.ts +741 -0
- package/e2e/cli/basic.test.ts +44 -0
- package/{src/cli/e2e → e2e/cli}/export-lite.test.ts +16 -12
- package/e2e/cli/init-gitignore.test.ts +86 -0
- package/e2e/cli/init.test.ts +76 -0
- package/e2e/cli/messages.test.ts +363 -0
- package/e2e/cli/serve.test.ts +76 -0
- package/{src/cli/e2e → e2e/cli}/skills.test.ts +11 -10
- package/{src/cli/e2e → e2e/daemon}/daemon.test.ts +57 -195
- package/e2e/jobs/agent-jobs.test.ts +216 -0
- package/e2e/jobs/cron.test.ts +64 -0
- package/e2e/jobs/restart.test.ts +108 -0
- package/e2e/policies/approval-session.test.ts +69 -0
- package/e2e/policies/auto-create-policies-file.test.ts +35 -0
- package/e2e/policies/builtin-manage-policies.test.ts +184 -0
- package/e2e/policies/builtin-run-host.test.ts +180 -0
- package/e2e/policies/environment-policies.test.ts +177 -0
- package/e2e/policies/manage-policies.test.ts +566 -0
- package/e2e/policies/output-size.test.ts +98 -0
- package/e2e/policies/policies-context-cwd.test.ts +160 -0
- package/e2e/policies/relative-script-path.test.ts +60 -0
- package/e2e/policies/requests-show.test.ts +135 -0
- package/e2e/policies/requests.test.ts +208 -0
- package/e2e/policies/slash-policies.test.ts +308 -0
- package/e2e/policies/startup-cleanup.test.ts +48 -0
- package/e2e/routers/session-timeout.test.ts +106 -0
- package/e2e/routers/slash-model.test.ts +152 -0
- package/e2e/routers/slash-new.test.ts +50 -0
- package/e2e/routers/slash-restart-adapter.test.ts +96 -0
- package/e2e/routers/slash-restart.test.ts +114 -0
- package/e2e/routers/slash-shutdown.test.ts +55 -0
- package/e2e/routers/slash-stop.test.ts +232 -0
- package/e2e/routers/slash-upgrade.test.ts +88 -0
- package/{src/cli/e2e → e2e/sandbox}/environments.test.ts +14 -13
- package/eslint.config.js +6 -0
- package/napkin.md +1 -1
- package/package.json +8 -3
- package/src/adapter-discord/commands.test.ts +42 -0
- package/src/adapter-discord/commands.ts +33 -0
- package/src/adapter-discord/config.ts +12 -0
- package/src/adapter-discord/forwarder.test.ts +499 -21
- package/src/adapter-discord/forwarder.ts +343 -124
- package/src/adapter-discord/inbound-cache.test.ts +47 -0
- package/src/adapter-discord/inbound-cache.ts +37 -0
- package/src/adapter-discord/index.test.ts +67 -2
- package/src/adapter-discord/index.ts +84 -216
- package/src/adapter-discord/interactions.test.ts +54 -3
- package/src/adapter-discord/interactions.ts +97 -53
- package/src/adapter-discord/processMessage.ts +239 -0
- package/src/adapter-discord/state.ts +1 -0
- package/src/adapter-google-chat/auth.test.ts +9 -5
- package/src/adapter-google-chat/auth.ts +29 -23
- package/src/adapter-google-chat/cards.ts +7 -2
- package/src/adapter-google-chat/client.test.ts +37 -2
- package/src/adapter-google-chat/client.ts +138 -38
- package/src/adapter-google-chat/config.ts +19 -0
- package/src/adapter-google-chat/forwarder.test.ts +81 -56
- package/src/adapter-google-chat/forwarder.ts +394 -185
- package/src/adapter-google-chat/inbound-cache.test.ts +61 -0
- package/src/adapter-google-chat/inbound-cache.ts +36 -0
- package/src/adapter-google-chat/state.test.ts +1 -0
- package/src/adapter-google-chat/state.ts +9 -1
- package/src/adapter-google-chat/subscriptions.ts +8 -6
- package/src/cli/builtin-policies.ts +44 -0
- package/src/cli/commands/agents.ts +59 -5
- package/src/cli/commands/down.ts +54 -2
- package/src/cli/commands/environments.ts +8 -2
- package/src/cli/commands/init.ts +31 -0
- package/src/cli/commands/logs.ts +116 -0
- package/src/cli/commands/policies.ts +6 -4
- package/src/cli/commands/serve.test.ts +67 -0
- package/src/cli/commands/serve.ts +284 -0
- package/src/cli/commands/up.ts +122 -2
- package/src/cli/commands/web-api/agents.ts +3 -2
- package/src/cli/index.ts +4 -0
- package/src/cli/install-detection.test.ts +72 -0
- package/src/cli/install-detection.ts +48 -0
- package/src/cli/lite.ts +54 -22
- package/src/cli/manage-policies-utils.ts +104 -0
- package/src/cli/manage-policies.ts +291 -0
- package/src/cli/run-host.ts +45 -0
- package/src/cli/supervisor-actions.ts +267 -0
- package/src/cli/supervisor-control.test.ts +129 -0
- package/src/cli/supervisor-control.ts +155 -0
- package/src/cli/supervisor-pid.ts +68 -0
- package/src/cli/supervisor.ts +277 -0
- package/src/daemon/agent/agent-context.ts +11 -11
- package/src/daemon/agent/agent-session.ts +8 -1
- package/src/daemon/agent/chat-logger.test.ts +78 -9
- package/src/daemon/agent/chat-logger.ts +25 -5
- package/src/daemon/agent/turn-registry.test.ts +89 -0
- package/src/daemon/agent/turn-registry.ts +94 -0
- package/src/daemon/agent/types.ts +2 -0
- package/src/daemon/api/agent-policy-endpoints.ts +263 -0
- package/src/daemon/api/agent-router.ts +47 -126
- package/src/daemon/api/index.test.ts +1 -0
- package/src/daemon/api/policy-request.test.ts +7 -5
- package/src/daemon/api/router-utils.ts +6 -5
- package/src/daemon/api/subagent-router.ts +110 -74
- package/src/daemon/api/subagent-utils.test.ts +60 -0
- package/src/daemon/api/subagent-utils.ts +113 -87
- package/src/daemon/api/user-router.ts +34 -8
- package/src/daemon/auth.ts +1 -0
- package/src/daemon/cron.test.ts +62 -4
- package/src/daemon/cron.ts +42 -16
- package/src/daemon/events.ts +65 -0
- package/src/daemon/index.ts +24 -1
- package/src/daemon/message-interruption.test.ts +1 -0
- package/src/daemon/message-jobs.test.ts +1 -0
- package/src/daemon/message.ts +78 -14
- package/src/daemon/observation.test.ts +26 -18
- package/src/daemon/pending-replies.test.ts +112 -0
- package/src/daemon/pending-replies.ts +162 -0
- package/src/daemon/policy-request-service.ts +3 -1
- package/src/daemon/policy-utils.test.ts +66 -1
- package/src/daemon/policy-utils.ts +126 -1
- package/src/daemon/request-store.ts +31 -0
- package/src/daemon/routers/session-timeout.ts +4 -0
- package/src/daemon/routers/slash-model.test.ts +344 -0
- package/src/daemon/routers/slash-model.ts +207 -0
- package/src/daemon/routers/slash-policies.test.ts +38 -32
- package/src/daemon/routers/slash-policies.ts +84 -33
- package/src/daemon/routers/slash-restart.test.ts +69 -0
- package/src/daemon/routers/slash-restart.ts +36 -0
- package/src/daemon/routers/slash-shutdown.test.ts +50 -0
- package/src/daemon/routers/slash-shutdown.ts +28 -0
- package/src/daemon/routers/slash-upgrade.test.ts +116 -0
- package/src/daemon/routers/slash-upgrade.ts +76 -0
- package/src/daemon/routers/types.ts +7 -0
- package/src/daemon/routers.ts +16 -0
- package/src/shared/adapters/blockquote.test.ts +28 -0
- package/src/shared/adapters/blockquote.ts +20 -0
- package/src/shared/adapters/filtering.test.ts +224 -10
- package/src/shared/adapters/filtering.ts +95 -7
- package/src/shared/adapters/inbound-cache.test.ts +48 -0
- package/src/shared/adapters/inbound-cache.ts +54 -0
- package/src/shared/adapters/turn-log-buffer.ts +266 -0
- package/src/shared/adapters/turn-log.test.ts +389 -0
- package/src/shared/adapters/turn-log.ts +357 -0
- package/src/shared/agent-utils.ts +12 -5
- package/src/shared/chats.test.ts +4 -0
- package/src/shared/chats.ts +9 -0
- package/src/shared/config.ts +16 -1
- package/src/shared/lite.ts +76 -2
- package/src/shared/policies.ts +26 -0
- package/src/shared/template-manifest.ts +267 -0
- package/src/shared/utils/shell.ts +61 -0
- package/src/shared/version.ts +34 -0
- package/src/shared/workspace.test.ts +217 -0
- package/src/shared/workspace.ts +626 -48
- package/templates/environments/cladding/allowlist-domain.mjs +125 -0
- package/templates/environments/cladding/env.json +21 -1
- package/templates/environments/cladding/run-with-network.mjs +54 -0
- package/templates/environments/macos-proxy/allowlist-domain.mjs +95 -0
- package/templates/environments/macos-proxy/env.json +8 -1
- package/templates/environments/macos-proxy/proxy.mjs +42 -13
- package/templates/gemini/template.json +5 -0
- package/templates/gemini-claw/template.json +13 -0
- package/templates/skills/clawmini-requests/SKILL.md +69 -10
- package/templates/skills/run-host/SKILL.md +51 -0
- package/templates/skills/skill-creator/SKILL.md +4 -3
- package/templates/skills/skill-creator/scripts/validate.sh +52 -0
- package/tsdown.config.ts +10 -1
- package/vitest.config.ts +2 -2
- package/web/.svelte-kit/ambient.d.ts +292 -176
- package/web/.svelte-kit/generated/server/internal.js +1 -1
- package/web/.svelte-kit/output/client/.vite/manifest.json +127 -137
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{Drm9vgeP.js → 3AZlWB6U.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BhRSsUCh.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BiLeM2i1.js +1 -0
- package/{dist/web/_app/immutable/chunks/CME08kGM.js → web/.svelte-kit/output/client/_app/immutable/chunks/BmBj85Ll.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BrERcKAH.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/Bv9252RM.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CIXNBPKi.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DISKL3GN.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{Zeh-C-mx.js → DcpaLzmX.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DnQ3vS13.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/KsloHTKS.js +1 -0
- package/{dist/web/_app/immutable/chunks/Ck-be5J2.js → web/.svelte-kit/output/client/_app/immutable/chunks/RsHsUj-8.js} +2 -2
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{G_zz-Gou.js → wpfV79dV.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/app.CIw1Qj0n.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.Di0-Jhte.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.CYS8iApT.js → 0.DYyUA1au.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/1.D-3QEMMZ.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.BnwnD1Ki.js → 2.4olHnH7U.js} +1 -1
- package/{dist/web/_app/immutable/nodes/3.Dr0ot9sV.js → web/.svelte-kit/output/client/_app/immutable/nodes/3.4w0bE-m2.js} +3 -3
- package/web/.svelte-kit/output/client/_app/immutable/nodes/4.CZvjhVHt.js +60 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.BBGQ_i84.js → 5.DLbPVJY2.js} +1 -1
- package/web/.svelte-kit/output/client/_app/version.json +1 -1
- package/web/.svelte-kit/output/server/.vite/manifest.json +12 -10
- package/web/.svelte-kit/output/server/chunks/Icon.js +1 -1
- package/web/.svelte-kit/output/server/chunks/client.js +1 -1
- package/web/.svelte-kit/output/server/chunks/exports.js +1 -1
- package/web/.svelte-kit/output/server/chunks/index-server.js +2 -1
- package/web/.svelte-kit/output/server/chunks/internal.js +1 -1
- package/web/.svelte-kit/output/server/chunks/render-context.js +77 -0
- package/web/.svelte-kit/output/server/chunks/root.js +739 -788
- package/web/.svelte-kit/output/server/chunks/shared.js +234 -21
- package/web/.svelte-kit/output/server/index.js +126 -90
- package/web/.svelte-kit/output/server/manifest-full.js +1 -1
- package/web/.svelte-kit/output/server/manifest.js +1 -1
- package/web/.svelte-kit/output/server/nodes/0.js +1 -1
- package/web/.svelte-kit/output/server/nodes/1.js +1 -1
- package/web/.svelte-kit/output/server/nodes/2.js +1 -1
- package/web/.svelte-kit/output/server/nodes/3.js +1 -1
- package/web/.svelte-kit/output/server/nodes/4.js +1 -1
- package/web/.svelte-kit/output/server/nodes/5.js +1 -1
- package/web/.svelte-kit/output/server/remote-entry.js +245 -81
- package/web/.svelte-kit/tsconfig.json +4 -1
- package/dist/cli/propose-policy.mjs.map +0 -1
- package/dist/lite-CBxOT1y5.mjs +0 -241
- package/dist/lite-CBxOT1y5.mjs.map +0 -1
- package/dist/routing-D8rTxtaV.mjs +0 -245
- package/dist/routing-D8rTxtaV.mjs.map +0 -1
- package/dist/web/_app/immutable/chunks/B6YN0Nuq.js +0 -1
- package/dist/web/_app/immutable/chunks/BmRlVmv6.js +0 -1
- package/dist/web/_app/immutable/chunks/CK9JZLaG.js +0 -2
- package/dist/web/_app/immutable/chunks/Ck3rYNON.js +0 -1
- package/dist/web/_app/immutable/chunks/DMtIqaiV.js +0 -2
- package/dist/web/_app/immutable/chunks/DhD271EB.js +0 -1
- package/dist/web/_app/immutable/chunks/DpuLqk8d.js +0 -1
- package/dist/web/_app/immutable/chunks/DsIToJCP.js +0 -1
- package/dist/web/_app/immutable/chunks/bBmtyQMj.js +0 -1
- package/dist/web/_app/immutable/entry/app.CJmSwntr.js +0 -2
- package/dist/web/_app/immutable/entry/start.ZpUrT2ak.js +0 -1
- package/dist/web/_app/immutable/nodes/1.Bli0Hqzn.js +0 -1
- package/dist/web/_app/immutable/nodes/4.oBhvQhcA.js +0 -60
- package/dist/workspace-BJmJBfKi.mjs +0 -456
- package/dist/workspace-BJmJBfKi.mjs.map +0 -1
- package/src/cli/e2e/agents.test.ts +0 -140
- package/src/cli/e2e/basic.test.ts +0 -43
- package/src/cli/e2e/cron.test.ts +0 -132
- package/src/cli/e2e/export-lite-func.test.ts +0 -206
- package/src/cli/e2e/fallbacks.test.ts +0 -175
- package/src/cli/e2e/init.test.ts +0 -77
- package/src/cli/e2e/messages.test.ts +0 -332
- package/src/cli/e2e/propose-policy.test.ts +0 -203
- package/src/cli/e2e/requests.test.ts +0 -180
- package/src/cli/e2e/session-timeout.test.ts +0 -192
- package/src/cli/e2e/slash-new.test.ts +0 -93
- package/src/cli/e2e/subagents.test.ts +0 -106
- package/src/cli/e2e/utils.ts +0 -66
- package/src/cli/propose-policy.ts +0 -91
- package/web/.svelte-kit/output/client/_app/immutable/chunks/B6YN0Nuq.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BmRlVmv6.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CK9JZLaG.js +0 -2
- package/web/.svelte-kit/output/client/_app/immutable/chunks/Ck3rYNON.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DMtIqaiV.js +0 -2
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DhD271EB.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DpuLqk8d.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DsIToJCP.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/bBmtyQMj.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/app.CJmSwntr.js +0 -2
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.ZpUrT2ak.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/1.Bli0Hqzn.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/4.oBhvQhcA.js +0 -60
- package/web/.svelte-kit/output/server/chunks/false.js +0 -4
- /package/dist/cli/{propose-policy.d.mts → manage-policies.d.mts} +0 -0
- /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
|
|
Binary file
|
|
@@ -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)
|