OpenClaw Backup Skill
Automated encrypted backup and restore for OpenClaw Agent workspace files using Claude Code.
Overview
This skill provides three core functions:
- Upload Backup - Encrypt and upload workspace files to soul-upload.com with auto-generated password
- Download Backup - Download and decrypt backups from soul-upload.com using stored password
- Delete Backup - Delete backups from remote storage
All backups use AES-256-CBC encryption (via openssl) with auto-generated random passwords. Each backup gets a unique password that is stored in the recovery file.
System Requirements
Before executing backup operations, ensure the following tools are installed:
- Python 3.7+ (script runtime environment)
- requests library (
pip install requests) - tar (file archiving)
- openssl (encryption/decryption)
- curl (HTTP requests, system built-in)
Default Backup Files
If the user doesn't specify files, the following OpenClaw workspace files are backed up by default:
SOUL.md- Agent core identity and goalsMEMORY.md- Agent memory and contextIDENTITY.md- Agent identity definitionAGENTS.md- Agent configurationTOOLS.md- Tool configuration
Workflow 1: Upload Backup
Trigger Scenarios
Execute when the user requests to backup workspace files:
- "Back up my workspace files"
- "Upload SOUL.md to soul-upload"
- "Create an encrypted backup of my agent files"
- "Backup SOUL.md and MEMORY.md"
Execution Steps
-
Collect File List
- If user specified files, use the user-specified files
- Otherwise, use default list:
SOUL.md MEMORY.md IDENTITY.md AGENTS.md TOOLS.md - Use Read tool to verify files exist
-
Execute Backup Script (Password Auto-Generated)
- Locate script path (usually
scripts/backup.pyin Skill directory) - Execute command WITHOUT --password argument (script will auto-generate):
python3 scripts/backup.py upload \ --files "SOUL.md MEMORY.md IDENTITY.md" - Script automatically generates a 32-character random password
- Capture stdout (JSON response) and stderr (progress info including generated password)
- Locate script path (usually
-
Process Response
- On success, script outputs JSON:
{ "backupId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "downloadUrl": "https://soul-upload.com/backup/...", "sizeBytes": 12345, "sha256": "abc123...", "password": "auto-generated-32-char-random-password" } - Parse JSON and extract key information including the auto-generated password
- On success, script outputs JSON:
-
Save Recovery Information
- Use Write tool to create/update
.openclaw-backup-recovery.txt - CRITICAL: Include the auto-generated password in the recovery file
- Format:
Backup ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Password: auto-generated-32-char-random-password Download URL: https://soul-upload.com/backup/... Created: 2024-01-15 10:30:00 UTC Size: 12.05 KB SHA256: abc123... Files: SOUL.md, MEMORY.md, IDENTITY.md --- - Append to end of file (preserve history)
- Use Write tool to create/update
-
Display Success Message
- Inform user backup is complete
- Show Backup ID and file size
- IMPORTANT: Inform user that password was auto-generated and saved to
.openclaw-backup-recovery.txt - Warn user: Recovery file is CRITICAL - without it, backup cannot be restored
Error Handling
| Error Scenario | Detection | User Guidance |
|---|---|---|
| Files not found | Script returns error: "Files not found: ..." | List missing files, ask if user wants to continue backing up other files |
| Files too large | Script returns error: "Backup size ... exceeds limit ..." | Show actual size, suggest removing large files or splitting backup |
| Network error | Script returns error: "Network error: ..." | Suggest checking network connection, ask if retry is wanted |
| 413 Too Large | Script returns error: "File too large (413 Payload Too Large)" | Indicate 20MB limit exceeded, suggest reducing backup size |
| Encryption failed | Script returns error: "openssl encryption failed: ..." | Check if openssl is properly installed |
Example Conversation
User: Back up my SOUL.md and MEMORY.md
Claude: I'll backup these files with auto-generated encryption.
[Executes backup script]
Backup complete!
- Backup ID: 3f8a2b1c-...
- Size: 45.2 KB
- Password: Auto-generated (32 chars)
- Recovery info saved to .openclaw-backup-recovery.txt
IMPORTANT: Keep .openclaw-backup-recovery.txt safe!
It contains the password needed to restore this backup.
Workflow 2: Download Backup
Trigger Scenarios
Execute when user requests to restore backup:
- "Restore my backup"
- "Download my last backup"
- "Recover backup [backup-id]"
- "Restore from [download-url]"
Execution Steps
-
Get Backup ID and Password
- Check if user provided Backup ID or Download URL
- If not provided, use Read tool to read
.openclaw-backup-recovery.txt - Extract latest Backup ID AND password from file
- If file doesn't exist or is empty, cannot proceed (password unknown)
-
Determine Output Directory
- Default: Current working directory (
.) - If user specified a directory, use user-specified directory
- Warn user: Existing files may be overwritten
- Default: Current working directory (
-
Execute Restore Script
- Execute command with password from recovery file:
python3 scripts/backup.py download \ --backup-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \ --password "password-from-recovery-file" \ --output-dir "." - Capture stdout (JSON response) and stderr (progress info)
- Execute command with password from recovery file:
-
Process Response
- On success, script outputs JSON:
{ "success": true, "extractedFiles": ["SOUL.md", "MEMORY.md", "IDENTITY.md"], "outputDir": "/path/to/output" } - Parse extracted file list
- On success, script outputs JSON:
-
Verify Restoration Result
- Use Read tool to read first few lines of restored files
- Show file preview for user to confirm content is correct
- Remind user to check complete content
-
Display Success Message
- List restored files
- Show output directory
- Suggest user verify file content
Error Handling
| Error Scenario | Detection | User Guidance |
|---|---|---|
| Backup ID doesn't exist | Script returns error: "Backup not found: ..." | Check if Backup ID is correct, may have been deleted |
| Recovery file missing | .openclaw-backup-recovery.txt not found | Cannot restore - password is unknown without recovery file |
| Wrong password | Script returns error: "Decryption failed - wrong password ..." | Recovery file may be corrupted or from different backup |
| Network error | Script returns error: "Network error: ..." | Suggest checking network connection, ask if retry is wanted |
| Extraction failed | Script returns error: "tar extraction failed: ..." | File may be corrupted, try downloading again |
Example Conversation
User: Restore my last backup
Claude: I found the most recent backup in .openclaw-backup-recovery.txt
- Backup ID: 3f8a2b1c-...
- Created: 2024-01-15 10:30:00 UTC
Downloading and decrypting backup...
Restoration complete! Extracted the following files:
- SOUL.md
- MEMORY.md
- IDENTITY.md
Files saved to current directory, please verify content is correct.
Workflow 3: Delete Backup
Trigger Scenarios
Execute when user requests to delete remote backup:
- "Delete my backup"
- "Remove backup [backup-id]"
- "Delete the backup from soul-upload"
Execution Steps
-
Get Backup ID
- Check if user provided Backup ID
- If not provided, use Read tool to read
.openclaw-backup-recovery.txt - Show available backup list for user to select
- If file doesn't exist or is empty, ask user to provide Backup ID
-
Request Confirmation
- Warning: This operation is irreversible, backup will be permanently deleted
- Show Backup ID to delete and creation time
- Ask user to confirm deletion
-
Execute Delete Script
- After user confirms, execute command:
python3 scripts/backup.py delete \ --backup-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - Capture stdout (JSON response) and stderr (progress info)
- After user confirms, execute command:
-
Process Response
- On success, script outputs JSON:
{ "success": true, "backupId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
- On success, script outputs JSON:
-
Update Recovery Info File
- Use Read tool to read
.openclaw-backup-recovery.txt - Remove deleted backup record (including its password)
- Use Write tool to save updated file
- If file becomes empty, can delete the file
- Use Read tool to read
-
Display Success Message
- Confirm backup was deleted
- Show deleted Backup ID
- Remind user: If backup is needed again, must create new one with new password
Error Handling
| Error Scenario | Detection | User Guidance |
|---|---|---|
| Backup ID doesn't exist | Script returns error: "Backup not found: ..." | Backup may have been deleted or ID is incorrect |
| Network error | Script returns error: "Network error: ..." | Suggest checking network connection, ask if retry is wanted |
| User cancels | User declines confirmation | Operation cancelled, backup not deleted |
Example Conversation
User: Delete my backup
Claude: I found the following backups in .openclaw-backup-recovery.txt:
1. Backup ID: 3f8a2b1c-... (2024-01-15 10:30:00)
2. Backup ID: 7b2c9d4e-... (2024-01-14 08:20:00)
Which backup would you like to delete? (1 or 2)
User: 1
Claude: Warning: This will permanently delete backup 3f8a2b1c-...
This action cannot be undone. Confirm deletion? (yes/no)
User: yes
Claude: Backup deleted.
- Backup ID: 3f8a2b1c-...
To backup again, create a new backup with a new auto-generated password.
Security Notes
Password Policy (NEW)
- Auto-Generated Passwords: Each backup gets a unique 32-character random password
- Never Reuse Passwords: Per soul-upload.com policy, do NOT reuse passwords across backups
- Password Storage: Password is stored in
.openclaw-backup-recovery.txt(necessary for decryption) - User Responsibility: Users must keep recovery file safe - without it, backup cannot be restored
Recovery File Security
- File Location:
.openclaw-backup-recovery.txt(workspace root directory) - Content: Backup ID, Password (CRITICAL), Download URL, timestamp, SHA256
- CRITICAL: Recovery file is the ONLY place password is stored
- Recommendation:
- Add to
.gitignoreif sensitive - OR commit to version control for team access
- Consider backing up recovery file itself to separate secure location
- Add to
Encryption Algorithm
- Algorithm: AES-256-CBC (symmetric encryption)
- Salting: openssl automatically adds salt for enhanced security
- Compatibility: Consistent with soul-upload.com official documentation
Temporary File Cleanup
- Script uses try-finally to ensure temporary files are cleaned up
- Avoids leaving unencrypted sensitive data on disk
File Size Limits
- Maximum Backup Size: 20 MB (compressed and encrypted)
- Check Timing: Automatically checked before upload
- Limit Exceeded Handling: Show actual size, suggest user:
- Remove large files (like logs, caches)
- Split backup (backup different files in batches)
API Reference
soul-upload.com Backup API:
| Endpoint | Method | Function | Response |
|---|---|---|---|
/backup | POST | Upload backup | {backupId, downloadUrl, sizeBytes, sha256} |
/backup/:backupId | GET | Download backup | 302 redirect to R2 storage URL |
/backup/:backupId | DELETE | Delete backup | {success: true, backupId} |
Common Status Codes:
- 200 - Success
- 404 - Backup not found
- 413 - File too large (exceeds 20MB)
- 415 - Unsupported file type
- 500 - Server error
Troubleshooting
Missing Dependencies
Problem: Script error "Missing required tools: tar, openssl"
Solution:
- macOS:
brew install openssl(tar built-in) - Ubuntu/Debian:
sudo apt-get install tar openssl - Verify installation:
tar --versionandopenssl version
Python requests Library Missing
Problem: Script error "Error: 'requests' library not found"
Solution:
pip install requests
# or
pip3 install requests
Recovery File Lost
Problem: Cannot restore backup - recovery file missing
Solution:
- Recovery file is CRITICAL - contains the only copy of the password
- Without recovery file, backup CANNOT be restored
- Recommend backing up recovery file to separate secure location
- If lost, backup is permanently inaccessible
Network Timeout
Problem: Timeout during upload/download
Solution:
- Check network connection
- Reduce backup file size (remove unnecessary files)
- Script default timeout is 5 minutes, usually sufficient
File Already Exists
Problem: Overwriting existing files during restore
Solution:
- Backup existing files before restore
- Specify different output directory
- Manually move existing files to other location
Usage Examples
Example 1: Backup All Default Files
User: Back up my workspace files
Claude: [Execute upload workflow using default file list]
[Auto-generate password and save to recovery file]
Example 2: Backup Specific Files
User: Back up only SOUL.md and MEMORY.md
Claude: [Execute upload workflow, backup only specified files]
[Auto-generate password and save to recovery file]
Example 3: Restore Latest Backup
User: Restore my last backup
Claude: [Read latest Backup ID and password from .openclaw-backup-recovery.txt]
[Execute download workflow]
Example 4: Restore Specific Backup
User: Restore backup 3f8a2b1c-1234-5678-90ab-cdef12345678
Claude: [Read password for this Backup ID from recovery file]
[Execute download workflow]
Example 5: Delete Old Backups
User: Delete my old backups
Claude: [Show available backup list from recovery file]
[User selects backup to delete]
[Execute delete workflow]
[Remove entry from recovery file]
Best Practices
- Regular Backups: Recommend weekly backups or after important changes
- Recovery File Management: Keep
.openclaw-backup-recovery.txtsafe and backed up separately - Verify Restoration: Regularly test backup restoration process to ensure backups are usable
- Clean Old Backups: Regularly delete unneeded old backups to save storage space
- Multiple Copies: Consider keeping recovery file in multiple secure locations
Script Path
Script file is located in Skill directory at scripts/backup.py.
When executing Bash commands, ensure correct relative or absolute path is used. Usually:
- If currently in Skill directory:
python3 scripts/backup.py ... - If in other directory: Use absolute path or
cdto Skill directory first
Reference Documentation
Version: 2.0.0 Author: Claude Code License: MIT Password Policy: Auto-generated unique password per backup (NEW in v2.0.0)