Skip to content

About local sync

A pulled workspace lets developers work on a workspace on their own computer with the hmi CLI. It is a second place where the same setup can change. Setup pages, the assistant, the API, and other local projects keep changing the cloud copy while you edit setup.db and dashboard sources on your machine. Sync has to merge those two streams of edits without losing either and without a lock that would stop the cloud while someone works offline.

Each workspace has a setup revision that only increases. It advances whenever the setup or the synced files change in the cloud. The local project remembers the revision of its last pull, and every local setup item and synced file remembers the version it was last synced at: its base.

cloud setup revision ◄── advances when the setup or synced files change in the cloud
│
hmi pull → everything changed since your last pull
│
unchanged locally → take the server version
changed locally → keep yours; record the server version as a conflict
│
hmi resolve → keep yours (--ours) or take the server's (--theirs)
│
hmi push → each changed item and file must still be at its base,
otherwise push_conflict and nothing is applied

These per-item bases are what let unrelated work pass. A push carries a base for each item and file it changes, and the server compares only those. If another person changed a different parameter in the meantime, the push still applies. If they changed one of yours, the whole push fails with push_conflict and nothing is applied, so the workspace never holds half of a change.

Local changes are setup items you added, changed, or deleted, and synced files you added, changed, or deleted (details). Pull never overwrites them. Items and files you did not change take the server version, and server deletions remove them. When the server also changed something you changed, pull keeps your version and records the server’s next to it as a conflict. The same change on both sides is no conflict at all. An item the server deleted while other local items still refer to it is kept and recorded as a conflict too, so references never dangle.

This puts the decision where the knowledge is. The CLI cannot know whether your edit or the server’s should win, so it keeps both and waits for hmi resolve. Until then push refuses, because sending your version would silently discard the server’s.

Pull and push identify each file by a hash of its content. Push uploads only the contents the server does not have; pull downloads only the contents no local file has. Unchanged files, including built dashboards, are not sent again, and a file moved within the project is not downloaded again. For the same reason, a file the server already holds with exactly your bytes is not a conflict.

A network failure can leave a push in an unknown state: the server may have applied it without the answer reaching you. Each push therefore has an ID that the CLI saves before sending, and a retry under the same ID returns the first result instead of applying the change twice. That makes “push again” safe; see Retry an interrupted push.

Some things sit outside per-item checks. The workspace name has no conflict detection; the last push wins. Report comments can only be added or deleted, so they never conflict. Quick reports stay in the cloud until someone saves them. Automation limits are read-only in a local project. Rules about who may change the name, logos, and the favicon still apply to a push, as they do in workspace settings.

To push, pull, and recover from errors, follow Synchronize local changes and Resolve sync conflicts. Commands and error codes are in the CLI reference.