File Synchronization
Relevant source files
The following files were used as context for generating this wiki page:
File Synchronization in OpenWork is the mechanism responsible for monitoring workspace files and ensuring that the underlying OpenCode engine and the user interface stay in sync with the current state of the filesystem. It primary role is to detect changes in configuration, agents, skills, and commands, triggering necessary "Reload required" events when runtime adjustments are needed.
This system is built on a "local-first" philosophy where the server watches specific directories (like .opencode/) and uses content-based fingerprints to suppress unnecessary noise, ensuring that only meaningful changes prompt a system reload.
Architecture and Components
The synchronization system consists of a watcher service, a content fingerprinting logic, and an event store that bridges the gap between the filesystem and the client UI.
Reload Watcher Service
The ReloadWatcher is the core service that orchestrates filesystem monitoring across multiple workspaces. It uses a debounced watching strategy to handle rapid-fire file writes (such as those from an IDE or automated tool).
The diagram shows how filesystem changes are processed through the watcher logic before being stored as events for the UI.
Sources: apps/server/src/reload-watcher.ts, apps/server/src/server.ts:1143-1150
Key Functions and Structures
| Component | Description |
|---|---|
startReloadWatchers | Initializes the watcher service for all configured workspaces. |
computeReloadFingerprint | Generates a hash based on the content of watched files to detect actual changes. |
ReloadEventStore | An in-memory store that holds events until they are consumed by the UI. |
ensureWorkspaceFiles | Bootstraps essential files into a new workspace root. |
Sources: apps/server/src/reload-watcher.ts:44, apps/server/src/workspace-init.ts:187
Data Flow and Synchronization Logic
The synchronization process follows a specific lifecycle to prevent "Reload required" spam, especially during initial workspace bootstrap or no-op writes.
Change Detection Lifecycle
- Detection: The watcher identifies a change in a watched path (e.g.,
opencode.jsoncor files within.opencode/skills/). - Validation: The system calculates a new fingerprint for the changed scope. If the new fingerprint matches the baseline fingerprint, the event is suppressed.
- Recording: If the fingerprint differs, a
ReloadReason(e.g.,config,skills,agents,mcp) is recorded in theReloadEventStore. - Notification: The UI polls the
/workspace/:id/eventsendpoint. If new events exist, it displays a "Reload required" toast.
The sequence illustrates the content-validation step that prevents identical writes from triggering reloads.
Sources: apps/server/src/reload-watcher.ts:88-120, apps/server/src/reload-watcher.test.ts:40-57, evals/reload-events-flow.md
Suppression of Internal Writes
During the initial workspace setup or "bootstrap," OpenWork writes default configuration and agent files. To prevent a "Reload required" banner from appearing immediately upon creating a workspace, the system uses refreshWorkspace with specific ReloadReason exclusions to update the baseline fingerprint after internal writes.
Sources: apps/server/src/reload-watcher.ts:32-35, apps/server/src/reload-watcher.test.ts:79-93
Watched Paths and Scopes
The system specifically targets files that affect the behavior of the OpenCode engine.
| Scope | Files/Directories Watched |
|---|---|
| Config | opencode.json, opencode.jsonc, .opencode/opencode.jsonc |
| Skills | .opencode/skills/**, .claude/skills/**, ~/.agents/skills/** |
| Agents | .opencode/agents/** |
| Commands | .opencode/commands/** |
Sources: apps/server/src/workspace-files.ts:5-15, apps/server/src/reload-watcher.ts:44-53
API Integration
The file synchronization state is exposed to the client through the server's REST API.
Endpoint: GET /workspace/:id/events
This endpoint allows the UI to fetch the current synchronization status and any pending reload triggers.
- Parameters:
id: The workspace ID.since(optional): A timestamp cursor to fetch only new events.
- Response:
items: Array ofReloadEventobjects.cursor: The current event store cursor.
Sources: apps/server/src/server.ts:1143-1150
Conclusion
File synchronization in OpenWork ensures a tight loop between the user's filesystem and the agentic execution environment. By utilizing content-based fingerprinting and debounced monitoring, it provides a stable experience that identifies when the OpenCode engine needs a manual reload without being disrupted by non-functional file system noise.