Commands
Three programs. filesync runs on each client,
filesync-admin on the server, and filesync-server is
started by sshd, never by hand.
On this page
filesync
filesync init --repo NAME --root DIR --server USER@HOST [--remote-repo NAME]
[--id ID] [--role client|replica] [--port N] [--identity FILE]
[--accept-host-key] [--known-hosts FILE] [--server-command PATH]
[--snapshot-mode hardlink|copy]
filesync init --repo NAME --root DIR --transport local --server-root DIR
[--remote-repo NAME] [--id ID] [--role client|replica]
filesync sync [--repo NAME]... [--dry-run] [--force] [--verbose] [--quiet]
[--json] [--no-prune] [--no-delta]
filesync status [--repo NAME] [--json]
filesync log [--repo NAME] [-n N] [--since YYYY-MM-DD|EPOCH]
[--until YYYY-MM-DD|EPOCH] [--exit N]... [--warnings] [--json]
filesync settings [--config FILE] [--json]
filesync verify [--repo NAME] [--deep] [--json]
filesync restore PATH [--repo NAME] [--to DIR] [--list]
filesync snapshot [--repo NAME] [--keep N]
filesync snapshot list [--repo NAME]
filesync snapshot restore DATE [PATH] [--repo NAME] [--to DIR]
filesync version
The sync root must contain the .filesync-root marker created by
filesync init. Diagnostics go to standard error; command output,
including any --json document, goes to standard output, so a cron
job can separate the two.
filesync init
Registers a directory in this client's configuration. It creates the root if
needed and writes the .filesync-root marker.
| Option | Meaning |
|---|---|
--repo NAME | The repo name, as the server knows it. |
--root DIR | The local directory to keep in step; created if needed. |
--server HOST | The ssh server, as host or user@host. |
--server-root DIR | The server root, for --transport local. |
--remote-repo NAME | The repo name on the server, if it differs from --repo. |
--id ID | The id the server knows this client by. |
--transport ssh|local | How the server is reached; the default is ssh, or local when --server-root is given. |
--role client|replica | What this client may do; the default is client. Only a replica may take snapshots. |
--identity FILE | ssh identity file. |
--known-hosts FILE | ssh known_hosts file. |
--port N | ssh port. |
--accept-host-key | Trust an unknown host key on first use. |
--server-command PATH | The server program to run over ssh. |
--snapshot-mode MODE | hardlink or copy, for filesync snapshot. |
--config FILE | The client configuration file to write. |
The id defaults to this machine's host name. That is the name the server
keeps this client's base, journal entries and conflict copies under, and the
name filesync-admin client allow must list. Pass --id
only to override it — for two machines with the same host name, say. It
is not a login, and it does not divide the repo: every client of a repo syncs
the whole tree.
filesync sync
| Option | Meaning |
|---|---|
--repo NAME | Sync this repo; repeatable to sync several. Default: every repo in the client configuration. |
--dry-run | Print the planned actions without changing either side. |
--force | Proceed despite the deletion limits that normally stop a suspicious run. |
--no-prune | Do not prune this repo's local trash during the run. |
--no-delta | Send whole files instead of block deltas. |
--verbose | Raise the log level to debug for this run. |
--quiet | Lower the log level to error. The summary line is still printed when the sync did something; a repo where nothing happened prints nothing. |
--json | Print one JSON document instead of text. |
Each run reports what moved and what it cost:
documents: pulled 2, pushed 1, deleted 0, conflicts 0
transfer: sent 12.4 KiB, received 96.1 KiB, 1 file by delta
Every attempt, successful or not, is appended to
~/.filesync/logs/REPO.jsonl. A lock refusal is reported as exit
code 2 rather than an error, because cron starting a run while the previous one
is finishing is normal.
status, log, settings, verify
filesync status
When each repo last synced, how big it is, and what the last transfer cost.
--repo limits it and --json makes it machine
readable.
filesync log
| Option | Meaning |
|---|---|
-n N | Show at most N runs; the default is 20. |
--since, --until | Inclusive window, as YYYY-MM-DD or an epoch. A date means midnight UTC; --until includes the whole day. |
--exit N | Only runs that ended with this code; repeatable. |
--warnings | Only runs that recorded a warning, conflict or skipped path. |
--json | One JSON document. |
All filters apply before the limit. Runs are listed oldest first, and a torn final line from a killed run is skipped.
filesync settings
Prints every process setting, its effective value, and where that value came
from — built-in default, settings file, or environment. See
Settings. --config FILE names the
settings file; --json prints the report as data.
filesync verify
Compares the local tree with the base the last successful sync recorded. Drift means the tree changed without being synced. It works offline: the ignore list is the one cached by the last sync.
| Option | Meaning |
|---|---|
--deep | Hash every file rather than trusting size and mtime. |
--json | One JSON document. |
Exit code 4 means verification found drift.
restore and snapshots
filesync restore
Puts a path back from this repo's local trash. The newest stored version
wins; --list shows them all instead. Versions are searched in this
repo's trash first, then in the shared trash that releases before 0.001.1
used, so files trashed before an upgrade can still be restored.
| Option | Meaning |
|---|---|
--to DIR | Copy the version into DIR instead of back into the sync root. |
--list | List the stored versions; restore nothing. |
The trash entry is kept, so a restore is repeatable. The destination must not already exist.
filesync snapshot
Takes today's snapshot of a replica, pruning old ones. Snapshots are for the
replica role only. --keep N sets how many to keep,
defaulting to the repo's snapshot_keep and then to 14; 0 keeps
all.
filesync snapshot --repo offsite --keep 7
filesync snapshot list --repo offsite
filesync snapshot restore 2026-10-20 --repo offsite --to /tmp/export
filesync snapshot restore 2026-10-20 notes --repo offsite
snapshot restore copies a whole snapshot, or one relative path
of it, back. Without --to it restores into the sync root, which
rolls the replica back to that date. It holds the repo lock while it works.
filesync-admin
filesync-admin --root DIR <command>
repo create NAME [--trash-days N] [--max-deletes N] [--max-delete-percent N]
[--ignore PATTERN]...
repo list
repo show NAME
client allow ID --repo NAME [--role client|replica]
client list --repo NAME
client forget ID --repo NAME
reindex NAME [--dry-run] [--json]
verify NAME [--deep] [--sample N] [--json]
restore NAME PATH [--to DIR] [--list] [--date YYYY-MM-DD]
log NAME... [-n N] [--client ID] [--since YYYY-MM-DD|EPOCH]
[--until YYYY-MM-DD|EPOCH] [--exit N]... [--warnings] [--json]
--root is read only before the command name.
| Command | What it does |
|---|---|
repo create | Creates the master tree, the metadata directory, the policy and an empty index. --trash-days sets retention, --max-deletes and --max-delete-percent the per-session deletion limits, and --ignore replaces the default ignore list. |
repo list | Lists the repos under the root. |
repo show | Prints one repo's policy. |
client allow | Admits a client id to a repo, as client or replica. A repo with no listed clients admits every client. |
client list | Lists a repo's admitted clients. |
client forget | Removes a client from the list. |
reindex | Rebuilds the master index by hashing every file. Holds the repo lock. Used after a manual repair such as a rollback from backup; --dry-run reports without writing. |
verify | Compares the master with its index. --deep hashes every file; --sample N hashes N of them. |
restore | Puts a path back from the server trash, into the master by default or into --to as an export. --date picks the newest version from that day; --list lists versions. Restoring into the master rebuilds the index. |
log | The server's journal, for one or more repos, with the same time, exit and warning filters as filesync log plus --client. |
If the server root cannot be written, repo create names the
directory that blocks it and says to chown it to the running account or to use
--root elsewhere. That advice is given only when a directory really
is unwritable, so a full disk or a root that is a file keeps its own error.
filesync-server
command="filesync-server --repo docs --client laptop --role client" ssh-ed25519 AAAA...
It is not run by hand: sshd starts it with the arguments pinned in
authorized_keys. The session carries only the repo, the client id
and the role, which is why the client cannot choose the server root and why
the wrapper exists. It refuses to speak
the protocol on a terminal unless FILESYNC_ALLOW_TTY is set.
Exit codes
| Code | Meaning | Applies to |
|---|---|---|
| 0 | Success. | both |
| 1 | Fatal error. | both |
| 2 | Another run holds the lock. | client |
| 3 | Completed with warnings. | client |
| 4 | Verification found drift. | both |
Library errors are raised with croak, but the commands strip the
at FILE line N suffix before printing. Set
FILESYNC_TRACE=1 to keep the full stack trace.