openclaw-workspace-sync 2.3.0 → 2.4.0

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.md CHANGED
@@ -1,31 +1,107 @@
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
+ "interval": 180,
64
+ "onSessionStart": true,
65
+ "exclude": [".git/**", "node_modules/**", "*.log"]
66
+ },
67
+ "backup": {
68
+ "enabled": true,
69
+ "provider": "s3",
70
+ "bucket": "my-backups",
71
+ "prefix": "habibi/",
72
+ "interval": 86400,
73
+ "encrypt": true,
74
+ "passphrase": "${BACKUP_PASSPHRASE}",
75
+ "include": ["workspace", "config", "cron", "memory"],
76
+ "retain": 7
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ > **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.
86
+
87
+ ---
88
+
89
+ ## Sync
90
+
91
+ 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.
92
+
93
+ <p align="center">
94
+ <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" />
95
+ </p>
18
96
 
19
97
  <p align="center">
20
98
  <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
99
  </p>
22
100
 
23
- ## Sync modes (breaking change in v2.0)
101
+ ### Sync modes (breaking change in v2.0)
24
102
 
25
103
  **`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
104
 
27
- The plugin supports three sync modes. Choose the one that fits your workflow:
28
-
29
105
  | Mode | Direction | Description |
30
106
  |------|-----------|-------------|
31
107
  | `mailbox` | Push + inbox/outbox | Workspace pushes to cloud; users drop files in `_outbox` to send them to the agent. **Safest.** |
@@ -34,7 +110,7 @@ The plugin supports three sync modes. Choose the one that fits your workflow:
34
110
 
35
111
  **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
112
 
37
- ### `mailbox` mode (recommended)
113
+ #### `mailbox` mode (recommended)
38
114
 
39
115
  The agent workspace is the source of truth. Each sync cycle:
40
116
 
@@ -56,7 +132,7 @@ On startup, the plugin bootstraps both directories:
56
132
 
57
133
  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.
58
134
 
59
- #### Inbox notifications (optional)
135
+ ##### Inbox notifications (optional)
60
136
 
61
137
  By default, mailbox mode is silent — files land in `_inbox` without waking the agent. This keeps costs at zero.
62
138
 
@@ -73,13 +149,12 @@ This wakes the agent on its next heartbeat. The agent sees the message and can p
73
149
  "mode": "mailbox",
74
150
  "provider": "dropbox",
75
151
  "remotePath": "",
76
- "localPath": "/",
77
152
  "interval": 180,
78
153
  "notifyOnInbox": true
79
154
  }
80
155
  ```
81
156
 
82
- ### `mirror` mode
157
+ #### `mirror` mode
83
158
 
84
159
  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.
85
160
 
@@ -89,7 +164,7 @@ The agent workspace is the source of truth. Every sync cycle copies the latest w
89
164
 
90
165
  This is safe: even if something goes wrong, only your local copy is affected — the workspace stays untouched.
91
166
 
92
- ### `ingest` option (mirror mode only)
167
+ ##### `ingest` option (mirror mode only)
93
168
 
94
169
  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.
95
170
 
@@ -105,7 +180,7 @@ When enabled, a local `inbox/` folder syncs its contents to `<remotePath>/inbox/
105
180
 
106
181
  > 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.
107
182
 
108
- ### `bisync` mode (advanced)
183
+ #### `bisync` mode (advanced)
109
184
 
110
185
  Full bidirectional sync using rclone bisync. Changes on either side propagate to the other.
111
186
 
@@ -123,136 +198,7 @@ Use this only if you understand the trade-offs:
123
198
 
124
199
  If you are running on a container platform, `mailbox` mode is strongly recommended.
125
200
 
126
- ## Before your first sync
127
-
128
- Getting the initial state right prevents data loss. Each mode has different requirements:
129
-
130
- ### `mailbox` mode — starting state
131
-
132
- 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**.
133
-
134
- **Recommended starting state:** Local workspace is the source of truth (the agent has been writing here), or local and remote are already identical.
135
-
136
- **If remote is the source of truth** (e.g. you've been syncing manually or switching from another mode), pull first:
137
-
138
- ```bash
139
- rclone sync <remote>:<path> /data/workspace/ --config <config-path> \
140
- --exclude '**/.DS_Store' --exclude '**/.git/**' \
141
- --exclude '**/__pycache__/**' --exclude '**/node_modules/**' \
142
- --verbose
143
- ```
144
-
145
- Then verify local matches remote before enabling the plugin.
146
-
147
- ### `mirror` mode — starting state
148
-
149
- The first sync **pulls** from cloud to local. Local can be empty, stale, or corrupted — the pull simply overwrites it. **No preparation needed.**
150
-
151
- ### `bisync` mode — starting state
152
-
153
- The first sync requires `--resync`, which copies everything from both sides to the other. Any stale or unwanted files on either side will propagate.
154
-
155
- **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`.
156
-
157
- ### General first-sync checklist
158
-
159
- 1. Run a `--dry-run` first to see what would happen: `openclaw workspace-sync sync --dry-run`
160
- 2. Check the output for unexpected deletions
161
- 3. If everything looks right, run the actual sync
162
- 4. Only then enable periodic sync (`interval` in config)
163
-
164
- > For maintenance, recovery, and common problems, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md).
165
-
166
- ## Setup sequence
167
-
168
- Getting sync right depends on doing things in the right order. Follow these steps:
169
-
170
- 1. **Configure the plugin** in `openclaw.json` with your provider credentials and `mode`
171
- 2. **Verify the remote** is accessible: `openclaw workspace-sync status`
172
- 3. **Run a dry-run first** to see what would happen: `openclaw workspace-sync sync --dry-run`
173
- 4. **Run the first sync**: `openclaw workspace-sync sync`
174
- - In `mailbox` mode, this pushes the workspace and drains the `_outbox`
175
- - In `mirror` mode, this pulls the current workspace down
176
- - In `bisync` mode, this requires `--resync` to establish the baseline
177
- 5. **Enable periodic sync** by setting `interval` in your config
178
-
179
- Take care when changing config (switching `remotePath`, `localPath`, or `mode`) — always disable periodic sync first, verify the new paths, then re-enable.
180
-
181
- ## Install
182
-
183
- ```bash
184
- openclaw plugins install openclaw-workspace-sync
185
- ```
186
-
187
- Or clone into your extensions directory:
188
-
189
- ```bash
190
- cd ~/.openclaw/extensions
191
- git clone https://github.com/ashbrener/openclaw-workspace-sync workspace-sync
192
- cd workspace-sync && npm install --omit=dev
193
- ```
194
-
195
- ## Quick start
196
-
197
- ```bash
198
- # Interactive setup wizard (recommended)
199
- openclaw workspace-sync setup
200
- ```
201
-
202
- The setup wizard guides you through:
203
- 1. Checking/installing rclone
204
- 2. Selecting cloud provider
205
- 3. Choosing sync mode
206
- 4. Dropbox app folder option (for scoped access)
207
- 5. Background sync interval
208
- 6. OAuth authorization
209
- 7. First sync
210
-
211
- Or configure manually — see [Configuration](#configuration) below.
212
-
213
- ## Configuration
214
-
215
- Add to your `openclaw.json`:
216
-
217
- ```json
218
- {
219
- "plugins": {
220
- "entries": {
221
- "openclaw-workspace-sync": {
222
- "enabled": true,
223
- "config": {
224
- "sync": {
225
- "provider": "dropbox",
226
- "mode": "mailbox",
227
- "remotePath": "",
228
- "localPath": "/",
229
- "interval": 60,
230
- "timeout": 1800,
231
- "onSessionStart": true,
232
- "onSessionEnd": false,
233
- "exclude": [".git/**", "node_modules/**", "*.log"]
234
- },
235
- "backup": {
236
- "enabled": true,
237
- "provider": "s3",
238
- "bucket": "my-backups",
239
- "prefix": "habibi/",
240
- "interval": 86400,
241
- "encrypt": true,
242
- "passphrase": "${BACKUP_PASSPHRASE}",
243
- "include": ["workspace", "config", "cron", "memory"],
244
- "retain": 7
245
- }
246
- }
247
- }
248
- }
249
- }
250
- }
251
- ```
252
-
253
- > **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.
254
-
255
- ### Config reference
201
+ ### Sync config reference
256
202
 
257
203
  | Key | Type | Default | Description |
258
204
  |-----|------|---------|-------------|
@@ -262,7 +208,7 @@ Add to your `openclaw.json`:
262
208
  | `ingestPath` | string | `"inbox"` | Local subfolder name for ingestion (relative to `localPath`) |
263
209
  | `notifyOnInbox` | boolean | `false` | Wake the agent when files arrive in `_inbox` (mailbox mode). Off by default — enabling this costs LLM credits per notification. |
264
210
  | `remotePath` | string | `"openclaw-share"` | Folder name in cloud storage |
265
- | `localPath` | string | `"shared"` | Subfolder within workspace to sync |
211
+ | `localPath` | string | `""` (workspace root) | Relative subfolder within the workspace to sync. Defaults to the workspace root (e.g. `/data/workspace`). Must be a relative path — absolute paths like `"/"` are rejected. Set to a subfolder name like `"shared"` to sync only that directory. |
266
212
  | `interval` | number | `0` | Background sync interval in seconds (0 = manual only, min 60) |
267
213
  | `timeout` | number | `1800` | Max seconds for a single rclone sync operation (min 60) |
268
214
  | `onSessionStart` | boolean | `false` | Sync when an agent session begins |
@@ -275,93 +221,7 @@ Add to your `openclaw.json`:
275
221
 
276
222
  Default excludes: `**/.DS_Store`
277
223
 
278
- ### Provider-specific options
279
-
280
- **Dropbox with app folder (recommended for security):**
281
-
282
- ```json
283
- {
284
- "provider": "dropbox",
285
- "remotePath": "",
286
- "dropbox": {
287
- "appFolder": true,
288
- "appKey": "your-app-key",
289
- "appSecret": "your-app-secret",
290
- "token": "{\"access_token\":\"...\"}"
291
- }
292
- }
293
- ```
294
-
295
- 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."
296
-
297
- **Google Drive:**
298
-
299
- ```json
300
- {
301
- "provider": "gdrive",
302
- "remotePath": "openclaw-sync",
303
- "gdrive": {
304
- "token": "{\"access_token\":\"...\"}",
305
- "teamDrive": "0ABcDeFgHiJ",
306
- "rootFolderId": "folder-id"
307
- }
308
- }
309
- ```
310
-
311
- `teamDrive` and `rootFolderId` are optional — omit them for personal Google Drive.
312
-
313
- **OneDrive:**
314
-
315
- ```json
316
- {
317
- "provider": "onedrive",
318
- "remotePath": "openclaw-sync",
319
- "onedrive": {
320
- "token": "{\"access_token\":\"...\"}",
321
- "driveId": "drive-id",
322
- "driveType": "business"
323
- }
324
- }
325
- ```
326
-
327
- `driveType` can be `personal`, `business`, or `sharepoint`. Both fields are optional.
328
-
329
- **S3 / Cloudflare R2 / Minio:**
330
-
331
- ```json
332
- {
333
- "provider": "s3",
334
- "remotePath": "openclaw-sync",
335
- "s3": {
336
- "endpoint": "https://s3.us-east-1.amazonaws.com",
337
- "bucket": "your-bucket",
338
- "region": "us-east-1",
339
- "accessKeyId": "AKID...",
340
- "secretAccessKey": "SECRET..."
341
- }
342
- }
343
- ```
344
-
345
- **Any rclone backend (SFTP, B2, Mega, pCloud, etc.):**
346
-
347
- ```json
348
- {
349
- "provider": "custom",
350
- "remotePath": "openclaw-sync",
351
- "custom": {
352
- "rcloneType": "sftp",
353
- "rcloneOptions": {
354
- "host": "example.com",
355
- "user": "deploy",
356
- "key_file": "/path/to/key"
357
- }
358
- }
359
- }
360
- ```
361
-
362
- 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`.
363
-
364
- ## CLI commands
224
+ ### Sync CLI commands
365
225
 
366
226
  ```bash
367
227
  # Interactive setup wizard
@@ -391,9 +251,9 @@ openclaw workspace-sync authorize --provider gdrive
391
251
  openclaw workspace-sync list
392
252
  ```
393
253
 
394
- ## Auto-sync
254
+ ### Auto-sync
395
255
 
396
- ### Session hooks
256
+ #### Session hooks
397
257
 
398
258
  Sync automatically when sessions start or end. These run during existing agent activity and incur zero LLM cost:
399
259
 
@@ -404,7 +264,7 @@ Sync automatically when sessions start or end. These run during existing agent a
404
264
  }
405
265
  ```
406
266
 
407
- ### Periodic background sync
267
+ #### Periodic background sync
408
268
 
409
269
  Set `interval` to enable automatic background sync (in seconds):
410
270
 
@@ -419,72 +279,54 @@ The gateway runs sync in the background at this interval. Minimum interval is 60
419
279
 
420
280
  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.
421
281
 
422
- ### External cron (alternative)
282
+ #### External cron (alternative)
423
283
 
424
284
  ```bash
425
285
  # Add to crontab (crontab -e)
426
286
  */5 * * * * openclaw workspace-sync sync >> /var/log/openclaw-sync.log 2>&1
427
287
  ```
428
288
 
429
- ## Supported providers
289
+ ### Before your first sync
430
290
 
431
- | Provider | Config value | Auth method | Config-driven |
432
- |----------|-------------|-------------|---------------|
433
- | Dropbox | `dropbox` | OAuth token | Full (token, appKey, appSecret, appFolder) |
434
- | Google Drive | `gdrive` | OAuth token | Full (token, teamDrive, rootFolderId) |
435
- | OneDrive | `onedrive` | OAuth token | Full (token, driveId, driveType) |
436
- | S3/R2/Minio | `s3` | Access keys | Full (endpoint, bucket, region, credentials) |
437
- | Any rclone backend | `custom` | Varies | Full (rcloneType + rcloneOptions) |
438
-
439
- 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.).
291
+ Getting the initial state right prevents data loss. Each mode has different requirements:
440
292
 
441
- ## Manual setup (without wizard)
293
+ #### `mailbox` mode starting state
442
294
 
443
- If you prefer to skip the interactive wizard, configure the plugin in `openclaw.json` and use the CLI:
295
+ 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**.
444
296
 
445
- ```bash
446
- # 1. Authorize with your cloud provider
447
- openclaw workspace-sync authorize --provider dropbox
297
+ **Recommended starting state:** Local workspace is the source of truth (the agent has been writing here), or local and remote are already identical.
448
298
 
449
- # 2. Run a dry-run to preview what will sync
450
- openclaw workspace-sync sync --dry-run
299
+ **If remote is the source of truth** (e.g. you've been syncing manually or switching from another mode), pull first:
451
300
 
452
- # 3. Run the first sync
453
- openclaw workspace-sync sync
301
+ ```bash
302
+ rclone sync <remote>:<path> /data/workspace/ --config <config-path> \
303
+ --exclude '**/.DS_Store' --exclude '**/.git/**' \
304
+ --exclude '**/__pycache__/**' --exclude '**/node_modules/**' \
305
+ --verbose
454
306
  ```
455
307
 
456
- The plugin handles rclone installation, config generation, and token storage automatically based on your `openclaw.json` settings.
308
+ Then verify local matches remote before enabling the plugin.
457
309
 
458
- ## Dropbox app folder access (recommended)
310
+ #### `mirror` mode starting state
459
311
 
460
- For better security, create a scoped Dropbox app that only accesses a single folder:
312
+ The first sync **pulls** from cloud to local. Local can be empty, stale, or corrupted the pull simply overwrites it. **No preparation needed.**
461
313
 
462
- 1. Go to [Dropbox App Console](https://www.dropbox.com/developers/apps)
463
- 2. Click **Create app** > **Scoped access** > **App folder**
464
- 3. Name it (e.g., `openclaw-sync`)
465
- 4. In **Settings** tab, add a **Redirect URI**: `http://localhost:53682/`
466
- - This is required for rclone's OAuth flow to work. Without it, Dropbox returns "Invalid redirect_uri" during authorization.
467
- 5. In **Permissions** tab, enable:
468
- - `files.metadata.read` / `files.metadata.write`
469
- - `files.content.read` / `files.content.write`
470
- 6. Copy **App key** and **App secret** from Settings
314
+ #### `bisync` mode starting state
471
315
 
472
- > **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."
316
+ The first sync requires `--resync`, which copies everything from both sides to the other. Any stale or unwanted files on either side will propagate.
473
317
 
474
- Benefits:
475
- - Token only accesses one folder, not your entire Dropbox
476
- - If token is compromised, blast radius is limited
477
- - Clean separation — sync folder lives under `Apps/<your-app-name>/`
318
+ **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`.
478
319
 
479
- ### Dropbox rate limiting
320
+ #### General first-sync checklist
480
321
 
481
- 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:
322
+ 1. Run a `--dry-run` first to see what would happen: `openclaw workspace-sync sync --dry-run`
323
+ 2. Check the output for unexpected deletions
324
+ 3. If everything looks right, run the actual sync
325
+ 4. Only then enable periodic sync (`interval` in config)
482
326
 
483
- - **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.
484
- - **Use `exclude` patterns liberally** — skip `node_modules`, `.git`, `__pycache__`, build output, and anything you don't need synced. Fewer files = fewer API calls.
485
- - **If you see `too_many_requests` errors** in the logs, increase the interval and add more excludes.
327
+ > For maintenance, recovery, and common problems, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md).
486
328
 
487
- ## Understanding sync safety
329
+ ### Sync safety
488
330
 
489
331
  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:
490
332
 
@@ -495,6 +337,7 @@ Cloud sync involves two copies of your data. When things go wrong, one side can
495
337
  **Bisync requires both sides to agree.** Bisync tracks what changed since the last sync. If that tracking state is lost (deploy, disk wipe, moving to a new machine), rclone does not know what changed and requires a `--resync`. A resync copies everything from both sides — if one side has stale or unwanted files, they propagate to the other.
496
338
 
497
339
  **Common pitfalls to avoid:**
340
+ - Setting `localPath` to an absolute path like `"/"` — this syncs your entire filesystem, not your workspace. The plugin now rejects absolute paths with a clear error. Use `""` for the workspace root or a relative subfolder like `"shared"`.
498
341
  - Changing `remotePath` or `localPath` while periodic sync is enabled
499
342
  - Running `--resync` without checking both sides first
500
343
  - Using `bisync` on container platforms where state is ephemeral
@@ -504,7 +347,7 @@ Cloud sync involves two copies of your data. When things go wrong, one side can
504
347
 
505
348
  > For recovery procedures, mode switching, and maintenance tips, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md).
506
349
 
507
- ## Important: `--resync` is destructive (bisync only)
350
+ #### Important: `--resync` is destructive (bisync only)
508
351
 
509
352
  **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:
510
353
 
@@ -519,15 +362,15 @@ Normal bisync (without `--resync`) only transfers files that changed since the l
519
362
  openclaw workspace-sync sync --resync
520
363
  ```
521
364
 
522
- ## Troubleshooting
365
+ ### Sync troubleshooting
523
366
 
524
- ### Token expired
367
+ #### Token expired
525
368
 
526
369
  ```bash
527
370
  openclaw workspace-sync authorize
528
371
  ```
529
372
 
530
- ### Conflicts (bisync only)
373
+ #### Conflicts (bisync only)
531
374
 
532
375
  Files modified on both sides get a `.conflict` suffix. The winner is determined by `conflictResolve` (default: `newer`). To find conflict files:
533
376
 
@@ -535,7 +378,7 @@ Files modified on both sides get a `.conflict` suffix. The winner is determined
535
378
  find <workspace>/shared -name "*.conflict"
536
379
  ```
537
380
 
538
- ### Stale lock files
381
+ #### Stale lock files
539
382
 
540
383
  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.
541
384
 
@@ -545,7 +388,7 @@ If you still see lock errors, you can manually clear them:
545
388
  rclone deletefile ~/.cache/rclone/bisync/<lockfile>.lck
546
389
  ```
547
390
 
548
- ### Sync times out
391
+ #### Sync times out
549
392
 
550
393
  Increase the `timeout` config (in seconds). The default is 1800 (30 min). For large workspaces:
551
394
 
@@ -555,28 +398,21 @@ Increase the `timeout` config (in seconds). The default is 1800 (30 min). For la
555
398
  }
556
399
  ```
557
400
 
558
- ### Permission errors
401
+ #### Permission errors
559
402
 
560
403
  ```bash
561
404
  chmod -R 755 <workspace>/shared
562
405
  ```
563
406
 
564
- ## Deployment recommendations
565
-
566
- If you are running OpenClaw on a cloud container (Fly.io, Railway, Render) or a VPS:
407
+ #### Dropbox rate limiting
567
408
 
568
- - **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.
569
- - **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.
570
- - **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.
571
-
572
- These recommendations apply regardless of whether you use this plugin. Cloud sync adds convenience but is not a substitute for proper backups.
409
+ 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:
573
410
 
574
- ## Security notes
411
+ - **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.
412
+ - **Use `exclude` patterns liberally** — skip `node_modules`, `.git`, `__pycache__`, build output, and anything you don't need synced. Fewer files = fewer API calls.
413
+ - **If you see `too_many_requests` errors** in the logs, increase the interval and add more excludes.
575
414
 
576
- - **Token storage**: rclone tokens are stored in `rclone.conf` with `0600` permissions
577
- - **Sensitive files**: Don't sync secrets, API keys, or credentials
578
- - **Encryption**: Consider [rclone crypt](https://rclone.org/crypt/) for sensitive data
579
- - **App folder**: Use Dropbox app folder access for minimal permissions
415
+ ---
580
416
 
581
417
  ## Encrypted backups
582
418
 
@@ -595,32 +431,6 @@ Back up your entire agent system — workspace, config, cron jobs, memory, sessi
595
431
 
596
432
  > **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.
597
433
 
598
- ### Configuration
599
-
600
- 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:
601
-
602
- ```json
603
- {
604
- "sync": {
605
- "provider": "dropbox",
606
- "mode": "mailbox",
607
- "remotePath": "",
608
- "interval": 180
609
- },
610
- "backup": {
611
- "enabled": true,
612
- "provider": "s3",
613
- "bucket": "my-backups",
614
- "prefix": "habibi/",
615
- "interval": 86400,
616
- "encrypt": true,
617
- "passphrase": "${BACKUP_PASSPHRASE}",
618
- "include": ["workspace", "config", "cron", "memory"],
619
- "retain": { "daily": 7, "weekly": 4 }
620
- }
621
- }
622
- ```
623
-
624
434
  ### Backup config reference
625
435
 
626
436
  | Key | Type | Default | Description |
@@ -656,7 +466,7 @@ Add `sync` and `backup` blocks to your plugin config. The backup provider can di
656
466
 
657
467
  Default: `["workspace", "config", "cron", "memory"]`
658
468
 
659
- ### CLI commands
469
+ ### Backup CLI commands
660
470
 
661
471
  ```bash
662
472
  # Create a backup now
@@ -682,7 +492,7 @@ openclaw workspace-sync backup status
682
492
 
683
493
  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.
684
494
 
685
- ### Provider examples
495
+ ### Backup provider examples
686
496
 
687
497
  **Cloudflare R2 (free tier: 10GB):**
688
498
 
@@ -743,6 +553,148 @@ By default, `restore` extracts to a staging directory (`~/.openclaw/.backup-rest
743
553
  }
744
554
  ```
745
555
 
556
+ ---
557
+
558
+ ## Provider-specific options
559
+
560
+ These provider blocks work for both sync and backup. Place them inside the `sync` or `backup` config block as needed.
561
+
562
+ **Dropbox with app folder (recommended for security):**
563
+
564
+ ```json
565
+ {
566
+ "provider": "dropbox",
567
+ "remotePath": "",
568
+ "dropbox": {
569
+ "appFolder": true,
570
+ "appKey": "your-app-key",
571
+ "appSecret": "your-app-secret",
572
+ "token": "{\"access_token\":\"...\"}"
573
+ }
574
+ }
575
+ ```
576
+
577
+ 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."
578
+
579
+ **Google Drive:**
580
+
581
+ ```json
582
+ {
583
+ "provider": "gdrive",
584
+ "remotePath": "openclaw-sync",
585
+ "gdrive": {
586
+ "token": "{\"access_token\":\"...\"}",
587
+ "teamDrive": "0ABcDeFgHiJ",
588
+ "rootFolderId": "folder-id"
589
+ }
590
+ }
591
+ ```
592
+
593
+ `teamDrive` and `rootFolderId` are optional — omit them for personal Google Drive.
594
+
595
+ **OneDrive:**
596
+
597
+ ```json
598
+ {
599
+ "provider": "onedrive",
600
+ "remotePath": "openclaw-sync",
601
+ "onedrive": {
602
+ "token": "{\"access_token\":\"...\"}",
603
+ "driveId": "drive-id",
604
+ "driveType": "business"
605
+ }
606
+ }
607
+ ```
608
+
609
+ `driveType` can be `personal`, `business`, or `sharepoint`. Both fields are optional.
610
+
611
+ **S3 / Cloudflare R2 / Minio:**
612
+
613
+ ```json
614
+ {
615
+ "provider": "s3",
616
+ "remotePath": "openclaw-sync",
617
+ "s3": {
618
+ "endpoint": "https://s3.us-east-1.amazonaws.com",
619
+ "bucket": "your-bucket",
620
+ "region": "us-east-1",
621
+ "accessKeyId": "AKID...",
622
+ "secretAccessKey": "SECRET..."
623
+ }
624
+ }
625
+ ```
626
+
627
+ **Any rclone backend (SFTP, B2, Mega, pCloud, etc.):**
628
+
629
+ ```json
630
+ {
631
+ "provider": "custom",
632
+ "remotePath": "openclaw-sync",
633
+ "custom": {
634
+ "rcloneType": "sftp",
635
+ "rcloneOptions": {
636
+ "host": "example.com",
637
+ "user": "deploy",
638
+ "key_file": "/path/to/key"
639
+ }
640
+ }
641
+ }
642
+ ```
643
+
644
+ 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`.
645
+
646
+ ### Supported providers
647
+
648
+ | Provider | Config value | Auth method | Config-driven |
649
+ |----------|-------------|-------------|---------------|
650
+ | Dropbox | `dropbox` | OAuth token | Full (token, appKey, appSecret, appFolder) |
651
+ | Google Drive | `gdrive` | OAuth token | Full (token, teamDrive, rootFolderId) |
652
+ | OneDrive | `onedrive` | OAuth token | Full (token, driveId, driveType) |
653
+ | S3/R2/Minio | `s3` | Access keys | Full (endpoint, bucket, region, credentials) |
654
+ | Any rclone backend | `custom` | Varies | Full (rcloneType + rcloneOptions) |
655
+
656
+ 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.).
657
+
658
+ ### Dropbox app folder access (recommended)
659
+
660
+ For better security, create a scoped Dropbox app that only accesses a single folder:
661
+
662
+ 1. Go to [Dropbox App Console](https://www.dropbox.com/developers/apps)
663
+ 2. Click **Create app** > **Scoped access** > **App folder**
664
+ 3. Name it (e.g., `openclaw-sync`)
665
+ 4. In **Settings** tab, add a **Redirect URI**: `http://localhost:53682/`
666
+ - This is required for rclone's OAuth flow to work. Without it, Dropbox returns "Invalid redirect_uri" during authorization.
667
+ 5. In **Permissions** tab, enable:
668
+ - `files.metadata.read` / `files.metadata.write`
669
+ - `files.content.read` / `files.content.write`
670
+ 6. Copy **App key** and **App secret** from Settings
671
+
672
+ > **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."
673
+
674
+ Benefits:
675
+ - Token only accesses one folder, not your entire Dropbox
676
+ - If token is compromised, blast radius is limited
677
+ - Clean separation — sync folder lives under `Apps/<your-app-name>/`
678
+
679
+ ---
680
+
681
+ ## Deployment recommendations
682
+
683
+ If you are running OpenClaw on a cloud container (Fly.io, Railway, Render) or a VPS:
684
+
685
+ - **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.
686
+ - **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.
687
+ - **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.
688
+ - **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.
689
+
690
+ ## Security notes
691
+
692
+ - **Token storage**: rclone tokens are stored in `rclone.conf` with `0600` permissions
693
+ - **Sensitive files**: Don't sync secrets, API keys, or credentials
694
+ - **Encryption**: Backups support AES-256 client-side encryption. For sync, consider [rclone crypt](https://rclone.org/crypt/) for sensitive data.
695
+ - **App folder**: Use Dropbox app folder access for minimal permissions
696
+ - **Passphrase safety**: Use environment variables (`${BACKUP_PASSPHRASE}`) — never hardcode passphrases in config files
697
+
746
698
  ## Development
747
699
 
748
700
  ```bash