Sync
Sync is not a feature you switch on to back up local files. It is the storage: every note, archive, pin, and your settings document live in an encrypted cloud workspace, and the app works against a decrypted in-memory copy of that workspace. There is no local workspace directory holding a second copy (epic #4204).
This is the same on the desktop app and in the browser. Neither is the "real" one that the other syncs from.
Getting connected
You do not configure sync before using it — you connect a workspace, and the app starts. The first launch walks you through signing in, creating a workspace or picking an existing one, and unlocking it with your master password. That flow is documented in full on Cloud-first onboarding; everything below assumes you are past it.
The one thing worth repeating here: each app instance is bound to exactly one workspace. The ROOT app, each generated text app, and each browser origin each hold their own binding, so having several workspaces on one account is the normal shape — one per text app.
What lives in the workspace
Everything the app manages:
| Content | Workspace path |
|---|---|
| Notes | inbox/ |
| Archives | archives/ |
| Pins | pins/… |
| Trash | .trash/… |
| Settings | .zudotext.settings.json |
| Frontmatter schema, skills | .zudotext/… |
The External File Editor deliberately stays outside the workspace and reads your real filesystem instead. Files you open through it are never copied into your workspace — that is the point of it.
Attachments use the same zero-knowledge boundary as workspace documents. The app encrypts an asset's filename and bytes before upload; the server stores an opaque name token and an encrypted byte envelope and does not receive the plaintext name, contents, or MIME type. MIME and image/file classification are derived on the client after the filename is decrypted.
Assets remain a separate cloud storage surface rather than workspace documents. Their deterministic encrypted names reveal when two filenames in one workspace are equal, and token length tracks the filename's UTF-8 byte length; the server also observes encrypted byte size, upload timing, and read/delete access patterns. See Sync Architecture for the complete contract and cryptographic caveat.
Your settings follow you
.zudotext.settings.json is a workspace document, so colors, editor options, shortcuts, framesets, and pins are identical on every device signed into that workspace.
The document is pushed whole. If two devices change different settings at the same moment, the one that saves last wins and the other device's change is lost. In practice settings are only written while a settings dialog is open, so this rarely bites. Anything that genuinely should differ per machine belongs in a device override instead.
Sync status
A small indicator appears in the toolbar. Clicking it opens a details panel showing the current state and recent activity.
| Indicator state | Meaning |
|---|---|
| Muted dot | Idle — up to date |
| Pulsing accent dot | Syncing in progress |
| Steady accent dot | Last sync succeeded |
| Muted dot with ring | Error |
| Offline icon | Signed out or offline |
To push and pull immediately rather than waiting for the 10-second quiet window, use Sync Now from the command palette (Mod+K). During continuous editing, the outbox starts a flush after at most 60 seconds of deferral.
Real-time sync
With Real-time sync enabled (Settings → Sync), the app holds a WebSocket to the sync server and changes from your other devices land as they happen. With it disabled, changes only move when a save triggers a push or you run Sync Now.
The toggle only takes effect on the desktop app. The browser build hides it and shows a note instead — real-time is unconditional there, because there is no local fallback to fall back to.
Conflicts
Concurrent edits to the same note from two devices are resolved last-writer-wins. The pull response also applies a self-device filter, so changes your own device pushed are not echoed back to you.
Offline behavior
Be aware of what does and does not hold when the network drops:
Holds:
Saving works and survives a restart. Writes go into a durable outbox — encrypted, persisted, and retried with backoff — so a save succeeds even with no connection.
Deleting works and survives a restart. Delete tombstones go through the same durable outbox as saves, so a delete made offline is not lost by a restart before you reconnect.
Reading works entirely offline once the app has started. The in-memory workspace model serves every read; nothing goes to the network.
Starting the app works offline, as long as it has started online at least once on this device. Each device keeps an encrypted local copy of your workspace (the "workspace mirror") on disk, kept current as you read and write — not just refreshed on reconnect. A cold launch with no network seeds the in-memory model from that local copy instead of the server, so you can open and edit your workspace with no connection at all. Files created or deleted offline stay visible across a restart.
Reconnecting resolves conflicts safely. An edit you made offline is never silently discarded once a delta from another device arrives; a file someone else deleted on another device while you were offline is respected too, rather than being resurrected by your own queued edit. See Encrypted Local Workspace Mirror for the exact rules.
Does not hold (accepted limitation):
The very first launch on a device, or a launch right after signing out, still needs the network. With no prior successful online session there is no local copy yet to seed from — the app shows a blocking "offline" screen with a retry until connectivity returns.
Once a device has opened your workspace online at least once, it can start fully offline from then on — signing out clears the local copy along with your key, so the next sign-in needs the network again for its first launch.
Settings → Sync
The Sync tab contains behaviour preferences. Runtime connection identity is not stored in settings: the workspace id comes from this app instance's binding, encryption readiness from the armed sync bridge, and the server URL from runtime bootstrap configuration. Better Auth authority is likewise build configuration.
| Field | Description |
|---|---|
| Device Name | A human-readable name for this device in the sync network |
| Real-time sync | WebSocket-based live sync (see above); hidden in the browser build (always on there) |
Sync requires an active subscription. New accounts get a 30-day trial automatically, so this is invisible until the trial ends.
Sync history
A sync log at the bottom of the Sync settings tab shows recent operations with timestamps and file counts. It is the first place to look when the status indicator shows an error.