Dry-run preview
--dry-run is your seatbelt. It computes and prints the exact plan the daemon would
execute, as JSON, and then exits — without uploading, downloading, deleting, or writing
the index. Use it before the first real sync of a new folder, after changing roots, or
whenever behavior surprises you.
proton-syncd \ --local-root /tmp/proton-sync-demo \ --remote-root /Drive/RemoteFolder \ --dry-runDry-run still contacts Proton Drive through the proton-drive CLI (to list the remote), so
authentication and remote permissions must already work. It does not bind the IPC
socket, take the daemon lock, or run any side effect.
The output shape
Section titled “The output shape”{ "summary": { "total": 1, "uploads": 0, "downloads": 1, "remote_directories_created": 0, "local_directories_created": 0, "local_moves": 0, "remote_moves": 0, "auto_links": 0, "conflicts": 0, "type_conflicts": 0, "remote_deletes": 0, "local_deletes": 0, "purges": 0, "skipped_unsupported": 0, "destructive_actions": 0 }, "plan": [ { "path": "notes.txt", "destination_path": null, "action": "download", "entity_kind": "file", "conflict_path": null, "remote_id": "remote-file-id" } ]}Every field is always present, so scripts can rely on a fixed shape. Unused summary
counters are 0, and the optional plan fields (destination_path, conflict_path,
remote_id) are null when they don’t apply.
Reading a plan row
Section titled “Reading a plan row”action— one ofupload,download,create_remote_directory,create_local_directory,move_local,move_remote,auto_link,conflict,type_conflict,remote_delete,local_delete,purge,skip_unsupported. See what each means.entity_kind—"file"or"directory".destination_path— populated only for the two move actions.conflict_path— populated only for aconflict, naming the.proton-cloudsidecar.remote_id— the Proton Drive node id, when known.
The number that matters: destructive_actions
Section titled “The number that matters: destructive_actions”destructive_actions is the sum of remote_deletes, local_deletes, and purges — the
count worth a second look before you run for real. On a first sync of a fresh pair it
should be 0, because the first pass is a non-destructive merge.
Note the two “destructive” senses the tooling distinguishes:
- Display-destructive —
remote_delete,local_delete, andpurge. These are tinted red and sorted first in the app’s plan view, and counted indestructive_actions. - Gated — only
remote_deleteandlocal_delete. Apurgeis index-only cleanup, so a purge-only plan is never gated by the delete-approval guard or by the app’s typed-DELETEconfirmation.
In the desktop app
Section titled “In the desktop app”The app’s Plan preview screen runs the same dry-run and renders it as a summary grid
plus one row per action, destructive rows floated to the top. When the plan contains a real
delete, Apply is inert until you type DELETE to arm it, and the confirmation names the
files at risk. See Screens.
One honest caveat the app surfaces: the dry-run and the real reconcile are separate invocations, so a plan applied a moment later can differ from the one you reviewed if something changed in between. Re-run the preview if you want a fresh check.
Selective sync applies
Section titled “Selective sync applies”Dry-run respects your --include/--exclude filters, so it’s the right way to confirm a
selective-sync rule set before enabling regular sync.