Skip to content
 
 

Latest commit

 

History

173 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Linux cloud folder icon

Proton Drive client for Linux — experimental community fork

Important

This is an experimental community fork of narrrl/proton-drive-linux. It is unofficial, is not affiliated with or endorsed by Proton AG, and is shared as-is without a promise of support, compatibility, or continued maintenance.

This experimental community fork extends the upstream client with thumbnail browsing directly in the regular Files section. It builds and caches previews for standard images and camera RAW files in any Drive folder, not only in the Photos gallery. Compared with the parent project, this fork also focuses on more native Linux desktop controls, responsive file and offline-copy actions, explicit control over the mount service's lifetime, and reproducible Debian packaging.

The underlying client retains upstream's files-on-demand FUSE mount with block-level caching, command-line interface, GTK4 desktop app, and system tray integration. Tagged GitHub releases from this fork contain an amd64 .deb package only; the Arch and Fedora files remain available for local builds.

Why this fork?

The upstream project is the foundation of this client. This fork exists to explore and share a more desktop-focused Linux experience: native controls, responsive background work, image and RAW thumbnails, explicit control over the mount service's lifetime, and a tested Debian package. The changes are kept public so they can be reviewed, reused, or proposed upstream independently; this repository does not imply a promise of support or long-term maintenance.

Features

  • Files-on-Demand (FUSE): Mount your Proton Drive as a virtual filesystem that fetches file content as applications read it, with block-level caching and disk-backed writes. Building thumbnails and choosing Offline copy can deliberately fetch content earlier.
  • Command-Line Interface (CLI): Manage your drive, authenticate, and monitor sync status directly from the terminal.
  • Responsive GTK4 Desktop App: Browse files, manage offline copies, configure options, and monitor active transfers through a modern native GUI. Network, control-socket, credential, and cache work is dispatched away from the GTK main loop.
  • Background Service Control: Keep mounts, sync, tray actions, and Drive search running after the app closes, or scope the mount service to the app session from Settings.
  • Shared Links & Invites: Browse files shared with you by other users, and view/manage your own public shared links directly in the GUI.
  • Local Backup (Computers): Sync and back up local directories (like Downloads, Documents, Pictures, etc.) directly to your Proton Drive account.
  • Locations: One page (and pdfs locations) listing every place Proton Drive occupies on this machine — the main mount plus each backed-up folder — with its mode, sync state, and whether it is read-only. Switching a folder between a full local copy and on-demand happens here.
  • System Tray Integration: Background indicator for status monitoring, quick actions, and fast sync controls.
  • Unified Search Launcher (HUD): A resident Google Drive-style launcher (pdfs-prompt) that searches Proton Drive and local files together, ranks the best matches, tolerates abbreviations and typos, and is ideal for a system-wide hotkey.
  • Secure Credential Storage: Integrates with the system Secret Service (GNOME Keyring, KWallet, etc.) with smart in-memory credential caching to avoid UI thread blockages.
  • Proton Photos Support: Access your Proton Photos timeline, view thumbnails, and download backed-up media natively (available in the GUI as a navigation tab and via the CLI).
  • Drive Thumbnails: See, build, and cache thumbnails for ordinary images and camera RAW files directly in the Files section, in any Drive folder. RAW previews are extracted locally with ExifTool; the original files are never modified.
  • File Version History: Every revision Proton Drive still holds for a file, from Versions… in the file's context menu or pdfs versions list|restore|save|rm. Restoring is server-side — no re-upload — and an old version can be written out to a local file without touching the live one.
  • Photo Favourites: Star a photo in the lightbox, filter the gallery to favourites, or use pdfs favorite <uid> / pdfs photos --favorites.
  • Photo Albums: Browse your albums — including the ones shared with you — from the Albums view of the Photos page, or with pdfs albums / pdfs album <uid>. Album contents open in the same gallery as the timeline.
  • Human Verification (CAPTCHA) Recovery: Detects sign-in gates (VPN/new IP challenges) and launches an embedded WebKitWebView dialog to safely complete the challenge, transparently retrying authentication with the earned token.
  • Selective Sync (.pdfsignore): Keep build trees, dependency directories, and editor leftovers out of synced folders using gitignore-style rules.
  • Data-Safe Offline Writes: Durable scratch/staging files and a transactional pending queue preserve acknowledged writes across network failures and restarts.

Quick Search and Media Opening

pdfs-prompt searches Drive metadata and the local home-directory index in one request. Results are ranked together rather than split by source. Matching is case-insensitive and supports exact names, prefixes, parent paths, multiple terms, punctuation-separated words, ordered abbreviations, common typos, and adjacent transpositions.

The prompt stays resident after its first launch, so invoking the shortcut again reuses and resets the existing window. Drive folders open from the mount. Audio and video results also open through FUSE, allowing media players to seek and request ranges without downloading the entire file first; ordinary Drive files are materialized into the local cache before opening.

Using your own launcher (fuzzel, rofi, wofi, …)

pdfs-prompt --dmenu runs the same search through an external dmenu-style launcher instead of the built-in window, so the HUD matches the rest of a tiling-WM desktop:

pdfs-prompt --dmenu                                   # fuzzel/rofi/wofi/tofi/bemenu/dmenu, whichever is installed
pdfs-prompt --dmenu --menu 'fuzzel --dmenu --width 60'
pdfs-prompt --dmenu --query invoice                   # skip straight to a search

A launcher filters a fixed list — it cannot ask for a new one per keystroke — so searching takes two steps, and the prompt says which step you are on:

  • Search Drive › lists the items explicitly kept offline (pdfs pins in the CLI). Type anything that isn't one of them and press Enter to search for it.
  • Drive: invoice › lists the results. Enter opens one; typing something else and pressing Enter searches again. Escape closes.

--query skips the first step. fuzzel and rofi also get file-type icons.

To make an existing keybinding use it without re-binding, and to configure the launcher command, set them in config.json:

{
  "prompt": {
    "mode": "dmenu",
    "menu": ["fuzzel", "--dmenu", "--width", "60"],
    "menu_limit": 50
  }
}

--gtk overrides "mode": "dmenu" for one invocation. A {prompt} token anywhere in menu is replaced by the prompt text; without one, the launcher's own prompt flag is appended.

Choosing How Files Open

By default every result is handed to xdg-open. An open_with block in config.json overrides that per file type — for instance opening text in Neovim inside Alacritty, while everything else still goes to the desktop:

{
  "open_with": {
    "terminal": ["alacritty", "-e"],
    "rules": [
      { "match": ["@text"], "command": ["nvim"], "terminal": true },
      { "match": ["*.png", "*.jpg"], "command": ["imv"] }
    ]
  }
}
  • match takes file-name globs (*.md, notes-*.txt) or the classes @dir, @text, @document, @image, @media, @any. First matching rule wins.
  • command is argv, not a shell line. A {} token is replaced by the path; without one the path is appended. $VAR tokens expand from the environment, so ["$EDITOR"] follows your editor.
  • "terminal": true wraps the command in terminal. When that is unset, the terminal comes from $PDFS_TERMINAL, then $TERMINAL, then the first known emulator on PATH; a bare name like TERMINAL=alacritty gains the right "run this" flag automatically.
  • "default": [...] replaces xdg-open for everything unmatched.

The rules apply to the prompt (both front ends) and to the GTK browser, so a file opens the same way wherever it was picked. Patterns are matched against the Drive name — a downloaded file is stored in the cache under its content hash, which says nothing about its type, so matching that would send everything to xdg-open.

Selective Sync (.pdfsignore)

Two-way synced folders skip paths matched by ignore rules, so syncing a project directory does not upload node_modules/, target/, or .git/.

Rules come from two places, and both apply:

  1. Per folder — a .pdfsignore file at the root of the synced folder (.protonignore also works). Gitignore syntax, including negation:

    # everything build-related
    build/
    *.log
    
    # ...except this one
    !important.log
  2. Globally — an ignore_patterns list in config.json, applied to every synced folder. When unset, sensible defaults apply: .git/, .hg/, .svn/, node_modules/, target/, .venv/, __pycache__/, *~, *.swp, *.tmp, .DS_Store, and Thumbs.db.

    {
      "ignore_patterns": ["node_modules/", "target/", "*.iso"]
    }

    Set it to [] to opt out of the defaults entirely.

Rules are re-read at the start of every sync pass, so edits take effect on the next pass without restarting the daemon.

Ignoring is never destructive. If a rule starts matching a file that was already synced, its copy on Drive is left untouched — the file simply stops being tracked. Removing the rule later picks the existing remote file back up rather than re-uploading it.

Diagnostics & Maintenance

When something looks wrong, pdfs diagnose checks the installation and prints a report. It runs without a daemon on purpose — the state worth diagnosing is usually the state where the daemon will not start:

$ pdfs diagnose
Paths
[ok  ]   state dir: /home/you/.local/state/proton-drive-linux
[ok  ]   database: /home/you/.local/state/proton-drive-linux/cache.db (170.3 MiB)

Account
[ok  ]   keyring session: you@proton.me

Daemon
[ok  ]   daemon responding
[ok  ]   mounted at: /home/you/ProtonDrive
[ok  ]   queued writes: none

No problems found.

It exits non-zero if any check fails, so it works in a health-check script.

For the local metadata database and content cache:

Command What it does
pdfs cache inspect Database size, reclaimable space, per-table row counts, cache usage against budget
pdfs cache inspect --deep Also runs SQLite's integrity check — reads every page, so it is slow on a large database
pdfs cache vacuum Checkpoints the write-ahead log and compacts the database
pdfs cache clear Deletes cached file content while keeping explicit offline copies

vacuum takes a write lock for its duration and needs room for a second copy of the database while it runs, so it is a deliberate operation rather than something the daemon does on a timer.

Before a release, run the real-kernel acceptance suite against a dedicated test account and mount. See docs/TESTING.md; it includes optional two-mount convergence checks and confines destructive operations to a fresh test directory.

Scripting (--json)

Query commands accept a global --json flag and emit machine-readable output:

$ pdfs --json sync list | jq '.items[] | select(.state != "idle") | .local_path'
$ pdfs --json cache inspect | jq '.db_reclaimable_bytes'
$ pdfs --json status | jq -r '.mount.mountpoint'

Supported on status, ls, pins, sync list, devices list, locations, transfers, activity, and cache inspect. Commands that perform an action keep their human output — a script that needs to know whether one worked has the exit code.

Two things worth relying on:

  • The payload is unwrapped. Output is {"items": […]}, not the daemon's internal {"SyncFolders": {"items": […]}}, so scripts never name an internal variant.
  • Errors still fail. A daemon-side error prints its JSON body (with a machine-readable kind) on stdout and exits non-zero, so set -e and if pdfs … behave as expected rather than treating a failed lookup as success.

Performance & Caching

The client includes several optimizations designed for high efficiency, a low memory footprint, and a responsive user experience:

  • On-Demand Block Cache: Files are read using the encrypted block geometry reported by each Drive revision. For files not explicitly kept offline, the client fetches and caches only the blocks covering requested byte ranges. This enables sequential and sparse reads (for example media streaming or metadata scanning) without downloading an entire file.
  • Disk-Backed Writes: Large file writes are staged on disk in temporary scratch files (rather than fully buffered in RAM) and track modified byte intervals. Only the unedited remote segments are fetched at commit time, keeping memory usage minimal.
  • Responsive GTK4 Loop: Potentially blocking D-Bus credential checks, control-socket requests, and cache calculations used by the GUI are dispatched to background work or fetched asynchronously.
  • Bounded Status Polling: Regular GUI status updates carry cache totals and an offline-item count rather than transferring the complete offline-copy registry every few seconds.
  • Durable Staging: Scratch metadata and staged writes are synced and atomically published before an upload is acknowledged locally. Rapid revisions supersede pending work transactionally.

Filesystem Safety

The current client strengthens the boundaries around local-only data and destructive reconciliation:

  • Truncate composes with queued revisions, preserving the authoritative prefix and correct zero-filled growth.
  • Combined move-and-rename operations are queued durably and tolerate partially completed remote state.
  • Session tombstones prevent successfully unlinked entries from reappearing through eventually consistent listings.
  • Names are valid UTF-8 and no longer than Linux's 255-byte component limit.
  • Incomplete mirror scans are non-destructive, and total-wipe protection covers every non-empty baseline.
  • Failed conflict preservation, local deletion, or staging publication does not settle a new baseline or discard the only local copy.
  • State, cache, and config directories must be real, current-user-owned 0700 directories; control sockets are 0600.

Prerequisites

To compile the application from source, install the native development packages for your distribution. Rust is installed separately in the next section. Users installing the .deb do not need to install these development packages.

Ubuntu / Debian (24.04+)

sudo apt-get update
sudo apt-get install -y \
  pkg-config \
  libfuse3-dev \
  libgtk-4-dev \
  libadwaita-1-dev \
  libwebkitgtk-6.0-dev \
  libsecret-1-dev \
  libdbus-1-dev \
  libimage-exiftool-perl

Arch Linux

sudo pacman -S --needed pkgconf fuse3 gtk4 libadwaita libsecret dbus webkitgtk-6.0 perl-image-exiftool

Fedora (44+)

sudo dnf install -y \
  pkgconf-pkg-config fuse3-devel gtk4-devel libadwaita-devel \
  webkitgtk6.0-devel libsecret-devel dbus-devel glib2-devel \
  perl-Image-ExifTool

At runtime, credential storage needs a Secret Service provider such as GNOME Keyring or KWallet, and opening files with the default handler needs xdg-utils. GNOME Shell may also need its AppIndicator extension to display the tray icon. Exact integration package names vary by distribution and desktop.


Building from Source

Ensure you have Rust and Cargo installed (minimum supported Rust version is 1.96).

  1. Clone the repository and navigate into the project directory:
    git clone https://github.com/emptyname-org/proton-drive-linux.git
    cd proton-drive-linux
  2. Build the workspace in release mode:
    cargo build --release --locked

The compiled binaries will be available under target/release/:

  • pdfs: The CLI utility.
  • pdfs-app: The GTK4 application.
  • pdfs-tray: The tray status notifier.
  • pdfs-prompt: The launcher prompt for quick HUD search.

Installation & Packages

Debian / Ubuntu release (amd64)

Tagged releases from this fork publish only a .deb package on the Releases page. Download it and install it with apt:

sudo apt install ./proton-drive-linux_*.deb

Other distributions (local builds)

Arch Linux

A local PKGBUILD is available under the packaging/ directory. You can build and install it using:

cd packaging && makepkg -fi

Fedora

A local .spec is available under packaging/. From the repository root:

sudo dnf install -y rpm-build
rpmbuild -bb packaging/proton-drive-linux.spec \
  --define "git_dir $PWD" \
  --define "_rpmdir $PWD/packaging/out" \
  --define "_builddir $PWD/packaging/build" \
  --define "_sourcedir $PWD" \
  --define "_specdir $PWD/packaging" \
  --define "_srcrpmdir $PWD/packaging/out"
sudo dnf install packaging/out/x86_64/proton-drive-linux-*.rpm

Automated Releases (CI/CD)

This project uses .github/workflows/ci.yml for pushes and pull requests, and .github/workflows/release.yml for release builds.

How it works:

  1. Triggers:
    • Pushing a git tag matching v* (for example v1.8.2+fork.2).
    • Manual runs via the Actions tab in GitHub (workflow_dispatch).
  2. Quality Gates and Build Process:
    • For tagged builds, verifies that the tag, workspace version, and packaging/PKGBUILD version agree.
    • Runs cargo fmt, Clippy with warnings denied, the locked workspace test suite, and the account-free FUSE acceptance contract.
    • Spawns an Ubuntu runner and installs GTK4, Libadwaita, FUSE3, and Secret Service packages.
    • Sets up the Rust compiler and caches build targets to speed up runs.
    • Compiles the workspace members in release mode.
  3. Artifact Packaging:
    • Builds one Debian/Ubuntu amd64 (.deb) package.
    • Includes the four binaries, systemd user service, desktop entry, icon, license, and tray autostart entry.
  4. Publishing:
    • Creates a GitHub Release matching the pushed tag and uploads only the .deb package.
    • For manual runs, exposes the same .deb as a workflow artifact for testing.

License

The code is licensed under the MIT License.

The application icon is a composite containing Tux, originally created by Larry Ewing using GIMP. The SVG declares the Free Art License and is distributed separately from the MIT-licensed code. See the icon attribution and license notice.

About

Experimental, unofficial Proton Drive desktop client for Linux with native GTK controls, local and RAW thumbnails, configurable background service lifecycle, and Debian packaging.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages