How OpenWork Cloud Synchronization Works: Desktop-to-Cloud Workspace Sync Explained
OpenWork synchronizes local and remote workspaces via an event-driven MCP protocol that pulls cloud state, migrates unsynced local data, and polls for incremental updates through dedicated HTTP endpoints.
OpenWork (the open-source workspace manager maintained by different-ai) implements a robust cloud synchronization mechanism that keeps desktop session groups consistent with remote cloud workspaces. The system uses a combination of client-side sync handlers and server-side MCP (Multiple Connection Protocol) routes to manage state merging, initial migrations, and real-time event polling.
The Cloud Sync Architecture
The synchronization mechanism relies on two primary components: a client-side sync handler that manages local state transitions, and server-side MCP endpoints that expose atomic operations for fetching, updating, and streaming workspace changes.
Client-Side Sync Handler (use-session-group-sync.ts)
Located at apps/app/src/react-app/shell/use-session-group-sync.ts, this handler orchestrates the desktop side of the sync process. It creates an endpoint reference via endpointForWorkspaceRef.current(workspace), initiates version tracking with beginSessionGroupServerSync(workspace.id), and executes the migration logic. The handler decides whether to upload existing local groups based on the migrateLocal flag and the presence of readMigrationComplete state.
Server-Side MCP Endpoints (cloud-mcp.ts)
The server implementation in apps/server/src/routes/cloud-mcp.ts exposes JSON-RPC style HTTP routes under the /cloud-mcp path. These endpoints implement provider actions that the desktop client consumes:
POST /cloud-mcp/state– Retrieves the current workspace state fromruntimeDb.getWorkspaceState(workspaceId).PUT /cloud-mcp/state– Persists local changes viaruntimeDb.saveWorkspaceState(workspaceId, state).POST /cloud-mcp/events– Returns incremental changes usingeventStore.getEvents(workspaceId, since).
Step-by-Step Synchronization Flow
When a workspace activates, the desktop app executes a four-phase synchronization protocol to ensure consistency between local SessionGroup data and the OpenWork Cloud.
1. Initialize the Sync Handler
The process begins when the React shell mounts the useSessionGroupSync hook for a specific RouteWorkspace. The handler acquires a version token from beginSessionGroupServerSync to track this sync attempt and establishes the MCP endpoint connection.
2. Pull Remote State
The client calls endpoint.client.getSessionGroups(endpoint.workspaceId), which maps to the server's POST /cloud-mcp/state route. This returns the canonical cloud state, which the client stores in the nextState variable. If the sync is cancelled mid-flight, the handler aborts to prevent partial updates.
3. Migrate Unsynced Local Session Groups
If the migrateLocal parameter is true and readMigrationComplete returns false—indicating a first-time sync—the handler checks for existing local data via localGroupStateForWorkspace. When hasGroupData confirms the cloud state is empty but local state exists, the client transforms local groups using serverStateFromWorkspaceState and uploads them via endpoint.client.putSessionGroups. After successful upload, writeMigrationComplete persists a flag to the workspace KV store to prevent redundant migrations.
4. Poll for Incremental Events
Following initial sync, the handler enters a polling loop against listSessionGroupEvents. New events trigger subsequent calls to getSessionGroups, allowing the desktop to merge remote changes incrementally without full-state transfers. The applySessionGroupServerState function reconciles these updates into the local UI state using the version token for optimistic concurrency.
Data Persistence and Storage Layer
The server persists synchronized data through a dedicated runtime database and workspace-scoped key-value storage.
Runtime Database (runtime-db.ts)
apps/server/src/runtime-db.ts provides the primary storage interface for cloud state. It implements getWorkspaceState and saveWorkspaceState, ensuring atomic writes of session group data. This layer isolates workspace state from other runtime concerns and supports the transactional semantics required for conflict-free synchronization.
Workspace KV Store and Migration Flags
apps/server/src/workspace-kv-store.ts manages metadata such as the migration-complete flag written by writeMigrationComplete. This key-value store tracks per-workspace synchronization metadata without polluting the main session group state, enabling the sync handler to idempotently determine whether initial migration has occurred.
Implementation Code Examples
The following excerpt from apps/app/src/react-app/shell/use-session-group-sync.ts demonstrates the client-side orchestration logic:
// apps/app/src/react-app/shell/use-session-group-sync.ts
const syncWorkspace = async (workspace: RouteWorkspace, migrateLocal: boolean) => {
const endpoint = endpointForWorkspaceRef.current(workspace);
if (!endpoint) return;
const version = beginSessionGroupServerSync(workspace.id);
// Pull the current state from the cloud
const response = await endpoint.client.getSessionGroups(endpoint.workspaceId);
if (cancelled) return;
let nextState = response.state;
const localState = localGroupStateForWorkspace(workspace, endpoint);
// Migrate any unsynced local groups to the cloud
if (migrateLocal && !readMigrationComplete(endpoint) && !hasGroupData(response.state) && localState !== undefined) {
const migrated = await endpoint.client.putSessionGroups(
endpoint.workspaceId,
serverStateFromWorkspaceState(localState)
);
nextState = migrated.state;
}
writeMigrationComplete(endpoint);
applySessionGroupServerState(workspace.id, nextState, version);
};
The server-side route implementation in apps/server/src/routes/cloud-mcp.ts handles the underlying RPC calls:
// apps/server/src/routes/cloud-mcp.ts
router.post("/cloud-mcp/state", async (req, res) => {
const { workspaceId } = req.body;
const state = await runtimeDb.getWorkspaceState(workspaceId);
res.json({ state });
});
router.put("/cloud-mcp/state", async (req, res) => {
const { workspaceId, state } = req.body;
await runtimeDb.saveWorkspaceState(workspaceId, state);
res.json({ success: true });
});
router.post("/cloud-mcp/events", async (req, res) => {
const { workspaceId, since } = req.body;
const events = await eventStore.getEvents(workspaceId, since);
res.json({ events });
});
Summary
- OpenWork Cloud synchronization uses an MCP-based protocol via the
/cloud-mcproutes to exchange session group state between desktop clients and the cloud. - The client-side handler (
use-session-group-sync.ts) manages versioned sync cycles, initial data migration, and event-driven updates. - Server endpoints (
cloud-mcp.ts) expose atomic fetch, save, and event-listening operations backed byruntime-db.ts. - Migration safety is enforced through the workspace KV store via
readMigrationCompleteandwriteMigrationComplete, ensuring local data uploads only occur once per workspace. - The system supports incremental synchronization by polling
listSessionGroupEventsand applying deltas viaapplySessionGroupServerState.
Frequently Asked Questions
How does OpenWork handle conflicts between local and remote workspace state?
OpenWork resolves conflicts through versioned synchronization tokens. The beginSessionGroupServerSync function generates a unique version identifier for each sync cycle. When applying updates via applySessionGroupServerState, the system validates this version against the current local state, ensuring that only the most recent cloud state overwrites local data, and preventing stale updates from clobbering newer changes.
What MCP endpoints manage cloud synchronization?
The synchronization protocol relies on three primary endpoints defined in apps/server/src/routes/cloud-mcp.ts: POST /cloud-mcp/state for retrieving workspace state, PUT /cloud-mcp/state for persisting local changes to the cloud, and POST /cloud-mcp/events for polling incremental updates. These endpoints implement the JSON-RPC interface that the desktop client consumes through methods like getSessionGroups and putSessionGroups.
Where is synchronized workspace state stored?
The canonical state resides in the runtime database managed by apps/server/src/runtime-db.ts, which provides getWorkspaceState and saveWorkspaceState methods. Migration metadata and sync flags are stored separately in the workspace KV store (workspace-kv-store.ts), allowing the system to track sync health and migration status independently from the session group data itself.
Does OpenWork support offline-first synchronization?
While the desktop app can operate on local state offline, the cloud synchronization mechanism requires an active connection to reach the MCP endpoints. The use-session-group-sync handler queues local changes and retries synchronization once connectivity restores, but the protocol itself is designed for online consistency via the eventStore polling mechanism rather than robust offline queueing with conflict resolution at reconnect.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →