From 0ff96db918103a4f062de7ea41faa06e8f7eb9fc Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 1 Feb 2026 12:24:34 +0000 Subject: [PATCH] feat: persist full workspace to R2, not just skills Expand R2 persistence to cover the entire /root/clawd/ workspace directory, not just skills. This prevents data loss on container restarts for: - Agent memory and notes - Tool configuration files (TOOLS.md) - Tone of voice documentation - Custom directories created by agents Changes: - sync.ts: Add rsync for /root/clawd/ to R2/clawd/ with exclusions for .git, node_modules, and temp files - start-moltbot.sh: Restore full workspace from R2 before legacy skills restore Backwards compatible with existing R2 backups that only have skills/. Based on cloudflare/moltworker#88 https://claude.ai/code/session_01Ckh9sHzHzPwkNBBPuzAapq --- src/gateway/sync.ts | 21 +++++++++++++++------ start-moltbot.sh | 20 +++++++++++++++++--- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/gateway/sync.ts b/src/gateway/sync.ts index a10c711..1054e43 100644 --- a/src/gateway/sync.ts +++ b/src/gateway/sync.ts @@ -12,13 +12,18 @@ export interface SyncResult { } /** - * Sync moltbot config from container to R2 for persistence. - * + * Sync moltbot config and workspace from container to R2 for persistence. + * * This function: * 1. Mounts R2 if not already mounted * 2. Verifies source has critical files (prevents overwriting good backup with empty data) - * 3. Runs rsync to copy config to R2 + * 3. Runs rsync to copy config and workspace to R2 * 4. Writes a timestamp file for tracking + * + * Persisted paths: + * - /root/.clawdbot/ → R2/clawdbot/ (config: clawdbot.json, agent settings) + * - /root/clawd/ → R2/clawd/ (workspace: memory, tools, custom files) + * - /root/clawd/skills/ → R2/skills/ (legacy backwards compatibility) * * @param sandbox - The sandbox instance * @param env - Worker environment bindings @@ -57,9 +62,13 @@ export async function syncToR2(sandbox: Sandbox, env: MoltbotEnv): Promise ${R2_MOUNT_PATH}/.last-sync`; + // Three sync operations: + // 1. /root/.clawdbot/ → R2/clawdbot/ (config) + // 2. /root/clawd/ → R2/clawd/ (full workspace: memory, tools, custom files) + // 3. /root/clawd/skills/ → R2/skills/ (legacy backwards compatibility) + const syncCmd = `rsync -r --no-times --delete --exclude='*.lock' --exclude='*.log' --exclude='*.tmp' /root/.clawdbot/ ${R2_MOUNT_PATH}/clawdbot/ && rsync -r --no-times --delete --exclude='*.lock' --exclude='*.log' --exclude='*.tmp' --exclude='.git' --exclude='node_modules' /root/clawd/ ${R2_MOUNT_PATH}/clawd/ && rsync -r --no-times --delete /root/clawd/skills/ ${R2_MOUNT_PATH}/skills/ && date -Iseconds > ${R2_MOUNT_PATH}/.last-sync`; try { const proc = await sandbox.startProcess(syncCmd); @@ -67,7 +76,7 @@ export async function syncToR2(sandbox: Sandbox, env: MoltbotEnv): Promise/dev/null)" ]; then + if should_restore_from_r2; then + echo "Restoring full workspace from $BACKUP_DIR/clawd..." + mkdir -p "$WORKSPACE_DIR" + cp -a "$BACKUP_DIR/clawd/." "$WORKSPACE_DIR/" + echo "Restored workspace from R2 backup" + fi +fi + +# Restore skills from R2 backup if available (legacy path, backwards compatibility) +# Note: skills are now included in the full workspace backup above, but we keep this +# for backwards compatibility with existing R2 backups that only have skills/ SKILLS_DIR="/root/clawd/skills" if [ -d "$BACKUP_DIR/skills" ] && [ "$(ls -A $BACKUP_DIR/skills 2>/dev/null)" ]; then if should_restore_from_r2; then - echo "Restoring skills from $BACKUP_DIR/skills..." + echo "Restoring skills from legacy path $BACKUP_DIR/skills..." mkdir -p "$SKILLS_DIR" cp -a "$BACKUP_DIR/skills/." "$SKILLS_DIR/" - echo "Restored skills from R2 backup" + echo "Restored skills from R2 backup (legacy)" fi fi