Push, pull & sync
Every imported project records a local base in .hlix/state.json and a cloud head with an immutable revision ID and monotonically increasing generation. Synchronization compares both sides to that common base.
Prerequisites
Section titled “Prerequisites”- Run commands from the imported project root
.hlix/config.jsoncontains a project ID.hlix/state.jsoncontains the last synchronized revision- Finish and test valuable local work before any forced pull
Choose the command
Section titled “Choose the command”Both sides are compared against the base revision they last agreed on: if only one moved, the direction is unambiguous; if both moved, hlix refuses rather than merging.
| Command | Use when | Behavior |
|---|---|---|
hlix push |
Local files changed; cloud did not | uploads a new immutable revision using compare-and-swap |
hlix pull |
Cloud changed; local did not | verifies and applies the cloud head locally |
hlix sync |
You want hlix to choose only when one side changed | pushes, pulls, or reports already synchronized |
hlix sync is intentionally not a merge engine. If local and cloud both changed from the same base, it stops with a conflict.
Look before you act
Section titled “Look before you act”All three commands accept --dry-run. It prints the divergence, takes no action, and reports the verdict the real command would reach.
hlix push --dry-runExpected result:
push --dry-run: Would push the local changes as a new cloud revision.
local generation 3 (rev_01J8Z4) — modifiedcloud generation 3 (rev_01J8Z4)files 412 local, 410 cloud — 3 local-only, 1 cloud-only, 2 differingThe first line is the verdict; the block below is the evidence for it. The verdict is one of four per command:
| Command | Verdict line |
|---|---|
push |
Would push the local changes as a new cloud revision. · Nothing to push — local matches the last synced revision. · Would refuse: the cloud changed since this folder's base revision. |
pull |
Would replace local files with the cloud revision. · Nothing to pull — the cloud head is the local base revision. · Would refuse: local files changed. Re-run with --force to replace them. |
sync |
Would push … · Would pull the cloud revision into this folder. · Already in sync. · Would refuse: local and cloud both changed since the last sync. |
A dry run that would end in a conflict exits 1, the same way hlix import --dry-run exits 1 for a blocker. The report is the deliverable, and the exit code still carries the verdict — so a script can gate on it without parsing the text. conflict is the only verdict that exits 1; every other dry run exits 0.
When the real run would stop to ask
Section titled “When the real run would stop to ask”A forced pull over local changes is the one case where the verdict alone is not the whole answer. The dry run adds a second line:
hlix pull --force --dry-runpull --dry-run: Would replace local files with the cloud revision.Requires --yes (or interactive approval) to execute.
local generation 3 (rev_01J8Z4) — modifiedcloud generation 4 (rev_01J9A2) — aheadfiles 412 local, 415 cloud — 2 local-only, 5 cloud-only, 3 differingThat run exits 0: needing an answer is not a refusal, and a caller who has one — a terminal, or --yes — executes exactly this plan.
In --json, the same fact is a field rather than a line:
{"dryRun":true,"action":"pull","approvalRequired":true,"localChanged":true,"cloudChanged":true}Push local changes
Section titled “Push local changes”hlix pushExpected result:
push complete.The new revision becomes head only when the cloud still matches the revision and generation in local state. Protected files are uploaded separately from the Git bundle.
Pull cloud changes
Section titled “Pull cloud changes”hlix pullExpected result: pull complete. The CLI verifies bundle size, SHA-256, Git bundle validity, commit SHA, manifest metadata, and every protected file before applying data.
If local managed files changed, pull refuses. After reviewing and backing up those changes, replace them explicitly:
hlix pull --forceThe forced-pull approval gate
Section titled “The forced-pull approval gate”pull --force is the one command that deletes local work, so it asks before replacing anything. The two flags say different things:
--forcestates “replace my changes.” It selects the destructive behavior.--yesstates “do not ask.” It answers the prompt in advance.
Interactively, --force alone prints what it is about to destroy and waits:
hlix pull --force will replace this folder with cloud revision 4.Local-only files to delete: 3Files to replace with the cloud copy: 2Local changes that were never pushed cannot be recovered by Hlix.Declining exits cancelled. A --json or non-interactive caller cannot answer a prompt, so it is refused rather than defaulted to yes:
`pull --force` replaces local files. Review with `hlix pull --dry-run`, then repeat with `--yes`.That refusal is approval_required. --force with no local changes replaces nothing and does not prompt.
For a Git project, pull updates the managed working tree to the cloud commit. For a non-Git import, it replaces files described by the revision manifest. Ignored local-only files are outside that managed set.
Reconcile automatically
Section titled “Reconcile automatically”hlix syncThe decision table is exact:
| Local since base | Cloud since base | Result |
|---|---|---|
| no change | no change | Already in sync. |
| changed | no change | push |
| no change | changed | pull |
| changed | changed | conflict; no side is overwritten |
Verify synchronization
Section titled “Verify synchronization”hlix sync --jsonExpected result: a versioned JSON envelope containing action, revisionId, and generation. Run the command again; it should report an action of none.
If synchronization fails
Section titled “If synchronization fails”not_initialized: runhlix import .from the project root.workspace_mismatch: a--workspace,--base-url, orHLIX_*value contradicts this folder’s binding. Drop the override, or point--cwdat a folder bound to the workspace you meant. Runhlix statusto see which source decided what.approval_required: a destructive step needs an approval this caller cannot give. Review with--dry-run, then repeat with--yes.cancelled: you declined the prompt. Nothing was changed.Cloud changed since the local base. Run `hlix pull` or resolve with `hlix sync`.— review before choosing a side.Local files changed since the last sync. Push them, or use `hlix pull --force` to replace them.— push first if the local work matters.Both local and cloud changed since the last sync. Pull or push explicitly after reviewing the conflict.: preserve local work in a branch or backup, inspect the cloud state, then choose a side explicitly.Project has active tasks: wait for them to reach a terminal state, pull their resulting head when needed, then retry.Downloaded revision … failed integrity verification: stop. Do not bypass the check; retry over a trusted network and contact support if it repeats.SECRETS_ENCRYPTION_KEY is not set: the deployment cannot decrypt protected state. An operator must repair backend configuration.Refusing to replace non-regular protected file: replace the symlink/device with the intended regular file only after confirming the path.