Stability Promise (M4.1)¶
This page freezes the protonfs command-line surface as of 1.0: every command,
option/argument name, exit code, config file location, config key, and environment
variable listed here is a stable public contract. A caller (human or script) that
depends only on what is documented on this page will keep working across 1.x
releases.
Versioning policy¶
protonfs computes its next version from Conventional Commits (see
.github/scripts/compute_next_version.py): a feat commit bumps minor, a
fix bumps patch, and a breaking commit (type!: or a BREAKING CHANGE:
footer) bumps major – once the project is at 1.0 or later. Before 1.0, that
same breaking-change signal is demoted to a minor bump instead, so day-to-day 0.x
development never jumps to 1.0.0 by accident. v1.0.0 itself is therefore always a
deliberate, manually-created tag, not something the automated release pipeline produces
on its own.
From v1.0.0 onward, any change that breaks something documented on this page –
removing or renaming a command/option, changing an exit code’s meaning, moving a config
file, dropping an environment variable – is a breaking change and requires that manual
major-version bump. Additive changes (a new command, a new optional flag, a new config
key with a backward-compatible default) remain minor/patch as normal.
Release-override directives (from 1.0.0)¶
A +:<spec> token standing alone on its own line of a commit message
(footer-style) overrides the Conventional Commit classification for that release
entirely, where <spec> is major | minor | patch | pre |
prepre | rc. Prose mentions and quoted examples (like the ones on this page)
never actuate a release. The pre-release forms follow SemVer 2.0.0 precedence with
channels alpha < beta < rc:
From a final release
X.Y.Z:+:pre->X.(Y+1).0-alpha,+:prepre->X.(Y+1).0-alpha.0,+:rc->X.(Y+1).0-rc– a pre-release always belongs to the next minor, so it sorts after the released base.Within a pre-release:
+:prepreincrements the number (-alpha->-alpha.1);+:preadvances the channel (alpha->beta->rc-> the final release);+:rcjumps any earlier channel to-rcand increments when already there (-rc->-rc.1);+:patch/+:minorfinalize.Plain Conventional Commits landing during a pre-release only increment the pre-release number – leaving the channel always requires a directive.
Directives are imperative: they are not subject to the pre-1.0 breaking-change
demotion, and the highest-impact directive wins when several land in one release
batch. Pre-release tags are marked as GitHub pre-releases and publish to PyPI as
PEP 440 pre-releases (1.1.0-alpha.1 -> 1.1.0a1), which pip skips unless
--pre is passed.
Release notes¶
Each release’s CHANGELOG entry is any hand-written [Unreleased] content followed
by notes generated from the release’s Conventional Commits: grouped by type
(Features, Bug fixes, Performance, Reverts, Refactors, Documentation, Tests, Build,
CI, Style), chronological within each group (earliest first). chore commits and
[skip ci] housekeeping are excluded from release notes.
Exit-code contract¶
Every protonfs command follows the same top-level convention:
0– success.2– usage error: bad/missing arguments, unknown option, invalid choice value. This is Click’s own default behaviour and is not overridden anywhere.1– everything else: an operational failure (a Proton Drive error, a lock conflict, a config problem) or a command-specific non-zero outcome documented below. A user declining a confirmation prompt (no--yes/--force) also exits1.
status and auth status layer additional meaning onto exit code 1/2 for
unattended callers, documented in the table below.
Global options (before the subcommand)¶
These flags are given before the subcommand (e.g. protonfs -vv --event-log pull) and apply to every command. A flag, when given, overrides its config key; when unset, the resolved config value is used, falling back to the built-in default.
-v/--verbose– repeatable,-v..``-vvvv``; raises console detail.--progress-inline/--progress-lines– progress render style (default:defaults.progress_style, else inline on a TTY).--event-log/--no-event-log– write.protonfs/events.log(default:defaults.event_log, else off).
Command surface¶
One-line contract and exit codes for every registered command. “Options” lists every flag/argument name; these names, not just their presence, are frozen.
Command |
Contract |
Exit codes |
|---|---|---|
|
Install/verify the proton-drive CLI, init |
|
|
Remove |
|
|
Summarize sync state as a count per state (see Sync states).
Argument: |
|
|
List tracked files with their sync state. Argument: |
|
|
Upload local-only/changed files to Drive. Argument: |
|
|
Download remote-only/changed files from Drive. Argument: |
|
|
Delete local bytes of protonfs-tracked files confirmed present on Drive.
Argument: |
|
|
Remove a file/directory from Drive (trash by default, |
|
|
Restore a trashed file/directory on Drive. Argument: |
|
|
List every item in |
|
|
Permanently empty |
|
|
Discover remote files and seed the local index (metadata-only). Argument:
|
|
|
Check the remote manifest ( |
|
|
Download and verify the official proton-drive CLI binary. Options:
|
|
|
Upgrade proton-drive to this release’s highest supported version (verify-first,
atomic swap; never past |
|
|
Check this host can run proton-drive (binary, session bus, OS keyring) and
version/state currency (support matrix, upstream advisory, index schema,
pending migrations, config layering). Warn-level findings suggest
protonfs upgrade without failing the exit code. Option: |
|
|
Print shell exports so |
|
|
Print, |
|
|
Install/list/remove cron jobs running push/pull on a schedule. |
|
|
Passthrough to |
Exit code is whatever |
|
Check for a valid session without invoking |
|
|
Print the resolved value of |
|
|
Set |
|
Sync states¶
The state names printed by status, emitted as status --format json keys,
shown by ls and accepted by ls --state are part of this contract, and so is
the exit-code class each one maps to. Without --remote no state says anything
checked on Drive; the states marked remote view are only produced by
status --remote/ls --remote.
State |
Meaning |
|
|---|---|---|
|
Local matches the index (and, with a remote view, the remote agrees).
Renamed from |
clean ( |
|
Indexed but deliberately not materialised on this machine. |
clean ( |
|
An un-smudged git-LFS pointer stub; deliberately left alone. |
clean ( |
|
Present locally, not in the index. |
drift ( |
|
Held by this machine, now gone locally. Without a remote view the remote
was not checked (reported as |
drift ( |
|
Remote view. Listed on Drive, absent locally and from the index. |
drift ( |
|
Remote view. One side diverged from the index; the other did not. |
drift ( |
|
Remote view. A file not held locally whose remote copy moved or vanished. |
drift ( |
|
Local diverged from the index with no remote view to attribute a direction. |
conflict ( |
|
Remote view. Local and remote both diverged from the index. |
conflict ( |
Known keys for config get/config set: remote_root,
device_id, defaults.on_conflict, defaults.low_io,
defaults.event_log, defaults.progress_style,
defaults.manifest (added in 2.1.0). Each is defined in the Configuration
section of Command Reference.
Config files and precedence¶
Layered configuration, highest precedence first:
Environment variables (see below) – always win, per-key.
.protonfs/config.local.json– per-device, gitignored..protonfs/config.json– per-repo shared, committed (the sync contract).~/.config/protonfs/config.json– global user defaults.$XDG_CONFIG_HOMErelocates the~/.configbase;$PROTONFS_CONFIGoverrides the full path outright.Built-in defaults (
defaults.on_conflict=skip,defaults.low_io=false,defaults.manifest=false,defaults.event_log=false,defaults.progress_style=inline).
config get always reports the fully resolved value across all four layers.
config set writes to exactly one layer: the shared repo file by default, or the
global/local file with --global/--local (mutually exclusive).
Environment variables¶
Variable |
Purpose |
|---|---|
Overrides the global config file path outright (points directly at the file). |
|
Per-key override for the resolved |
|
Per-key override for the resolved |
|
Per-key override for the resolved |
|
Per-key override for the resolved |
|
Per-key override for the resolved |
|
Per-key override for the resolved |
|
Per-key override for the resolved |
|
Set (to any truthy value) to switch every remote-manifest read and write off on
this host, whatever |
|
Path/name of the |
|
Overrides the |
|
Explicit SHA-512 to verify a |
|
Timeout in seconds for a Drive listing call (default |
|
Max retries for a Drive listing call (default |
|
Base backoff in seconds between Drive listing retries (default |
|
Cap in seconds on the Drive listing retry backoff (default |
|
Timeout in seconds for a Drive upload/download call (default |
|
Max retries for a Drive upload/download call (default |
|
Base backoff in seconds between Drive upload/download retries (default |
|
Cap in seconds on the Drive upload/download retry backoff (default |
|
Supplies the password for the protonfs-owned keyring bootstrap, instead of generating one. |
|
Set (to any truthy value) to disable protonfs’s Secret Service/keyring bootstrap entirely; the caller is responsible for providing one. |
Proton Drive support matrix¶
protonfs states, as a checkable contract, which proton-drive CLI versions
each of its own releases supports. src/protonfs/install.py exposes this as
SUPPORTED_DRIVE_VERSIONS (an explicit set of supported versions),
highest_supported() (the version install-drive/the upgrade command installs
– always equal to DEFAULT_VERSION), and is_supported(version). The
installed CLI’s own version is available via DriveClient.drive_version(), which
parses proton-drive version output (e.g. Proton Drive CLI
cli-drive@0.5.0+73e40d90) down to the comparable semver "0.5.0".
protonfs release |
Supported proton-drive versions |
Notes |
|---|---|---|
1.0.x |
|
|
Upgrade policy¶
A given protonfs release only ever upgrades proton-drive up to its own
highest_supported() – it will never install a proton-drive version newer
than that, even if one exists upstream. Picking up a newer upstream
proton-drive release requires upgrading protonfs itself: a maintainer runs
python .github/scripts/repin_proton_drive.py to independently verify and pin the
new version’s checksums for every supported platform, adds it to
SUPPORTED_DRIVE_VERSIONS, and cuts a new protonfs release with that as its
highest_supported(). This keeps the installed proton-drive version always
within the range a given protonfs release was built and tested against.
protonfs upgrade is the user-facing voice of this policy: it upgrades an
outdated binary to highest_supported() (SHA-512-verified before an atomic
swap), reports – without installing – when upstream’s Stable release is ahead,
and runs pending repo-state migrations. protonfs upgrade --check previews all
of it, exiting 0 when fully current and 1 when an upgrade is available.
See also¶
Getting Started for installation and first-run setup.
Upgrading for the upgrade story built on this support matrix.
Syncing across machines for the push/pull/status workflow this contract supports.