Hyperclay Local
  1. Hyperclay Local
  2. Guide
  3. Sync with hyperclay.com

Sync with hyperclay.com

Connect an API key to sync your personal folder and team folders two ways with hyperclay.com.

Cloud sync keeps your local folders and your hyperclay.com account in sync in both directions. Sync is off by default, and enabling it is the only time your files leave your computer (the only other network request the app makes is checking https://local.hyperclay.com/updates/stable for app updates).

Connect your sync key#

One API key authenticates your personal folder and every team folder on your computer.

  1. Get an API key

    Open hyperclay.com/dashboard (or click Get API key in the app’s sync key dialog) and create a sync API key. Keys start with hcsk_.

  2. Open the sync key form

    Click the Hyperclay Local tray icon to open the popover, then click Connect sync → (or open Options and choose Sync Key…).

  3. Enter your username and key

    Enter your hyperclay.com username in Username and paste your hcsk_... key into API Key, then click Connect & Enable Sync.

Hyperclay Local validates the key against GET https://hyperclay.com/_/sync/status with an X-API-Key header, then stores it in settings.json encrypted with Electron’s safeStorage and base64-encoded. If safeStorage.isEncryptionAvailable() is false on your platform, the key is stored in plaintext.

Once connected, your personal folder begins syncing and any teams you belong to on hyperclay.com appear automatically in the popover (and refresh every 5 minutes, or whenever you open Options and click Refresh Teams). You can turn sync on or off across all folders at any time using the Sync switch in the popover or Enable Sync / Disable Sync in the tray menu.

Remote host and endpoints#

The remote host is https://hyperclay.com (or https://localhyperclay.com when running in development mode with NODE_ENV=development or --dev). It is not user-configurable.

Personal sync calls endpoints under /_/sync/, and each team folder calls the same routes under /_/team/<username>/sync/, all authenticated with the X-API-Key header:

Text
GET    https://hyperclay.com/_/sync/status
GET    https://hyperclay.com/_/sync/nodes
POST   https://hyperclay.com/_/sync/nodes
GET    https://hyperclay.com/_/sync/nodes/{nodeId}/content
PUT    https://hyperclay.com/_/sync/nodes/{nodeId}/content
PATCH  https://hyperclay.com/_/sync/nodes/{nodeId}/rename
PATCH  https://hyperclay.com/_/sync/nodes/{nodeId}/move
DELETE https://hyperclay.com/_/sync/nodes/{nodeId}[?cascade=true]
POST   https://hyperclay.com/_/sync/control
GET    https://hyperclay.com/_/sync/stream            (Server-Sent Events)

For page documents that store editor merge state in .hyperclay/page-state, uploads send the merge record before the file content, downloads fetch it before writing the file, and renames or deletes move or remove the record alongside the document.

How changes travel#

Local to remote#

Local filesystem changes are debounced (500 ms of quiet, up to a 5 second cap) and compared as a complete folder snapshot against the recorded baseline. Reading changes from a tree diff rather than raw watcher event order means renames stay renames and folders moved together keep their identity.

  • Attachment deletions under uploads/: A single deletion under uploads/ waits 3000 ms (3 seconds) before being sent. If 20 or more attachments (or at least 10% of attachments, minimum 5) are removed from uploads/ at once, sync holds the deletions on the server and posts a notice in the popover with Delete on server and Restore here buttons.
  • Retries: Failed network pushes retry up to 3 times at 5 s, 15 s, and 60 s. Authentication failures, name conflicts, and validation errors are not retried.

Remote to local#

Remote changes arrive over the Server-Sent Events stream (GET /_/sync/stream). Frames are typed in their JSON body: live-sync, node-saved, node-renamed, node-moved, node-deleted, and control.

  • If the stream disconnects, it reconnects after 5000 ms.
  • A fallback check runs every 5 minutes, and 5 minutes of stream silence triggers a full reconciling pass.
  • Echo suppression: live-sync frames whose sender matches this computer’s settings.deviceId (crypto.randomUUID()) are ignored. Node mutations are tracked in an in-flight outbox keyed <op>:<nodeId> with a 30 second TTL so the server’s broadcast of your own write is skipped.

How sync reconciles files#

Sync never relies on system clocks or file modification times. For each file, it compares a 16-character truncated SHA-256 checksum of the local file against the recorded localChecksum baseline, and the server’s ETag against the recorded remoteEtag baseline:

  1. Changed locally only: Uploads the local file to hyperclay.com.
  2. Changed on hyperclay.com only: Downloads the remote file to your folder.
  3. Changed on both sides with identical bytes: Adopts the new baseline without transferring the file.
  4. Changed on both sides with different bytes (or present on both sides with no prior baseline and different bytes): Opens a conflict. Your local file stays in place, the remote bytes are saved in <folder>/.hyperclay/conflicts/, and the popover’s Notices tab lets you choose Keep mine, Keep theirs, or Keep both (which writes <name> (conflicted copy).html beside the original and uploads it).
  5. Deleted on one side: A file deleted on hyperclay.com that you did not edit is moved to <folder>/.trash/. If you edited it locally, it becomes a conflict (Keep mine re-creates it on the server; Keep theirs moves your local copy to .trash/). A file deleted locally and untouched on the server is deleted on the server, while a file deleted locally that changed on the server is downloaded back.

The top-level uploads/ folder is never deleted, moved, or renamed on the server, and missing attachments under uploads/ during initial sync are restored by download. For the full decision table, see How sync decides and Conflicts and deletions.

Ignored files, naming rules, and size limits#

Never synced#

Sync ignores any path with a segment starting with ., as well as system and tool directories:

Text
**/node_modules/**   **/sites-versions/**   **/tailwindcss/**
**/.*                **/.*/**               **/.trash/**
**/.DS_Store         **/Thumbs.db           **/desktop.ini
**/*~                **/#*#

Symbolic links are also skipped, and directories the app cannot read are left out of deletion decisions. Because dotfiles and dot-folders are ignored, .hyperclay/versions/, .hyperclay/conflicts/, .hyperclay/api/, .hyperclay/guard/, and .hyperclay/page-state remain local (except page merge state synced through its dedicated route).

Names that will not sync#

The local HTTP server serves almost any filename, whereas sync enforces hyperclay.com’s naming rules:

  • Documents: Must end in .html or .htmlclay and match ^[a-z0-9_-]+\.(html|htmlclay)$ (lowercase letters, numbers, hyphens, and underscores only). Names such as My Notes.html, Post.HTML, or café.html serve locally on localhost but will not sync.
  • Hyphens and reserved names: No leading or trailing hyphen, no --, and no Windows reserved basenames (CON, PRN, AUX, NUL, COM1, LPT1, and so on).
  • Folders: Must match ^[a-z0-9_-]+$, with a maximum folder depth of 5 levels.
  • Attachments (non-document files): Filename up to 255 bytes of UTF-8, no leading or trailing dot, and no control characters or / \ < > : " | ? * (including their full-width equivalents).

A file or folder that breaks these rules is not silently skipped. It raises a non-retryable validation error in the popover’s Notices tab with the exact reason, such as Folder depth cannot exceed 5 levels. Please reorganize your files into a shallower structure.

Size limits#

  • Attachments: An attachment larger than your hyperclay.com plan’s per-file upload limit stays on your computer. The folder card displays 1 file can't sync (or N files can't sync), and Notices lists <file> is stored here but can't sync: <size>, and this plan allows <limit> with a Show File button. If the file shrinks or your plan limit increases, it queues for upload automatically.
  • Documents: A document larger than 5 MiB on the server is downloaded during initial sync and marked uploadBlocked so local edits to it are not re-uploaded. Locally, /_/save accepts documents up to 20 MB (20971520 bytes).

See What syncs and Limits for full details.

Sync state on disk#

Sync uses plain JSON files rather than a database. Each synced folder stores three files in a directory named after the first 12 hex characters of the SHA-256 hash of the folder’s absolute path:

Text
<userData>/sync-meta/<12 hex>/node-map.json
<userData>/sync-meta/<12 hex>/sync-state.json
<userData>/sync-meta/<12 hex>/tombstones.json

Tombstones expire after 7 days. All three files are written atomically via a temporary file plus rename.

How the server, UI, and sync fit together#

  • Embedded server: Each folder runs an Express.js server on 127.0.0.1 with static file serving, extension-based client-side routing, POST /_/save for self-saving documents, directory listings, and path traversal protections. See How it works.
  • Popover and tray controls: The system tray menu and popover let you toggle serving and sync, open the workspace window or browser, inspect sync and error logs (View Sync Logs and View Error Logs under Options), and manage your sync key. See Popover and tray.