openclaw-workspace-sync 2.3.0 → 2.3.1

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/README.src.md CHANGED
@@ -1,31 +1,108 @@
1
- # OpenClaw Workspace Cloud Sync Plugin
1
+ # OpenClaw Workspace Sync & Backup Plugin
2
2
 
3
- Sync your OpenClaw agent workspace with cloud storage via [rclone](https://rclone.org/).
3
+ Sync and back up your OpenClaw agent workspace to cloud storage via [rclone](https://rclone.org/).
4
4
 
5
- Supports **Dropbox, Google Drive, OneDrive, S3/R2/Minio**, and [70+ cloud providers](https://rclone.org/overview/).
5
+ **Sync** your workspace to Dropbox, Google Drive, OneDrive, S3, or [70+ providers](https://rclone.org/overview/) with mailbox, mirror, or bisync modes. **Back up** your entire agent system — workspace, config, sessions, memory — as encrypted snapshots to S3, R2, B2, or any rclone backend.
6
6
 
7
- ## How it works
7
+ ## What's included
8
8
 
9
- <p align="center">
10
- <img src="https://raw.githubusercontent.com/ashbrener/openclaw-workspace-sync/main/docs/how-it-works.png" alt="How it works — Local Machine syncs to Cloud Provider syncs to Remote Gateway" width="600" />
11
- </p>
9
+ | Feature | What it does | Cost |
10
+ |---------|-------------|------|
11
+ | [**Sync**](#sync) | Live mirror of your workspace to/from cloud storage. Three modes: mailbox (safest), mirror, bisync. | Zero LLM cost — pure file ops |
12
+ | [**Encrypted Backup**](#encrypted-backups) | Streaming encrypted snapshots of your entire agent system to your own bucket. Automatic retention. | Zero LLM cost, zero extra disk |
13
+
14
+ Both features use rclone under the hood and share provider credentials. You can use sync alone, backup alone, or both together with different providers — e.g. sync to Dropbox for daily access, backup to R2 for disaster recovery.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ openclaw plugins install openclaw-workspace-sync
20
+ ```
12
21
 
13
- The remote gateway workspace is the **source of truth**. Changes made by the agent flow down to your local machine through cloud storage. You can send files to the agent through an optional inbox.
22
+ Or clone into your extensions directory:
14
23
 
15
- **Zero LLM cost.** All sync operations are pure rclone file operations — they never wake the bot or trigger LLM calls.
24
+ ```bash
25
+ cd ~/.openclaw/extensions
26
+ git clone https://github.com/ashbrener/openclaw-workspace-sync workspace-sync
27
+ cd workspace-sync && npm install --omit=dev
28
+ ```
16
29
 
17
- ## Architecture
30
+ ## Quick start
31
+
32
+ ```bash
33
+ # Interactive setup wizard (recommended)
34
+ openclaw workspace-sync setup
35
+ ```
36
+
37
+ The setup wizard guides you through:
38
+ 1. Checking/installing rclone
39
+ 2. Selecting cloud provider
40
+ 3. Choosing sync mode
41
+ 4. Dropbox app folder option (for scoped access)
42
+ 5. Background sync interval
43
+ 6. OAuth authorization
44
+ 7. First sync
45
+
46
+ Or configure manually — see [Configuration](#configuration) below.
47
+
48
+ ## Configuration
49
+
50
+ Add to your `openclaw.json`. The `sync` and `backup` blocks are independent — use one or both:
51
+
52
+ ```json
53
+ {
54
+ "plugins": {
55
+ "entries": {
56
+ "openclaw-workspace-sync": {
57
+ "enabled": true,
58
+ "config": {
59
+ "sync": {
60
+ "provider": "dropbox",
61
+ "mode": "mailbox",
62
+ "remotePath": "",
63
+ "localPath": "/",
64
+ "interval": 180,
65
+ "onSessionStart": true,
66
+ "exclude": [".git/**", "node_modules/**", "*.log"]
67
+ },
68
+ "backup": {
69
+ "enabled": true,
70
+ "provider": "s3",
71
+ "bucket": "my-backups",
72
+ "prefix": "habibi/",
73
+ "interval": 86400,
74
+ "encrypt": true,
75
+ "passphrase": "${BACKUP_PASSPHRASE}",
76
+ "include": ["workspace", "config", "cron", "memory"],
77
+ "retain": 7
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ ```
85
+
86
+ > **Flat format still works.** Putting `provider`, `mode`, etc. at the config root (without `sync`) is supported for backwards compatibility. The nested `{ sync, backup }` format is recommended for clarity.
87
+
88
+ ---
89
+
90
+ ## Sync
91
+
92
+ Live workspace mirroring via rclone. The remote gateway workspace is the **source of truth**. Changes made by the agent flow down to your local machine through cloud storage. You can send files to the agent through an optional inbox.
93
+
94
+ <p align="center">
95
+ <img src="https://raw.githubusercontent.com/ashbrener/openclaw-workspace-sync/main/docs/how-it-works.png" alt="How it works — Local Machine syncs to Cloud Provider syncs to Remote Gateway" width="600" />
96
+ </p>
18
97
 
19
98
  <p align="center">
20
99
  <img src="https://raw.githubusercontent.com/ashbrener/openclaw-workspace-sync/main/docs/architecture.png" alt="Plugin architecture — CLI, Hooks, and Sync Manager feed into rclone wrapper" width="600" />
21
100
  </p>
22
101
 
23
- ## Sync modes (breaking change in v2.0)
102
+ ### Sync modes (breaking change in v2.0)
24
103
 
25
104
  **`mode` is now required.** Previous versions used bidirectional bisync implicitly. Starting with v2.0, you must explicitly set `"mode"` in your config. The plugin will refuse to start and log an error until `mode` is set. This prevents accidental data loss from an unexpected sync direction.
26
105
 
27
- The plugin supports three sync modes. Choose the one that fits your workflow:
28
-
29
106
  | Mode | Direction | Description |
30
107
  |------|-----------|-------------|
31
108
  | `mailbox` | Push + inbox/outbox | Workspace pushes to cloud; users drop files in `_outbox` to send them to the agent. **Safest.** |
@@ -34,7 +111,7 @@ The plugin supports three sync modes. Choose the one that fits your workflow:
34
111
 
35
112
  **Upgrading from a previous version?** If you were using bisync before, add `"mode": "bisync"` to your config to preserve the existing behavior. For the safest option, use `"mode": "mailbox"`.
36
113
 
37
- ### `mailbox` mode (recommended)
114
+ #### `mailbox` mode (recommended)
38
115
 
39
116
  The agent workspace is the source of truth. Each sync cycle:
40
117
 
@@ -72,7 +149,7 @@ On startup, the plugin bootstraps both directories:
72
149
 
73
150
  Because the push explicitly excludes `_inbox/**` and `_outbox/**`, there is no risk of sync loops or accidental overwrites. Files only flow in one direction through each channel.
74
151
 
75
- #### Inbox notifications (optional)
152
+ ##### Inbox notifications (optional)
76
153
 
77
154
  By default, mailbox mode is silent — files land in `_inbox` without waking the agent. This keeps costs at zero.
78
155
 
@@ -95,7 +172,7 @@ This wakes the agent on its next heartbeat. The agent sees the message and can p
95
172
  }
96
173
  ```
97
174
 
98
- ### `mirror` mode
175
+ #### `mirror` mode
99
176
 
100
177
  The agent workspace is the source of truth. Every sync cycle copies the latest workspace state down to your local folder. Local files outside the workspace are never sent up.
101
178
 
@@ -117,7 +194,7 @@ flowchart LR
117
194
 
118
195
  This is safe: even if something goes wrong, only your local copy is affected — the workspace stays untouched.
119
196
 
120
- ### `ingest` option (mirror mode only)
197
+ ##### `ingest` option (mirror mode only)
121
198
 
122
199
  Want to send files to the agent while using mirror mode? Enable the `ingest` option. This creates a local `inbox/` folder (sibling to the sync folder) that syncs one-way **up** to the workspace. Drop a file in the inbox — it appears on the remote workspace. The inbox is separate from the mirror, so there is no risk of overwriting workspace files.
123
200
 
@@ -133,7 +210,7 @@ When enabled, a local `inbox/` folder syncs its contents to `<remotePath>/inbox/
133
210
 
134
211
  > For a more robust file-exchange pattern, consider `mailbox` mode instead. Mailbox uses `rclone move` to drain files (deleting from the source after transfer), which prevents duplicates and is easier to reason about.
135
212
 
136
- ### `bisync` mode (advanced)
213
+ #### `bisync` mode (advanced)
137
214
 
138
215
  Full bidirectional sync using rclone bisync. Changes on either side propagate to the other.
139
216
 
@@ -164,136 +241,7 @@ Use this only if you understand the trade-offs:
164
241
 
165
242
  If you are running on a container platform, `mailbox` mode is strongly recommended.
166
243
 
167
- ## Before your first sync
168
-
169
- Getting the initial state right prevents data loss. Each mode has different requirements:
170
-
171
- ### `mailbox` mode — starting state
172
-
173
- The first sync **pushes** your local workspace to the cloud. This means rclone makes cloud match local exactly — any files on cloud that don't exist locally will be **deleted**.
174
-
175
- **Recommended starting state:** Local workspace is the source of truth (the agent has been writing here), or local and remote are already identical.
176
-
177
- **If remote is the source of truth** (e.g. you've been syncing manually or switching from another mode), pull first:
178
-
179
- ```bash
180
- rclone sync <remote>:<path> /data/workspace/ --config <config-path> \
181
- --exclude '**/.DS_Store' --exclude '**/.git/**' \
182
- --exclude '**/__pycache__/**' --exclude '**/node_modules/**' \
183
- --verbose
184
- ```
185
-
186
- Then verify local matches remote before enabling the plugin.
187
-
188
- ### `mirror` mode — starting state
189
-
190
- The first sync **pulls** from cloud to local. Local can be empty, stale, or corrupted — the pull simply overwrites it. **No preparation needed.**
191
-
192
- ### `bisync` mode — starting state
193
-
194
- The first sync requires `--resync`, which copies everything from both sides to the other. Any stale or unwanted files on either side will propagate.
195
-
196
- **Recommended starting state:** Both sides are identical, or one side is empty and the other has the data you want. Verify both before running `--resync`.
197
-
198
- ### General first-sync checklist
199
-
200
- 1. Run a `--dry-run` first to see what would happen: `openclaw workspace-sync sync --dry-run`
201
- 2. Check the output for unexpected deletions
202
- 3. If everything looks right, run the actual sync
203
- 4. Only then enable periodic sync (`interval` in config)
204
-
205
- > For maintenance, recovery, and common problems, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md).
206
-
207
- ## Setup sequence
208
-
209
- Getting sync right depends on doing things in the right order. Follow these steps:
210
-
211
- 1. **Configure the plugin** in `openclaw.json` with your provider credentials and `mode`
212
- 2. **Verify the remote** is accessible: `openclaw workspace-sync status`
213
- 3. **Run a dry-run first** to see what would happen: `openclaw workspace-sync sync --dry-run`
214
- 4. **Run the first sync**: `openclaw workspace-sync sync`
215
- - In `mailbox` mode, this pushes the workspace and drains the `_outbox`
216
- - In `mirror` mode, this pulls the current workspace down
217
- - In `bisync` mode, this requires `--resync` to establish the baseline
218
- 5. **Enable periodic sync** by setting `interval` in your config
219
-
220
- Take care when changing config (switching `remotePath`, `localPath`, or `mode`) — always disable periodic sync first, verify the new paths, then re-enable.
221
-
222
- ## Install
223
-
224
- ```bash
225
- openclaw plugins install openclaw-workspace-sync
226
- ```
227
-
228
- Or clone into your extensions directory:
229
-
230
- ```bash
231
- cd ~/.openclaw/extensions
232
- git clone https://github.com/ashbrener/openclaw-workspace-sync workspace-sync
233
- cd workspace-sync && npm install --omit=dev
234
- ```
235
-
236
- ## Quick start
237
-
238
- ```bash
239
- # Interactive setup wizard (recommended)
240
- openclaw workspace-sync setup
241
- ```
242
-
243
- The setup wizard guides you through:
244
- 1. Checking/installing rclone
245
- 2. Selecting cloud provider
246
- 3. Choosing sync mode
247
- 4. Dropbox app folder option (for scoped access)
248
- 5. Background sync interval
249
- 6. OAuth authorization
250
- 7. First sync
251
-
252
- Or configure manually — see [Configuration](#configuration) below.
253
-
254
- ## Configuration
255
-
256
- Add to your `openclaw.json`:
257
-
258
- ```json
259
- {
260
- "plugins": {
261
- "entries": {
262
- "openclaw-workspace-sync": {
263
- "enabled": true,
264
- "config": {
265
- "sync": {
266
- "provider": "dropbox",
267
- "mode": "mailbox",
268
- "remotePath": "",
269
- "localPath": "/",
270
- "interval": 60,
271
- "timeout": 1800,
272
- "onSessionStart": true,
273
- "onSessionEnd": false,
274
- "exclude": [".git/**", "node_modules/**", "*.log"]
275
- },
276
- "backup": {
277
- "enabled": true,
278
- "provider": "s3",
279
- "bucket": "my-backups",
280
- "prefix": "habibi/",
281
- "interval": 86400,
282
- "encrypt": true,
283
- "passphrase": "${BACKUP_PASSPHRASE}",
284
- "include": ["workspace", "config", "cron", "memory"],
285
- "retain": 7
286
- }
287
- }
288
- }
289
- }
290
- }
291
- }
292
- ```
293
-
294
- > **Flat format still works.** Putting `provider`, `mode`, etc. at the config root (without `sync`) is supported for backwards compatibility. The nested `{ sync, backup }` format is recommended for clarity.
295
-
296
- ### Config reference
244
+ ### Sync config reference
297
245
 
298
246
  | Key | Type | Default | Description |
299
247
  |-----|------|---------|-------------|
@@ -316,93 +264,7 @@ Add to your `openclaw.json`:
316
264
 
317
265
  Default excludes: `**/.DS_Store`
318
266
 
319
- ### Provider-specific options
320
-
321
- **Dropbox with app folder (recommended for security):**
322
-
323
- ```json
324
- {
325
- "provider": "dropbox",
326
- "remotePath": "",
327
- "dropbox": {
328
- "appFolder": true,
329
- "appKey": "your-app-key",
330
- "appSecret": "your-app-secret",
331
- "token": "{\"access_token\":\"...\"}"
332
- }
333
- }
334
- ```
335
-
336
- With `appFolder: true`, set `remotePath` to `""`. The app folder root is your sync root — do not repeat the app folder name in `remotePath` or rclone will fail with "directory not found."
337
-
338
- **Google Drive:**
339
-
340
- ```json
341
- {
342
- "provider": "gdrive",
343
- "remotePath": "openclaw-sync",
344
- "gdrive": {
345
- "token": "{\"access_token\":\"...\"}",
346
- "teamDrive": "0ABcDeFgHiJ",
347
- "rootFolderId": "folder-id"
348
- }
349
- }
350
- ```
351
-
352
- `teamDrive` and `rootFolderId` are optional — omit them for personal Google Drive.
353
-
354
- **OneDrive:**
355
-
356
- ```json
357
- {
358
- "provider": "onedrive",
359
- "remotePath": "openclaw-sync",
360
- "onedrive": {
361
- "token": "{\"access_token\":\"...\"}",
362
- "driveId": "drive-id",
363
- "driveType": "business"
364
- }
365
- }
366
- ```
367
-
368
- `driveType` can be `personal`, `business`, or `sharepoint`. Both fields are optional.
369
-
370
- **S3 / Cloudflare R2 / Minio:**
371
-
372
- ```json
373
- {
374
- "provider": "s3",
375
- "remotePath": "openclaw-sync",
376
- "s3": {
377
- "endpoint": "https://s3.us-east-1.amazonaws.com",
378
- "bucket": "your-bucket",
379
- "region": "us-east-1",
380
- "accessKeyId": "AKID...",
381
- "secretAccessKey": "SECRET..."
382
- }
383
- }
384
- ```
385
-
386
- **Any rclone backend (SFTP, B2, Mega, pCloud, etc.):**
387
-
388
- ```json
389
- {
390
- "provider": "custom",
391
- "remotePath": "openclaw-sync",
392
- "custom": {
393
- "rcloneType": "sftp",
394
- "rcloneOptions": {
395
- "host": "example.com",
396
- "user": "deploy",
397
- "key_file": "/path/to/key"
398
- }
399
- }
400
- }
401
- ```
402
-
403
- The `custom` provider accepts any [rclone backend type](https://rclone.org/overview/) and passes `rcloneOptions` directly to the rclone config. This gives you config-driven access to all 70+ providers without manually editing `rclone.conf`.
404
-
405
- ## CLI commands
267
+ ### Sync CLI commands
406
268
 
407
269
  ```bash
408
270
  # Interactive setup wizard
@@ -432,9 +294,9 @@ openclaw workspace-sync authorize --provider gdrive
432
294
  openclaw workspace-sync list
433
295
  ```
434
296
 
435
- ## Auto-sync
297
+ ### Auto-sync
436
298
 
437
- ### Session hooks
299
+ #### Session hooks
438
300
 
439
301
  Sync automatically when sessions start or end. These run during existing agent activity and incur zero LLM cost:
440
302
 
@@ -445,7 +307,7 @@ Sync automatically when sessions start or end. These run during existing agent a
445
307
  }
446
308
  ```
447
309
 
448
- ### Periodic background sync
310
+ #### Periodic background sync
449
311
 
450
312
  Set `interval` to enable automatic background sync (in seconds):
451
313
 
@@ -460,72 +322,54 @@ The gateway runs sync in the background at this interval. Minimum interval is 60
460
322
 
461
323
  In `mailbox` mode, periodic sync pushes the workspace to the cloud and drains the `_outbox`. In `mirror` mode, periodic sync pulls the latest workspace state down to local. In `bisync` mode, it runs a full bidirectional sync.
462
324
 
463
- ### External cron (alternative)
325
+ #### External cron (alternative)
464
326
 
465
327
  ```bash
466
328
  # Add to crontab (crontab -e)
467
329
  */5 * * * * openclaw workspace-sync sync >> /var/log/openclaw-sync.log 2>&1
468
330
  ```
469
331
 
470
- ## Supported providers
332
+ ### Before your first sync
471
333
 
472
- | Provider | Config value | Auth method | Config-driven |
473
- |----------|-------------|-------------|---------------|
474
- | Dropbox | `dropbox` | OAuth token | Full (token, appKey, appSecret, appFolder) |
475
- | Google Drive | `gdrive` | OAuth token | Full (token, teamDrive, rootFolderId) |
476
- | OneDrive | `onedrive` | OAuth token | Full (token, driveId, driveType) |
477
- | S3/R2/Minio | `s3` | Access keys | Full (endpoint, bucket, region, credentials) |
478
- | Any rclone backend | `custom` | Varies | Full (rcloneType + rcloneOptions) |
479
-
480
- All providers are fully config-driven — no manual `rclone.conf` editing needed. The `custom` provider gives access to all [70+ rclone backends](https://rclone.org/overview/) (SFTP, B2, Mega, pCloud, Azure Blob, etc.).
334
+ Getting the initial state right prevents data loss. Each mode has different requirements:
481
335
 
482
- ## Manual setup (without wizard)
336
+ #### `mailbox` mode starting state
483
337
 
484
- If you prefer to skip the interactive wizard, configure the plugin in `openclaw.json` and use the CLI:
338
+ The first sync **pushes** your local workspace to the cloud. This means rclone makes cloud match local exactly any files on cloud that don't exist locally will be **deleted**.
485
339
 
486
- ```bash
487
- # 1. Authorize with your cloud provider
488
- openclaw workspace-sync authorize --provider dropbox
340
+ **Recommended starting state:** Local workspace is the source of truth (the agent has been writing here), or local and remote are already identical.
489
341
 
490
- # 2. Run a dry-run to preview what will sync
491
- openclaw workspace-sync sync --dry-run
342
+ **If remote is the source of truth** (e.g. you've been syncing manually or switching from another mode), pull first:
492
343
 
493
- # 3. Run the first sync
494
- openclaw workspace-sync sync
344
+ ```bash
345
+ rclone sync <remote>:<path> /data/workspace/ --config <config-path> \
346
+ --exclude '**/.DS_Store' --exclude '**/.git/**' \
347
+ --exclude '**/__pycache__/**' --exclude '**/node_modules/**' \
348
+ --verbose
495
349
  ```
496
350
 
497
- The plugin handles rclone installation, config generation, and token storage automatically based on your `openclaw.json` settings.
351
+ Then verify local matches remote before enabling the plugin.
498
352
 
499
- ## Dropbox app folder access (recommended)
353
+ #### `mirror` mode starting state
500
354
 
501
- For better security, create a scoped Dropbox app that only accesses a single folder:
355
+ The first sync **pulls** from cloud to local. Local can be empty, stale, or corrupted the pull simply overwrites it. **No preparation needed.**
502
356
 
503
- 1. Go to [Dropbox App Console](https://www.dropbox.com/developers/apps)
504
- 2. Click **Create app** > **Scoped access** > **App folder**
505
- 3. Name it (e.g., `openclaw-sync`)
506
- 4. In **Settings** tab, add a **Redirect URI**: `http://localhost:53682/`
507
- - This is required for rclone's OAuth flow to work. Without it, Dropbox returns "Invalid redirect_uri" during authorization.
508
- 5. In **Permissions** tab, enable:
509
- - `files.metadata.read` / `files.metadata.write`
510
- - `files.content.read` / `files.content.write`
511
- 6. Copy **App key** and **App secret** from Settings
357
+ #### `bisync` mode starting state
512
358
 
513
- > **Important:** When using an app folder scoped app, set `"remotePath": ""` (empty string) in your config. The app folder **is** the root rclone sees it as `/`. If you set `remotePath` to your app folder name (e.g., `"openclaw-sync"`), rclone will look for a subfolder *inside* the app folder with that name and fail with "directory not found."
359
+ The first sync requires `--resync`, which copies everything from both sides to the other. Any stale or unwanted files on either side will propagate.
514
360
 
515
- Benefits:
516
- - Token only accesses one folder, not your entire Dropbox
517
- - If token is compromised, blast radius is limited
518
- - Clean separation — sync folder lives under `Apps/<your-app-name>/`
361
+ **Recommended starting state:** Both sides are identical, or one side is empty and the other has the data you want. Verify both before running `--resync`.
519
362
 
520
- ### Dropbox rate limiting
363
+ #### General first-sync checklist
521
364
 
522
- Dropbox enforces API rate limits (`too_many_requests`). If your workspace has many files (10k+), each sync cycle can consume a large number of API calls just for checking. To avoid hitting limits:
365
+ 1. Run a `--dry-run` first to see what would happen: `openclaw workspace-sync sync --dry-run`
366
+ 2. Check the output for unexpected deletions
367
+ 3. If everything looks right, run the actual sync
368
+ 4. Only then enable periodic sync (`interval` in config)
523
369
 
524
- - **Set `interval` high enough** for the sync to complete between cycles. A workspace with ~40k files takes ~2 minutes to scan. An `interval` of 180 (3 min) is the minimum; 300 (5 min) is safer.
525
- - **Use `exclude` patterns liberally** — skip `node_modules`, `.git`, `__pycache__`, build output, and anything you don't need synced. Fewer files = fewer API calls.
526
- - **If you see `too_many_requests` errors** in the logs, increase the interval and add more excludes.
370
+ > For maintenance, recovery, and common problems, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md).
527
371
 
528
- ## Understanding sync safety
372
+ ### Sync safety
529
373
 
530
374
  Cloud sync involves two copies of your data. When things go wrong, one side can overwrite the other. Here is what to keep in mind:
531
375
 
@@ -545,7 +389,7 @@ Cloud sync involves two copies of your data. When things go wrong, one side can
545
389
 
546
390
  > For recovery procedures, mode switching, and maintenance tips, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md).
547
391
 
548
- ## Important: `--resync` is destructive (bisync only)
392
+ #### Important: `--resync` is destructive (bisync only)
549
393
 
550
394
  **Never use `--resync` unless you know exactly what it does.** The `--resync` flag tells rclone to throw away its knowledge of what has changed and do a full reconciliation — it copies every file that exists on either side to the other side. This means:
551
395
 
@@ -560,15 +404,15 @@ Normal bisync (without `--resync`) only transfers files that changed since the l
560
404
  openclaw workspace-sync sync --resync
561
405
  ```
562
406
 
563
- ## Troubleshooting
407
+ ### Sync troubleshooting
564
408
 
565
- ### Token expired
409
+ #### Token expired
566
410
 
567
411
  ```bash
568
412
  openclaw workspace-sync authorize
569
413
  ```
570
414
 
571
- ### Conflicts (bisync only)
415
+ #### Conflicts (bisync only)
572
416
 
573
417
  Files modified on both sides get a `.conflict` suffix. The winner is determined by `conflictResolve` (default: `newer`). To find conflict files:
574
418
 
@@ -576,7 +420,7 @@ Files modified on both sides get a `.conflict` suffix. The winner is determined
576
420
  find <workspace>/shared -name "*.conflict"
577
421
  ```
578
422
 
579
- ### Stale lock files
423
+ #### Stale lock files
580
424
 
581
425
  The plugin automatically handles stale rclone lock files. If a sync is interrupted (timeout, crash, kill), the next run detects the stale lock, clears it, and retries. Lock files older than 15 minutes are treated as expired by rclone's `--max-lock` flag.
582
426
 
@@ -586,7 +430,7 @@ If you still see lock errors, you can manually clear them:
586
430
  rclone deletefile ~/.cache/rclone/bisync/<lockfile>.lck
587
431
  ```
588
432
 
589
- ### Sync times out
433
+ #### Sync times out
590
434
 
591
435
  Increase the `timeout` config (in seconds). The default is 1800 (30 min). For large workspaces:
592
436
 
@@ -596,28 +440,21 @@ Increase the `timeout` config (in seconds). The default is 1800 (30 min). For la
596
440
  }
597
441
  ```
598
442
 
599
- ### Permission errors
443
+ #### Permission errors
600
444
 
601
445
  ```bash
602
446
  chmod -R 755 <workspace>/shared
603
447
  ```
604
448
 
605
- ## Deployment recommendations
606
-
607
- If you are running OpenClaw on a cloud container (Fly.io, Railway, Render) or a VPS:
449
+ #### Dropbox rate limiting
608
450
 
609
- - **Use a separate persistent volume for the workspace.** Container root filesystems are ephemeral a redeploy wipes everything. Mount a dedicated volume (e.g., Fly.io volumes, EBS, DigitalOcean block storage) at your workspace path so data survives deploys and restarts.
610
- - **Enable daily volume snapshots.** Most cloud providers offer automated snapshots (Fly.io does this by default with 5-day retention). If something goes wrong — a bad sync, accidental deletion, or a failed reorganization — a recent snapshot lets you restore in minutes instead of rebuilding from scratch.
611
- - **Test your restore process.** A backup you have never restored is a backup you do not have. Create a volume from a snapshot at least once to confirm the process works and you know the steps.
612
-
613
- These recommendations apply regardless of whether you use this plugin. Cloud sync adds convenience but is not a substitute for proper backups.
451
+ Dropbox enforces API rate limits (`too_many_requests`). If your workspace has many files (10k+), each sync cycle can consume a large number of API calls just for checking. To avoid hitting limits:
614
452
 
615
- ## Security notes
453
+ - **Set `interval` high enough** for the sync to complete between cycles. A workspace with ~40k files takes ~2 minutes to scan. An `interval` of 180 (3 min) is the minimum; 300 (5 min) is safer.
454
+ - **Use `exclude` patterns liberally** — skip `node_modules`, `.git`, `__pycache__`, build output, and anything you don't need synced. Fewer files = fewer API calls.
455
+ - **If you see `too_many_requests` errors** in the logs, increase the interval and add more excludes.
616
456
 
617
- - **Token storage**: rclone tokens are stored in `rclone.conf` with `0600` permissions
618
- - **Sensitive files**: Don't sync secrets, API keys, or credentials
619
- - **Encryption**: Consider [rclone crypt](https://rclone.org/crypt/) for sensitive data
620
- - **App folder**: Use Dropbox app folder access for minimal permissions
457
+ ---
621
458
 
622
459
  ## Encrypted backups
623
460
 
@@ -653,32 +490,6 @@ flowchart TD
653
490
 
654
491
  > **Disk-constrained?** Because backups stream directly, you don't need any free disk space for the backup itself. Only the restore downloads to a staging directory.
655
492
 
656
- ### Configuration
657
-
658
- Add `sync` and `backup` blocks to your plugin config. The backup provider can differ from your sync provider — sync to Dropbox for live mirror, backup to S3 for disaster recovery:
659
-
660
- ```json
661
- {
662
- "sync": {
663
- "provider": "dropbox",
664
- "mode": "mailbox",
665
- "remotePath": "",
666
- "interval": 180
667
- },
668
- "backup": {
669
- "enabled": true,
670
- "provider": "s3",
671
- "bucket": "my-backups",
672
- "prefix": "habibi/",
673
- "interval": 86400,
674
- "encrypt": true,
675
- "passphrase": "${BACKUP_PASSPHRASE}",
676
- "include": ["workspace", "config", "cron", "memory"],
677
- "retain": { "daily": 7, "weekly": 4 }
678
- }
679
- }
680
- ```
681
-
682
493
  ### Backup config reference
683
494
 
684
495
  | Key | Type | Default | Description |
@@ -714,7 +525,7 @@ Add `sync` and `backup` blocks to your plugin config. The backup provider can di
714
525
 
715
526
  Default: `["workspace", "config", "cron", "memory"]`
716
527
 
717
- ### CLI commands
528
+ ### Backup CLI commands
718
529
 
719
530
  ```bash
720
531
  # Create a backup now
@@ -740,7 +551,7 @@ openclaw workspace-sync backup status
740
551
 
741
552
  By default, `restore` extracts to a staging directory (`~/.openclaw/.backup-restore/`), not directly over your live workspace. This lets you inspect the contents before copying them into place. Use `--to` to control where files land.
742
553
 
743
- ### Provider examples
554
+ ### Backup provider examples
744
555
 
745
556
  **Cloudflare R2 (free tier: 10GB):**
746
557
 
@@ -801,6 +612,148 @@ By default, `restore` extracts to a staging directory (`~/.openclaw/.backup-rest
801
612
  }
802
613
  ```
803
614
 
615
+ ---
616
+
617
+ ## Provider-specific options
618
+
619
+ These provider blocks work for both sync and backup. Place them inside the `sync` or `backup` config block as needed.
620
+
621
+ **Dropbox with app folder (recommended for security):**
622
+
623
+ ```json
624
+ {
625
+ "provider": "dropbox",
626
+ "remotePath": "",
627
+ "dropbox": {
628
+ "appFolder": true,
629
+ "appKey": "your-app-key",
630
+ "appSecret": "your-app-secret",
631
+ "token": "{\"access_token\":\"...\"}"
632
+ }
633
+ }
634
+ ```
635
+
636
+ With `appFolder: true`, set `remotePath` to `""`. The app folder root is your sync root — do not repeat the app folder name in `remotePath` or rclone will fail with "directory not found."
637
+
638
+ **Google Drive:**
639
+
640
+ ```json
641
+ {
642
+ "provider": "gdrive",
643
+ "remotePath": "openclaw-sync",
644
+ "gdrive": {
645
+ "token": "{\"access_token\":\"...\"}",
646
+ "teamDrive": "0ABcDeFgHiJ",
647
+ "rootFolderId": "folder-id"
648
+ }
649
+ }
650
+ ```
651
+
652
+ `teamDrive` and `rootFolderId` are optional — omit them for personal Google Drive.
653
+
654
+ **OneDrive:**
655
+
656
+ ```json
657
+ {
658
+ "provider": "onedrive",
659
+ "remotePath": "openclaw-sync",
660
+ "onedrive": {
661
+ "token": "{\"access_token\":\"...\"}",
662
+ "driveId": "drive-id",
663
+ "driveType": "business"
664
+ }
665
+ }
666
+ ```
667
+
668
+ `driveType` can be `personal`, `business`, or `sharepoint`. Both fields are optional.
669
+
670
+ **S3 / Cloudflare R2 / Minio:**
671
+
672
+ ```json
673
+ {
674
+ "provider": "s3",
675
+ "remotePath": "openclaw-sync",
676
+ "s3": {
677
+ "endpoint": "https://s3.us-east-1.amazonaws.com",
678
+ "bucket": "your-bucket",
679
+ "region": "us-east-1",
680
+ "accessKeyId": "AKID...",
681
+ "secretAccessKey": "SECRET..."
682
+ }
683
+ }
684
+ ```
685
+
686
+ **Any rclone backend (SFTP, B2, Mega, pCloud, etc.):**
687
+
688
+ ```json
689
+ {
690
+ "provider": "custom",
691
+ "remotePath": "openclaw-sync",
692
+ "custom": {
693
+ "rcloneType": "sftp",
694
+ "rcloneOptions": {
695
+ "host": "example.com",
696
+ "user": "deploy",
697
+ "key_file": "/path/to/key"
698
+ }
699
+ }
700
+ }
701
+ ```
702
+
703
+ The `custom` provider accepts any [rclone backend type](https://rclone.org/overview/) and passes `rcloneOptions` directly to the rclone config. This gives you config-driven access to all 70+ providers without manually editing `rclone.conf`.
704
+
705
+ ### Supported providers
706
+
707
+ | Provider | Config value | Auth method | Config-driven |
708
+ |----------|-------------|-------------|---------------|
709
+ | Dropbox | `dropbox` | OAuth token | Full (token, appKey, appSecret, appFolder) |
710
+ | Google Drive | `gdrive` | OAuth token | Full (token, teamDrive, rootFolderId) |
711
+ | OneDrive | `onedrive` | OAuth token | Full (token, driveId, driveType) |
712
+ | S3/R2/Minio | `s3` | Access keys | Full (endpoint, bucket, region, credentials) |
713
+ | Any rclone backend | `custom` | Varies | Full (rcloneType + rcloneOptions) |
714
+
715
+ All providers are fully config-driven — no manual `rclone.conf` editing needed. The `custom` provider gives access to all [70+ rclone backends](https://rclone.org/overview/) (SFTP, B2, Mega, pCloud, Azure Blob, etc.).
716
+
717
+ ### Dropbox app folder access (recommended)
718
+
719
+ For better security, create a scoped Dropbox app that only accesses a single folder:
720
+
721
+ 1. Go to [Dropbox App Console](https://www.dropbox.com/developers/apps)
722
+ 2. Click **Create app** > **Scoped access** > **App folder**
723
+ 3. Name it (e.g., `openclaw-sync`)
724
+ 4. In **Settings** tab, add a **Redirect URI**: `http://localhost:53682/`
725
+ - This is required for rclone's OAuth flow to work. Without it, Dropbox returns "Invalid redirect_uri" during authorization.
726
+ 5. In **Permissions** tab, enable:
727
+ - `files.metadata.read` / `files.metadata.write`
728
+ - `files.content.read` / `files.content.write`
729
+ 6. Copy **App key** and **App secret** from Settings
730
+
731
+ > **Important:** When using an app folder scoped app, set `"remotePath": ""` (empty string) in your config. The app folder **is** the root — rclone sees it as `/`. If you set `remotePath` to your app folder name (e.g., `"openclaw-sync"`), rclone will look for a subfolder *inside* the app folder with that name and fail with "directory not found."
732
+
733
+ Benefits:
734
+ - Token only accesses one folder, not your entire Dropbox
735
+ - If token is compromised, blast radius is limited
736
+ - Clean separation — sync folder lives under `Apps/<your-app-name>/`
737
+
738
+ ---
739
+
740
+ ## Deployment recommendations
741
+
742
+ If you are running OpenClaw on a cloud container (Fly.io, Railway, Render) or a VPS:
743
+
744
+ - **Use a separate persistent volume for the workspace.** Container root filesystems are ephemeral — a redeploy wipes everything. Mount a dedicated volume (e.g., Fly.io volumes, EBS, DigitalOcean block storage) at your workspace path so data survives deploys and restarts.
745
+ - **Enable daily volume snapshots.** Most cloud providers offer automated snapshots (Fly.io does this by default with 5-day retention). If something goes wrong — a bad sync, accidental deletion, or a failed reorganization — a recent snapshot lets you restore in minutes instead of rebuilding from scratch.
746
+ - **Test your restore process.** A backup you have never restored is a backup you do not have. Create a volume from a snapshot at least once to confirm the process works and you know the steps.
747
+ - **Use encrypted backups for off-site disaster recovery.** Volume snapshots protect against accidental deletes, but not against provider outages or account issues. Streaming encrypted backups to a separate provider (e.g., R2, B2) gives you a fully independent recovery path.
748
+
749
+ ## Security notes
750
+
751
+ - **Token storage**: rclone tokens are stored in `rclone.conf` with `0600` permissions
752
+ - **Sensitive files**: Don't sync secrets, API keys, or credentials
753
+ - **Encryption**: Backups support AES-256 client-side encryption. For sync, consider [rclone crypt](https://rclone.org/crypt/) for sensitive data.
754
+ - **App folder**: Use Dropbox app folder access for minimal permissions
755
+ - **Passphrase safety**: Use environment variables (`${BACKUP_PASSPHRASE}`) — never hardcode passphrases in config files
756
+
804
757
  ## Development
805
758
 
806
759
  ```bash