A two-way OneDrive client for Linux built on FUSE. OneDrive is mounted as a virtual filesystem — all files and folders appear instantly from a local metadata index, file content is fetched transparently on first open, and local changes (create, edit, delete, rename) are synced back to OneDrive automatically.
- Read: on-demand download — files are fetched only when opened, not on directory browse
- Write: create, edit, delete, and rename files and folders — changes are uploaded to OneDrive on close
- File managers and thumbnail renderers are blocked from triggering downloads (detected by process name)
- Editor temp files (vim swap, Office lock files,
.tmp) are silently redirected to/tmpand never uploaded - Remote changes appear within ~30 seconds via background delta polling
- Auto-unmount on process exit — no zombie mounts requiring a reboot
- OAuth2 authentication with automatic token refresh
- OneDrive Personal only
- Python 3.10+
fuse3andlibfuse3-devsystem packages
sudo apt install fuse3 libfuse3-dev # Debian/Ubuntu/Pop!_OSgit clone https://github.com/ccampora/py-onedrive.git
cd py-onedrive
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtOn the first run a browser window opens for Microsoft account login. After authorizing you are redirected to a URL like:
https://login.microsoftonline.com/common/oauth2/nativeclient?code=M.C544_SN1...
Paste the full URL or just the code value into the console. Tokens are saved to ~/.py-onedrive/.py-onedrive-secrets and refreshed automatically on subsequent runs.
./start.shstart.sh handles the full lifecycle: kills any existing mount process, cleans up stale FUSE transport endpoints, creates the mountpoint if needed, then launches mount.py and waits to confirm it mounted successfully.
Extra flags are passed through to mount.py:
./start.sh --debug
./start.sh --poll-interval 60source .venv/bin/activate
python mount.pyOptions:
--mountpoint DIR Mount point (default: ~/Onedrive)
--poll-interval N Seconds between metadata syncs (default: 30)
--max-downloads N Max concurrent file downloads (default: 4)
--debug Verbose logging and FUSE debug mode
fusermount3 -u ~/Onedrive
# or Ctrl+C if running in the foregroundDirectory listings are served entirely from the local metadata index — no network calls on browse. When a file is opened with an application, it is downloaded from OneDrive and cached locally. Subsequent opens are instant from the local cache.
File managers and thumbnail renderers (cosmic-files, nautilus, evince-thumbnai, tumbler, etc.) are detected by process name and blocked from triggering downloads. Only applications that explicitly open a file (Evince, LibreOffice, a text editor, etc.) cause a fetch.
Changes made inside ~/Onedrive are synced back to OneDrive:
| Operation | Behaviour |
|---|---|
| Create file | Uploaded to OneDrive when the file is closed |
| Edit file | Current content downloaded to a temp file, uploaded on close |
| Create folder | Created on OneDrive immediately |
| Delete file or folder | Deleted from OneDrive immediately |
| Rename / move | Updated on OneDrive immediately via a single API call |
New files and folders appear in directory listings immediately after creation — no need to refresh.
Editor temp files are intercepted at create() time and redirected entirely to /tmp. They are invisible in directory listings and never reach OneDrive. Filtered patterns:
- Vim:
.*.swp,.*.swx, numeric write-probe files (e.g.4913) - Generic:
*.tmp, files ending with~ - Office:
~$*lock files,.~lock.*LibreOffice locks
The background poller calls the OneDrive delta API every 30 seconds. When changes are detected, the local metadata index is updated and the affected directory inodes are invalidated so ls reflects the change immediately on the next call.
cp onedrive.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now onedrive
systemctl --user status onedriveA native panel applet for the COSMIC desktop that shows sync status, pending files, and provides quick actions (Sync Now, Pause, Resume).
Requires Rust (stable) and the COSMIC SDK dependencies:
cd applet/cosmic
cargo build --release# Install the binary
cp applet/cosmic/target/release/cosmic-onedrive-applet ~/.local/bin/
# Install the desktop entry so the panel can discover the applet
cp /usr/share/applications/com.github.ccampora.OneDriveApplet.desktop ~/.local/share/applications/If you don't already have the desktop entry, create it:
mkdir -p ~/.local/share/applications
cat > ~/.local/share/applications/com.github.ccampora.OneDriveApplet.desktop <<'EOF'
[Desktop Entry]
Name=OneDrive Applet
Comment=OneDrive sync status applet
Exec=cosmic-onedrive-applet
Icon=cloud
Type=Application
NoDisplay=true
X-CosmicApplet=true
Categories=System;
EOFOpen Settings → Desktop → Panel → Applets and add "OneDrive Applet" to the right wing. The panel will manage the applet lifecycle automatically (start on login, restart on crash).
The panel icon changes based on connection state:
| State | Icon |
|---|---|
| Connected / idle | Light gray cloud |
| Syncing / uploading / downloading | Cloud with sync arrows |
| Paused | Cloud with pause bars |
| Error | Cloud with warning triangle |
| Disconnected | Dimmed cloud with red X |
| Path | Purpose |
|---|---|
~/.py-onedrive/.py-onedrive-secrets |
OAuth2 access and refresh tokens |
~/.py-onedrive/.py-onedrive-deltalink |
Delta sync cursor (resumes from last known state) |
~/.py-onedrive/.py-onedrive-inodes |
Stable inode mapping (survives process restarts) |
~/.py-onedrive/db/ |
Item metadata cache — one JSON file per OneDrive item |
~/.py-onedrive/cache/ |
Downloaded file content cache |
~/Onedrive/ |
FUSE mount point |
- Shared folders — only the user's own drive is currently supported
- Large file uploads — files over ~150 MB should use the Graph API upload session for reliability
- Cache eviction — the content cache grows unboundedly; an LRU policy would bound disk usage
- Conflict resolution — no handling when the same file is modified both locally and remotely