swarmfile-mirror
swarmfile-mirror copies a project (or a subtree) from one Swarmfile hub to another over the public HTTP API - for example, moving a project off the hosted hub onto your own self-hosted swarmfile-server, or keeping a second copy. It is the counterpart to swarmfile-migrate: migrate brings a local tree or an S3 bucket in; mirror copies a project to another project.
A mirror is normally a copy, not a signed replica: files are re-chunked/re-sealed for the destination, so it has no origin commit or checkpoint. With --provenance-out on a plaintext whole-project mirror, the copy preserves the source's block CIDs, manifests and entry lineage, and the origin's signed manifest is written beside it, so swarmfile-verify-history --pin-key <key> --provenance <file> can prove the destination's confirmed head commit or tree is the origin's (the manifest's key ring is untrusted input, hence the pin). A managed/E2E mirror copy re-seals under the destination's key, so its tree differs and the flag refuses; the community server's optional admin copy-project is the same-server exact-history alternative. swarmfile-verify-history --mirror-* likewise matches only a replica that preserves the origin's confirmed head commit. See Verifiable History. It ships as a standalone open-source binary (install with curl -fsSL https://get.swarmfile.com/mirror | sh; source and releases at swarmfile-mirror); no engine or mount is needed. See the Mirroring a Project Between Hubs guide for the workflow.
Flags#
| Flag | Description |
|---|---|
--source-hub-url <url> | Source hub base URL. |
--source-org-id <org> | Source organization id or slug. |
--source-project-id <id> | Source project id. |
--source-token <token> | Source token (sf_pat_… / org key). Defaults to $SWARMFILE_SOURCE_API_KEY, then $SWARMFILE_API_KEY. |
--dest-hub-url <url> | Destination hub base URL. |
--dest-org-id <org> | Destination organization id or slug. |
--dest-project-id <id> | Destination project id. |
--dest-token <token> | Destination token. Defaults to $SWARMFILE_DEST_API_KEY, then $SWARMFILE_API_KEY. |
--path <path> | Subtree to mirror (default: the whole project). |
--branch <name> | Branch to read on the source (default main). |
--cdc | Content-defined chunking (FastCDC) instead of fixed-size. |
--auto-profile | Auto-select the chunking strategy from each file's type (AEC profiles). Conflicts with --cdc. |
--exclude <glob> | Skip entries by name (repeatable, */?). |
--dry-run | List what would be copied; touch nothing. With --provenance-out/--preserve-tree it still fetches the confirmed head tree and verifies the live source listing, but writes no manifest. |
--json | Print a JSON summary (files, bytes, dirs, symlinks, resumed, skipped). |
--state <file> | Resume file: records each mirrored source path → (cid, size) atomically; a re-run skips already-mirrored files. Refuses a state file from a different run. |
--concurrency <n> | Files copied in flight (default 4; 1 = sequential). Ignored with --state and in --dry-run. |
--preserve-tree | Plaintext whole-project copy that keeps the source's block CIDs and entry lineage (no manifest). Use when the origin has no signed history but the exact tree matters. Same constraints as --provenance-out: empty destination (or matching resume state), no --path/--exclude, plaintext both sides; managed/E2E re-seals and is refused. --dry-run performs the tree/listing verification without writing. |
--provenance-out <file> | Write the origin's portable provenance manifest after a successful plaintext whole-project mirror. Implies a tree-preserving copy: the source's block CIDs, manifest/segments and entry lineage are kept, so the destination's tree (and usually its confirmed commit) matches. Requires an empty destination branch (or a resume with the same --state), a source with a confirmed head and zero unconfirmed commits, no --exclude/--path, and a credential that can read the whole tree; sync-ignored entries are included (showIgnored=1). It fetches the confirmed head's canonical tree and refuses if the source or destination live listing differs (lineage/content/kind/target), and a resume state is pinned to the source head. Refused for a managed/E2E source or destination, which re-seals and cannot match. --concurrency/--cdc/--auto-profile do not affect this mode (source chunks are copied verbatim). With --dry-run it performs only the source tree/listing verification and writes no manifest. Verify with swarmfile-verify-history --pin-key <key> --provenance <file>. |
Exit codes#
| Code | Meaning |
|---|---|
0 | Success. |
1 | A failure (including a refused collision or an absolute symlink target). |
2 | A usage error. |
Examples#
export SWARMFILE_SOURCE_API_KEY=sf_pat_… # source hub token
export SWARMFILE_DEST_API_KEY=sf_key_… # destination hub token
swarmfile-mirror \
--source-hub-url https://hub.swarmfile.com \
--source-org-id my-org --source-project-id <id> \
--dest-hub-url https://your-server \
--dest-org-id my-org --dest-project-id <id> \
--path /Projects --state /tmp/mirror.json