Workspace Sharing & Sync
Production-ready OpenClaw plugin for workspace sharing and real-time synchronization
Install
openclaw plugins install clawhub:@gauravprasadgp/openclaw-share-workspaceOpenClaw Workspace Sharing & Sync
A production-ready OpenClaw plugin for real-time workspace sharing, file synchronization, and access management — powered by MongoDB.
Multiple OpenClaw agents on different machines can share the same workspace: files created, updated, or deleted on one machine automatically appear (or disappear) on every other connected machine.
✨ Features
- Automatic two-way file sync — chokidar watches your local workspace directory; changes propagate to all connected peers in real time
- File create / update / delete — full lifecycle synced, not just state blobs
- Real-time delivery — MongoDB Change Streams (with polling fallback for standalone instances)
- Role-based access control — OWNER, EDITOR, VIEWER roles enforced on every operation
- Shareable access keys — invite collaborators without needing their user ID upfront; set expiry and max-use limits
- Optimistic concurrency — version-checked writes prevent silent conflicts
- Audit log — every action recorded with who did what and when
- Auto-start on plugin load — configure once, sync starts automatically every time the gateway restarts
📦 Installation
openclaw plugins install @gauravprasadgp/openclaw-share-workspace
⚙️ Configuration
Add the plugin config to ~/.openclaw/openclaw.json under plugins.entries:
Minimal (manual sync)
{
"plugins": {
"entries": {
"shared-workspace": {
"enabled": true,
"mongodbUri": "mongodb://localhost:27017"
}
}
}
}
Full (auto-start file sync on every gateway restart)
{
"plugins": {
"entries": {
"shared-workspace": {
"enabled": true,
"mongodbUri": "mongodb+srv://user:pass@cluster.mongodb.net/",
"dbName": "openclaw",
"syncProvider": "mongodb",
"pollIntervalMs": 3000,
"enableChangeStreams": true,
"autoSync": {
"enabled": true,
"workspaceId": "ws-001",
"userId": "agent-main",
"workspaceDir": "/Users/alice/.openclaw/workspace",
"debounceMs": 300,
"ignore": ["*.log", "tmp/**", "*.tmp"]
}
}
}
}
}
All configuration options
| Field | Type | Default | Description |
|---|---|---|---|
mongodbUri | string | — | MongoDB connection string. Falls back to MONGODB_URI env var |
dbName | string | "openclaw" | MongoDB database name |
syncProvider | "mongodb" | "mongodb" | Sync backend (only MongoDB supported today) |
pollIntervalMs | number | 3000 | Polling interval (ms) when change streams are unavailable. Min 1000 |
enableChangeStreams | boolean | true | Use MongoDB Change Streams for real-time delivery. Requires a replica set |
autoSync.enabled | boolean | false | Auto-start filesystem sync when the plugin loads |
autoSync.workspaceId | string | — | Which workspace to sync (must already exist in MongoDB) |
autoSync.userId | string | — | Author ID for outbound changes from this machine |
autoSync.workspaceDir | string | — | Absolute path of the local directory to watch |
autoSync.debounceMs | number | 300 | Wait this long after the last file event before syncing (prevents editor burst-saves sending many events) |
autoSync.ignore | string[] | [] | Extra glob patterns to ignore on top of the built-in list |
Built-in ignore list (always excluded, regardless of config):
node_modules/, .git/, dist/, .env*, *.log, package-lock.json, yarn.lock, pnpm-lock.yaml, .DS_Store
🚀 Use Cases
1 — Two agents on different machines sharing a workspace
Both machines configure autoSync pointing at the same workspaceId. After gateway restart on both:
Machine A edits src/agent.ts
→ FileSyncService detects change
→ uploads to MongoDB (file_update event)
→ Machine B receives event via Change Stream / polling
→ Machine B writes src/agent.ts to disk automatically
No manual steps after initial config.
2 — Invite a collaborator with an access key
The workspace owner generates a key with an expiry and role:
Tool: generate_access_key
workspaceId: "ws-001"
createdBy: "user-alice"
role: "EDITOR"
expiresInHours: 48
maxUses: 1
Share the returned key string with the collaborator. They join with:
Tool: join_workspace
key: "<key-string>"
userId: "user-bob"
Bob now has EDITOR access. No OWNER involvement needed at join time. Keys can be revoked at any time — already-joined users are not removed.
3 — Read-only observer
Share a workspace with role: VIEWER. Viewers can:
get_workspace,get_workspace_state,list_user_workspaces- Receive inbound file sync events (files written to their disk)
Viewers cannot write: create_workspace_file, update_workspace_file, delete_workspace_file, update_workspace_state all return ACCESS_DENIED.
4 — Selective sync with ignore patterns
Ignore build artifacts and secrets while syncing source:
"autoSync": {
"enabled": true,
"workspaceId": "ws-001",
"userId": "agent-main",
"workspaceDir": "/workspace",
"ignore": ["build/**", "*.secret", "coverage/**", ".cache/**"]
}
5 — On-demand sync without auto-start
If autoSync is not configured, use the tools directly:
Tool: start_file_sync
workspaceId: "ws-001"
userId: "agent-main"
workspaceDir: "/Users/alice/.openclaw/workspace"
debounceMs: 500
# ... when done ...
Tool: stop_file_sync
workspaceId: "ws-001"
userId: "agent-main"
6 — Audit who changed what
Tool: get_workspace_audit_log
workspaceId: "ws-001"
limit: 50
Returns a log of every FILE_CREATED, FILE_UPDATED, FILE_DELETED, WORKSPACE_SHARED, ACCESS_REVOKED, ACCESS_KEY_GENERATED, and more — with userId, timestamp, and changed fields.
🛠 Available Tools
Workspace management
| Tool | Who can call | Description |
|---|---|---|
create_workspace | Anyone | Create a new workspace |
get_workspace | OWNER, EDITOR, VIEWER | Get workspace metadata |
list_user_workspaces | Anyone | List all workspaces a user has access to |
get_workspace_users | OWNER | List all users and their roles |
Access control
| Tool | Who can call | Description |
|---|---|---|
share_workspace | OWNER | Grant a user a role directly |
revoke_workspace_access | OWNER | Remove a user's access |
generate_access_key | OWNER | Create a shareable invite key (EDITOR or VIEWER only) |
join_workspace | Anyone with key | Join via an access key |
list_access_keys | OWNER | List all keys and their usage |
revoke_access_key | OWNER | Invalidate a key (does not remove already-joined users) |
File sync
| Tool | Who can call | Description |
|---|---|---|
create_workspace_file | OWNER, EDITOR | Add a new file; broadcasts file_create to all peers |
update_workspace_file | OWNER, EDITOR | Overwrite a file; broadcasts file_update to all peers |
delete_workspace_file | OWNER, EDITOR | Remove a file; broadcasts file_delete to all peers |
start_file_sync | OWNER, EDITOR | Start automatic two-way filesystem ↔ workspace sync |
stop_file_sync | OWNER, EDITOR | Stop the filesystem watcher |
State & audit
| Tool | Who can call | Description |
|---|---|---|
get_workspace_state | OWNER, EDITOR, VIEWER | Get full workspace state (includes files array) |
update_workspace_state | OWNER, EDITOR | Shallow-merge arbitrary key/value pairs into state |
get_workspace_audit_log | OWNER | Paginated audit log |
🔄 How file sync works
┌─────────────────────────────────────────────────────┐
│ Machine A (OWNER/EDITOR) │
│ │
│ Local filesystem change (create/edit/delete) │
│ ↓ chokidar detects it (debounced 300ms) │
│ FileSyncService reads file content │
│ ↓ │
│ WorkspacePlugin stores in MongoDB workspace_states │
│ + inserts event into workspace_updates │
└──────────────────────┬──────────────────────────────┘
│ MongoDB Change Stream / polling
┌──────────────────────▼──────────────────────────────┐
│ Machine B (any role with connectSync) │
│ │
│ FileSyncService receives WorkspaceUpdate │
│ operationType = file_create / file_update │
│ → fs.writeFile(path, content) │
│ operationType = file_delete │
│ → fs.rm(path) │
│ │
│ Echo-loop guard: writes marked in-flight so the │
│ local watcher doesn't re-broadcast them back │
└─────────────────────────────────────────────────────┘
Conflict detection: every write accepts an optional expectedVersion. If the current version in MongoDB doesn't match, a ConflictError is thrown — no silent overwrites.
🗄 MongoDB collections
| Collection | Purpose |
|---|---|
workspaces | Workspace metadata (name, owner, timestamps) |
workspace_access | User ↔ workspace role assignments |
workspace_states | Current canonical state per workspace (includes files[]) |
workspace_updates | Append-only event log used for real-time sync fan-out |
workspace_keys | Access keys (expiry, use count, role, revoked flag) |
audit_logs | Full audit trail of all actions |
❓ Troubleshooting
Plugin skips initialization
⚠️ shared-workspace: skipping initialization because mongodbUri is not configured
Add mongodbUri to your config or export MONGODB_URI and restart the gateway.
autoSync fields warning
⚠️ shared-workspace: autoSync.enabled=true but missing fields: workspaceId, workspaceDir
All three fields (workspaceId, userId, workspaceDir) must be set for auto-start to work. The plugin still loads and all tools remain available.
Change streams not working
Set enableChangeStreams: false if your MongoDB is a standalone instance (not a replica set). The plugin will fall back to polling every pollIntervalMs ms automatically.
Files not appearing on the remote machine
- Confirm both machines are pointed at the same
workspaceIdand same MongoDB instance - Check that the receiving agent called
start_file_sync(or hasautoSyncconfigured) - Verify the userId on the receiving machine is different from the sender — the inbound handler skips its own updates
Version conflict errors
Pass expectedVersion only when you know the current version. Omit it to always overwrite regardless of the current version.
🔗 Links
- Registry: ClawHub Plugin Page
- OpenClaw docs: https://docs.openclaw.ai
- MongoDB Atlas (free tier): https://www.mongodb.com/atlas
