Skip to content

About

Unofficial bidirectional Proton Drive sync for Linux — native CLI + GUI, three-way merge engine, built on Proton's official proton-drive CLI.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

protondrive4linux

protondrive4linux

Bidirectional folder sync for Proton Drive on Linux, built on Proton's official proton-drive CLI.

protondrive4linux is an independent, unofficial project. It is not affiliated with, endorsed by, or sponsored by Proton AG. "Proton" and "Proton Drive" are trademarks of Proton AG. protondrive4linux never sees your Proton credentials; it only drives Proton's own CLI, which you log in yourself.

The official proton-drive CLI can upload, download, list, and manage sharing, but it has no sync engine. protondrive4linux adds one: a three-way-merge engine that keeps one or more local folders and their Proton Drive counterparts in sync in both directions, driven entirely by the CLI's one-shot commands. It ships as a dependency-light CLI plus an optional native GUI, both on one core library.

Activity: live sync is on and the latest files are listed Folders: one watched, one syncing, one with files waiting to retry Conflicts: what changed on both sides and what was done about each

More pages, the light theme and the sign-in screen: docs/screenshots.md

Features

  • Bidirectional three-way merge. A per-pair baseline lets it tell "new on the remote" apart from "deleted locally", so changes on either side are applied correctly instead of blindly mirrored.
  • Safe by default. Deletions are opt-in and recoverable (remote to Proton trash, local to the desktop trash). A missing baseline unions both sides rather than mass-deleting. Conflicts keep both copies. An unmounted local folder or a vanished remote base is refused, not mistaken for a mass delete.
  • Selective sync. Exclude sub-folders per pair. Excluded paths are never touched on Proton; you can optionally free up local space by removing the local copy while the cloud copy stays.
  • Live sync. A watch daemon reconciles on local change (inotify, debounced) and does a periodic full rescan to catch everything else, including changes made on your other devices.
  • Native GUI or CLI. An egui desktop app (single binary, optional system tray) or a lean command-line tool. Same engine, same config.
  • Checksummed releases, signing in progress. Releases ship .deb, .rpm, and a portable binary tarball with published SHA-256 checksums. Independent GPG signing of release artifacts is being rolled out (see SECURITY.md) so a compromised release pipeline, not just a corrupted download, can be caught.

Requirements

  • Linux with a recent Rust toolchain (edition 2021) if building from source.
  • The official proton-drive CLI on your PATH (https://proton.me/blog/proton-drive-cli). Verified against cli-drive 0.8.0. Installing via the PKGBUILD (Arch/AUR) pulls this in automatically as a dependency (proton-drive-cli, -bin, or -git - three community AUR packages provide it); building from source or installing another way still means getting it yourself.
  • gio (from glib, present on most desktops) for recoverable local deletes; a manual XDG-trash fallback is used if it is missing.

Install

Arch Linux (AUR)

yay -S protondrive4linux-git   # or paru, or any other AUR helper

This pulls in the official proton-drive CLI automatically (as proton-drive-cli, its -bin, or its -git variant — pick whichever your AUR helper offers) along with every other dependency, so one command leaves you ready to launch the app and sign in. protondrive4linux-git tracks master; see PKGBUILD if you'd rather build it yourself with makepkg.

From a release (Debian/Ubuntu)

# download the .deb from the Releases page, then:
sudo apt install ./protondrive4linux_<version>_amd64.deb

From a release (Fedora/RHEL)

sudo dnf install ./protondrive4linux-<version>.x86_64.rpm

Both packages install the protondrive4linux CLI and protondrive4linux-gui GUI to /usr/bin, a desktop launcher, and systemd user units. A portable protondrive4linux-<version>-x86_64-linux.tar.gz (both binaries) is also attached to each release if you'd rather not use a package manager.

From source

# CLI
cargo install --path .                      # -> ~/.cargo/bin/protondrive4linux
cargo test                                  # engine + unit tests

# GUI (opt-in feature, keeps the CLI dependency-light)
cargo build --release --features gui --bin protondrive4linux-gui

The GUI build needs a few system libraries (Debian/Ubuntu):

sudo apt-get install -y libgtk-3-dev libxkbcommon-dev libwayland-dev \
  libx11-dev libxcb1-dev libgl1-mesa-dev libxdo-dev libayatana-appindicator3-dev

Quick start

GUI

Launch protondrive4linux from your app menu (or protondrive4linux-gui). Sign in to Proton (this opens Proton's own login in your browser and signs in the CLI), add folder pairs on the Folders page, and use "Choose folders to sync" to exclude any sub-folders you don't want. Settings covers the theme (follow the system, force light/dark, or pick Dracula, Nord, Tokyo Night or one of your own - a small TOML file, see docs/THEMES.md), the tray, auto-sync, conflict handling, and your update channel.

CLI

protondrive4linux login                       # proton-drive auth login (browser)
protondrive4linux init                        # write ~/.config/protondrive4linux/protondrive4linux.toml
$EDITOR ~/.config/protondrive4linux/protondrive4linux.toml
protondrive4linux sync --dry-run              # preview
protondrive4linux sync                        # apply
protondrive4linux watch                       # live sync: FS events + periodic rescan

init writes a starter config (private to you: folder 0700, file 0600); add your own [[pair]] entries. Other commands: status, doctor (see Troubleshooting), logout. sync takes --dry-run, --resync (rebuild the baseline from the union of both sides), and --json; passing pair names syncs only those.

How it works

For each folder pair, protondrive4linux keeps a baseline snapshot of the last state the two sides agreed on. On every run it scans the current local and remote trees and classifies each path against the baseline (created, modified, or deleted) independently per side. Combining the two verdicts decides the action and which side wins.

Detecting changes. Proton's CLI has no "recently changed" feed, and rebuilding its SDK to add one isn't worthwhile. So protondrive4linux watches your local folders live and aims the work at where the activity actually is:

  • A local change reconciles only the folder whose direct contents changed (one shallow folder listing), not the whole tree. Because the watch is recursive, a change deeper down arrives as its own event and reconciles its own folder, so editing one file never re-walks a subtree.
  • On startup it syncs folders with fresh local changes first, then recently active ("hot") folders, then everything else.
  • A full walk of both trees is the safety net that catches remote-side changes (edits made on your other devices, which the CLI only reveals by re-walking). It streams: it reconciles and transfers folder-by-folder as it walks, so a large tree starts syncing right away instead of after a full scan. It is paced to how long a walk actually takes, roughly six times its own duration, so a large tree is not re-walked constantly. Remote-only changes therefore appear on the next hot or full pass, not instantly.

If the tray dies - a crash, the panel or compositor restarting - --tray starts it again on its own, and an open window says when background sync stopped or has stopped updating (with a Try again button if it can't be started); Quit from the tray menu still stops everything. When the background tray daemon is doing the work, an open window mirrors its live state, so scanning and per-file transfers show up in Activity in real time. The tray icon carries a status badge so you can tell at a glance without opening anything: green check = up to date, blue dots = syncing, grey bars = auto sync off, red "!" = a folder has errors or files are waiting to retry, amber dash = signed out of Proton, amber clock = waiting for your keyring (see Troubleshooting). The menu's top line spells it out ("Syncing docs (3/10)", "Up to date · synced 2 minutes ago", ...). The sync model and its reasoning are written up in docs/SYNC_MODEL.md.

Safety model.

  • Deletions propagate only when propagate_deletes is on, and recoverably: the remote copy goes to Proton's online trash, the local copy to your desktop trash (local_delete = "remove" unlinks permanently instead).
  • A missing baseline (first run, or a wiped state dir) unions both sides rather than mirroring, so a lost baseline can't trigger a mass delete.
  • If a folder's local root is missing (an unmounted drive) or its remote base folder has vanished, the pair is refused for that run instead of being read as "everything was deleted". The same goes for a root that comes back empty while at least five files are on record (an unmounted drive's mount point, a folder emptied by mistake; deleting the last file or two of a small folder is just a deletion): that run goes on without any deletion, and says why.
  • A folder that can't be read (permissions, an I/O error), a tracked file or folder that has become a symlink, and a listing that breaks off half way are all "can't see", never "deleted": nothing is deleted on that basis. Symlinks are never followed, and nothing is ever written through one.
  • Pointing an existing folder pair at another local or remote folder discards its old record (it described the old folders) and starts it afresh: both sides are merged and nothing is deleted, instead of every file reading as deleted on the side that changed.
  • A download arrives whole or not at all. The CLI writes into a private hidden folder (.protondrive4linux-….part) inside the folder the file belongs in, and the file is moved into place only after it has arrived at the size the listing promised, been flushed to disk, and found your local copy exactly as the run left it. A download that dies half way (a full disk, a killed CLI, a crash, a power cut) therefore never leaves a half file under the real name or replaces your good copy, and a half file can never be read as your own edit and uploaded over the good one. If you edit a file while a download of a newer version of it is landing, your edit wins and the two meet as a conflict on the next run. While a download runs it needs room for both copies; leftovers of a killed one are removed on the next scan.
  • A failed or interrupted run never poisons the wider sync: the baseline records a file only after its transfer actually completes, so a timeout, an error, or a run cancelled part-way leaves every other file's state untouched and retries the rest next run in the correct direction. This is what stops a half-finished run from later mistaking a not-yet-downloaded file for a deletion.
  • Two files of the same size are not taken for the same file just because their times differ: that is a conflict (both kept) unless Proton's own SHA-1 for the file matches the local one. Likewise a delete + create of the same size and time is only treated as a rename when the content matches, when Proton lists a digest to check it against.
  • A deletion too big to be believed is held back. With deletes propagating, one run may delete at most the larger of max_delete_files (100) and max_delete_percent (20 %) of the files a pair tracks. A run that would delete more deletes nothing - it still transfers - and says so, with how to proceed: protondrive4linux sync --allow-mass-delete NAME if you meant it, protondrive4linux sync --resync NAME to get the files back instead. It is the net under the specific guards above, for the mistake nobody thought of, and what bounds the damage when it is Proton that suddenly looks emptied. Before a full walk deletes a single file it counts the files still on disk, so a tree that has mostly gone (an unmounted drive, rm -rf) deletes nothing at all; a walk over many folders spends one allowance, not one per folder. A smaller pair can never trip it (a run may always delete 100 files). The window shows it as a banner on the Activity page - how many files, how much of the folder, which side - with Restore them (get the files back) and Delete them (you meant it; it asks first), and the tray sends one notification; the commands above do the same from a terminal. See docs/screenshots.md.
  • A folder deleted on one side is only deleted on the other if everything in it is known: a file you created or edited since the last sync, or one that arrived from another device, keeps the folder (the files sync normally and the folder goes later if it is then empty of news).
  • Conflicts keep both copies by default (name (conflict <timestamp>).ext). The GUI's Conflicts page lists every file that changed on both sides and what was done about it - including conflict = "skip" ones, which are left untouched until you settle them - and protondrive4linux status reports how many are unresolved.

File manager

Opt-in (Settings → File manager, or file_manager = true): your synced folders are added to the sidebar of the GTK file managers (Nautilus, Nemo, Thunar, PCManFM - via ~/.config/gtk-3.0/bookmarks), and two entries - Proton Drive - Sync now and Proton Drive - Conflicts - appear in Nautilus's right-click → Scripts menu. It also marks sync status with small emblems in Nautilus and Nemo (kept up by the tray): a check on each synced folder when it's up to date, arrows while it syncs or a file waits to retry, a warning for a conflict (on the file, its folder and the folders above it, so you can find it), a cross for errors, a lock on folders you excluded. A file with no emblem is simply in sync.

It's only a shortcut to the real local folder (no virtual filesystem), it never touches your own bookmarks, scripts or emblems - even a script with the same name - and turning it off removes exactly what it added. COSMIC Files and Dolphin keep their favorites in their own formats and don't read these emblems, so they aren't covered.

Selective sync

Each pair can list sub-paths to exclude (in the GUI's "Choose folders to sync", or exclude = [...] in the config). Excluded paths are ignored entirely and never touched on Proton. Excluding an already-synced folder freezes both copies in place; when you exclude one, protondrive4linux offers to remove the local copy (to the desktop trash) to free space while the cloud copy stays. Re-including a folder later re-downloads it from the cloud, so excluding can never delete remote data.

Configuration

TOML at ~/.config/protondrive4linux/protondrive4linux.toml (override with -c PATH or $PROTONDRIVE4LINUX_CONFIG). See protondrive4linux.example.toml for the annotated template.

[cli]
binary = "proton-drive"
upload_flags = ["--file-conflict-strategy", "replace", "--folder-conflict-strategy", "replace"]
download_flags = ["--file-conflict-strategy", "remove", "--folder-conflict-strategy", "remove"]
fresh_cache = true            # throwaway metadata cache per run (avoids stale listings)
# credentials_store = "keychain"   # keychain | pass | unsafe_file

[options]
remote_root = "/my-files"     # Proton's per-user root
propagate_deletes = false     # deletes cross over (recoverably); false = never delete
# max_delete_files = 100      # one run deletes at most max(this, max_delete_percent % of what a pair tracks);
# max_delete_percent = 20     # more is held back for your confirmation (100 = guard off)
local_delete = "trash"        # trash | remove
conflict = "keep-both"        # keep-both | newer | skip
compare = "size+mtime"        # size | size+mtime | sha1
poll_interval = 900           # watch: seconds between full rescans
update_channel = "stable"     # stable | prerelease
# check_on_launch = false     # GUI: check for updates on start (notify only)
# notifications = true        # tray: desktop notifications for conflicts, lasting problems, held-back deletions, sign-out, background sync stopping
# theme = "system"            # GUI: system | light | dark | the name of a custom theme
# file_manager = false        # add synced folders to the file manager sidebar + Nautilus Scripts menu

[[pair]]
name = "documents"
local = "~/Documents"
remote = "Documents"          # -> /my-files/Documents
# exclude = ["APPS"]          # sub-paths never synced; the Proton copy is untouched

fresh_cache matters: the CLI caches directory metadata and serves it stale, so without a fresh cache per run it would miss changes made on another device.

Running in the background (systemd --user)

Use one of these, not both (they'd contend for the same pairs):

# Live sync (recommended) — the watch daemon:
systemctl --user enable --now protondrive4linux-watch.service

# or a periodic timer instead:
systemctl --user enable --now protondrive4linux.timer

The packaged units target /usr/bin/protondrive4linux. If you installed with cargo install, edit ExecStart to %h/.cargo/bin/protondrive4linux. Proton Drive is rate-limited, so keep the sync set modest and the rescan interval sane.

Troubleshooting: doctor

When something doesn't sync, start with:

protondrive4linux doctor

It checks the installation and changes nothing: one line per check, and under anything that needs attention, what to do about it.

Check What it looks at
Version The binary that's answering: version, commit, where it's installed.
Config Found, parses, how many folder pairs. A config that's missing or broken doesn't stop the checks that don't need it.
Proton CLI proton-drive on your PATH, its version (this build is verified against 0.8.0 and newer), and a warning if it sits in a directory other users can write to.
Network Whether an HTTPS connection to drive-api.proton.me can be opened. Nothing is sent over it.
Credentials Whether the CLI has a working session, asked the same way the app asks. The session itself is never read. It tells an unreachable keyring (locked, no D-Bus session, headless) from never having signed in, since signing in again won't fix the first.
Folders Each pair's local folder exists.
Permissions Your config and state folder belong to you and are closed to others (0600 / 0700; a config owned by root, set up by an administrator, is only noted). Anyone who can write the config can choose which program runs as cli.binary, and the state folder holds logs and a database that list your file names.
systemd The packaged user units: running, failed, enabled but stopped, or the live service and the timer both active (use one).
Watcher Whether a watcher (the tray app, protondrive4linux watch, or the service) is running right now.
Desktop entry The launcher and the GUI binary installed together, and whether launch-at-login is on.

The exit status is 0 unless a check failed (warnings don't count), so it works in scripts: --json prints the report as JSON, and --offline skips the checks that use the network (reachability and sign-in). --probe, or a REMOTE_PATH argument, additionally lists that remote folder through the CLI and shows how its JSON is parsed - for when a CLI update changes the output.

The report names paths on your system (your home folder, your synced folders), so skim it before pasting it into a public bug report. It never prints credentials.

"Waiting for your keyring"

The proton-drive CLI keeps your Proton session in your system keyring (GNOME Keyring, KWallet, ...). If it can't reach the keyring - it is locked, no keyring is running in this login, or the app was started without a D-Bus session - the app says Waiting for your keyring (an amber clock on the tray icon) instead of asking you to sign in, because signing in again doesn't help and your session is usually still there. Unlock the keyring, or start one in this session, and syncing resumes by itself within a minute (the window's Check again does it at once). If it lasts five minutes you get one notification. doctor shows the same thing under Credentials, and its hint says what to try; to keep the session somewhere else, see credentials_store under Configuration.

Updates

Update through whatever installed protondrive4linux: yay -Syu (AUR), your package manager for the .deb/.rpm, or a fresh cargo install --path . from source.

The GUI's in-app updater is currently disabled. It checks a GitHub release's checksum before installing, but that checksum is computed by GitHub over the same asset it's checking — it catches a corrupted download, not a compromised release pipeline or account. It'll come back once releases carry an independent signature checked against a maintainer key baked into the binary; see SECURITY_AUDIT.md §0.6 for the detail. Releases still come from GitHub as before (every tag a pre-release, promoted to stable deliberately) - only the automatic in-app install step is off.

Privacy and trust

protondrive4linux has no access to your Proton account. Logging in runs Proton's own proton-drive auth login in your browser; the CLI stores the session in your OS keyring, and all encryption and decryption is done by Proton's software. protondrive4linux never sees, stores, or transmits your password or Proton credentials. Sync logs (which record file paths, not secrets) are written private to your user.

Known limitations

How the data-loss review of the sync engine went - what it found, what it fixed, and what still is a risk - is in docs/DATA_LOSS_REVIEW.md.

  • Remote-side changes (edits on another device) are only noticed on a hot or full pass, not instantly, because the CLI has no event feed and must re-walk. Actively-changed local folders sync immediately; see docs/SYNC_MODEL.md.
  • Default compare = "size+mtime" can miss an in-place edit that keeps the same size and mtime, and a file whose Proton entry has no modification time is compared by size alone; use compare = "sha1" to compare content exactly.
  • A transfer that doesn't finish within cli.cli_timeout_secs (30 minutes by default) is stopped and retried, so a file too big for your connection to move in that time never arrives until you raise it.
  • Renames look like a delete + create.

Development

See docs/contributing/CONTRIBUTING.md for layout, build, and release notes, docs/GUI_API.md for the GUI backend API, docs/roadmap/ROADMAP.md for what's planned next, and CHANGELOG.md for what's changed release to release.

License

MIT. See LICENSE.

About

Unofficial bidirectional Proton Drive sync for Linux — native CLI + GUI, three-way merge engine, built on Proton's official proton-drive CLI.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages