A lightweight, native menubar/system tray application for Filen.io cloud sync on macOS and Linux.
- Tray-first interface - Stays out of the Dock/taskbar; the only app window is the optional sign-in flow
- In-app login - Sign in, complete two-factor authentication, and persist the Filen CLI session without opening a terminal
- CLI-owned credentials - Credentials are sent to the bundled CLI through a pseudo-terminal, never through process arguments, environment variables, or application logs
- Real-time sync status - Shows current sync state with live file count updates
- Live menu updates - Menu items update in-place without closing the menu
- Recent activity - Review the latest uploads, downloads, removals, and other file operations
- Native platform styling - A macOS-style login window on macOS and a KDE/Plasma-style window on Linux
- Cross-platform tray support - Tauri's native tray on macOS and StatusNotifierItem (SNI) via
ksnion Linux - Auto-sync - Optionally start syncing on launch
- Bundled sync engine - Ships a pinned classic CLI patched with the newer Filen sync engine's memory fixes
- Logout confirmation - Prevents accidental logout with a confirmation dialog
- Update check - Manually check GitHub for a newer release from the tray menu
No separate Filen CLI or Node.js runtime is required after installation. The
app bundles v0.0.39-menubar.2: a focused build of classic CLI v0.0.39 with
@filen/sync v0.3.7 and @filen/sdk v0.4.2. It runs on an app-owned copy of
the official Node.js v24.18.1 runtime. Neither the helper nor this Node.js
runtime is resolved from PATH: the runtime stays private to the application
bundle on macOS and under /usr/lib/Filen Menubar/filen-cli/ in Linux packages.
The newer sync engine bounds large tree-building work, avoids deep-cloning complete trees, and uses a more compact persisted state. The fork also stops retaining an unused in-memory CLI log during continuous sync and omits ignored- tree inventories that the menubar does not consume when no explicit CLI log file is requested. A transient realtime-socket error now follows the SDK's reconnect path instead of terminating the sync process. Unused drive, S3, and WebDAV commands and their dependencies are excluded from the bundled build. Its self-updater is disabled; app releases update the host, helper, and runtime together.
The pinned inputs, patches, resolved dependency graph, license information, and
release-compliance tooling live under third-party/filen-cli/. Release assets
also include corresponding source, a software bill of materials (SBOM), and
third-party notices.
Existing classic-CLI sessions are reused, so upgrades do not require signing in
again. Do not run an older continuous-sync CLI against the same sync pair while
Filen Menubar is running. Its compact sync cache is isolated under state/v3,
leaving an older classic CLI's state/v2 cache untouched for rollback. The
first patched run therefore performs a full tree scan.
macOS:
xcode-select --installRelease builds currently target Apple silicon and require macOS 13.5 or newer.
Linux (Debian/Ubuntu):
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file \
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-devLinux (Fedora):
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file \
libxdo-devel libappindicator-gtk3-devel librsvg2-develLinux (Arch/CachyOS/Manjaro):
sudo pacman -S webkit2gtk-4.1 libappindicator-gtk3 librsvg base-devel \
curl wget file openssl libxdoNote: The
webkit2gtk-4.1package is essential - it providesjavascriptcoregtk-4.1required by Tauri.
Linux release builds target x86_64, require glibc 2.34 or newer, and bundle the Node.js runtime used by the sync backend.
Download the latest release from the Releases page:
- macOS:
.dmginstaller - Linux (Debian/Ubuntu):
.debpackage - Linux (Fedora/RHEL):
.rpmpackage - Linux (Arch):
filen-menubar-binon the AUR, or the.pkg.tar.zstattached to each release
# Install the deb package
sudo dpkg -i ./Filen.Menubar_*_amd64.deb
# Install any missing dependencies
sudo apt-get install -f# Install the rpm package
sudo rpm -i ./Filen.Menubar-*.rpm
# Or with dnf
sudo dnf install ./Filen.Menubar-*.rpmInstall from the AUR with your usual helper:
paru -S filen-menubar-bin # or: yay -S ...The patched sync backend is included in filen-menubar-bin; there is no
separate CLI or system Node.js runtime dependency. The AUR package supports
x86_64 and carries the same app-owned runtime as the release .deb.
This is the recommended route: pacman owns the files, so pacman -Qo works and
updates arrive with your normal paru -Sua. The package repacks the release
binary rather than compiling, so it installs in seconds.
Without an AUR helper, grab the .pkg.tar.zst from the
latest release:
sudo pacman -U filen-menubar-bin-*-x86_64.pkg.tar.zstAutostart is not configured by either route. To enable it:
cp /usr/share/applications/filen-menubar.desktop ~/.config/autostart/Use the install script for a complete from-source installation with autostart:
git clone https://github.com/philippgerard/filen-menubar.git
cd filen-menubar
./scripts/install-linux.sh installThis will:
- Install missing distro build dependencies (Bun must already be installed at the exact version listed above)
- Build the application
- Install the host executable to
/usr/local/binand its private sync backend under/usr/local/lib/Filen Menubar/ - Create desktop entry and icons
- Configure autostart on login
Note:
/usr/local/binnormally precedes/usr/binonPATH, so a script-installed binary shadows the packaged one. Pick one route or the other — if you switch to the AUR package, remove the old copy first with./scripts/install-linux.sh uninstall.
Or build manually:
# Install build dependencies
sudo pacman -S webkit2gtk-4.1 base-devel curl wget file openssl libxdo \
libappindicator-gtk3 librsvg nodejs npm rust
# Install Bun v1.3.14, then clone and build
git clone https://github.com/philippgerard/filen-menubar.git
cd filen-menubar
npm ci
cargo install tauri-cli --version "^2" --locked
npm run tauri build
# Binary will be in src-tauri/target/release/filen-menubarThe build fails closed if Bun is missing or is not exactly v1.3.14.
Note: AppImage is not supported because its sandboxing prevents reliable access to the bundled sync-backend resources.
The install script supports several commands:
./scripts/install-linux.sh install # Full install (build + setup + autostart)
./scripts/install-linux.sh build # Build only
./scripts/install-linux.sh setup # Install pre-built binary + autostart
./scripts/install-linux.sh autostart # Setup autostart only
./scripts/install-linux.sh uninstall # Remove everything
./scripts/install-linux.sh deps # Install dependencies only# Clone the repository
git clone https://github.com/philippgerard/filen-menubar.git
cd filen-menubar
# Install dependencies
npm ci
# Install Tauri CLI
cargo install tauri-cli --version "^2" --locked
# Run in development mode
npm run tauri dev
# Build for production
npm run tauri buildConfiguration is stored in a JSON file:
- macOS:
~/Library/Application Support/filen-menubar/config.json - Linux:
~/.config/filen-menubar/config.json
{
"localPath": "~/Filen",
"remotePath": "/",
"syncMode": "twoWay",
"autoStart": true,
"locale": "de",
"loggingEnabled": true,
"logLevel": "info",
"ignore": ["node_modules", "*.tmp"],
"excludeDotFiles": false
}| Option | Description | Default |
|---|---|---|
localPath |
Local folder to sync | ~/Filen |
remotePath |
Remote Filen path | / |
syncMode |
Sync direction: twoWay, localToCloud, cloudToLocal, localBackup, or cloudBackup |
twoWay |
autoStart |
Start syncing on app launch | true |
locale |
UI language (en, de). If omitted, uses system locale |
System locale |
loggingEnabled |
Enable file logging for debugging | false |
logLevel |
Log verbosity: trace, debug, info, warn, error |
info |
ignore |
File or directory patterns excluded from sync | [] |
excludeDotFiles |
Exclude files and directories whose names start with . |
false |
File logging is disabled by default. When enabled, logs are written to a single file that is overwritten on each app launch:
- macOS:
~/Library/Logs/io.filen.menubar/filen.log - Linux:
~/.local/share/filen-menubar/logs/filen.log
To enable logging, add "loggingEnabled": true to your config file. You can also set the log level with "logLevel": "debug" for more verbose output.
Access logs via the "Show Logs..." menu item, or use the helper script:
./scripts/logs.shThe "Recent Activity..." window retains the newest 500 file operations observed by this client, including uploads, downloads, directory changes, removals, renames, and failed operations. Only paths relative to the configured sync root are stored. Use Clear in the activity window to remove the history.
- macOS:
~/Library/Application Support/filen-menubar/activity-history.json - Linux:
~/.local/share/filen-menubar/activity-history.json
- Launch: Start the menubar app
- Click "Login..." in the tray menu
- Sign in: Enter your Filen credentials and, when required, your two-factor code
- Sync: The login window closes and syncing starts automatically
The app uses its bundled backend for authentication as well as syncing, so the tray login is the supported sign-in path.
The sign-in screen is a local page bundled with Filen Menubar, not a hosted Filen website. The app starts its bundled Filen CLI in a pseudo-terminal and responds to its normal interactive prompts:
- The CLI receives email, password, and two-factor codes through its standard input rather than command-line arguments or environment variables.
- Rust-side secret buffers are zeroed after use, and credentials are never written to application logs.
- Filen Menubar answers
yto the CLI's Keep me logged in? prompt. The CLI encrypts the saved session and protects its encryption key with macOS Keychain or the Linux Secret Service. - If secure system storage is unavailable, the app refuses the CLI's plaintext-storage fallback.
For two-factor-enabled accounts, Filen may send one failed-login alert followed by the successful-login alert. The classic CLI first submits the password to learn that a two-factor code is required, then submits the complete login. The bundled login uses that same upstream authentication flow.
Status: Synced
Up to date ← Shows "X files remaining..." when syncing
─────────────
Open Local Folder → Opens your local sync folder in Finder/file manager
Open Web UI → Opens Filen web interface in browser
Recent Activity... → Shows the latest file operations performed by this client
─────────────
Pause Syncing → Pause/resume syncing (label toggles with state)
Logout → Stop sync and clear session (with confirmation)
─────────────
Settings... → Opens config file in editor
Show Logs... → Opens log folder (for debugging)
About Filen Menubar → Shows version and app info
Check for Updates... → Checks GitHub for a newer release, opens download page
─────────────
Quit → Stop syncing and exit
| State | Description |
|---|---|
| Not Logged In | No CLI session found. Choose Login... from the tray menu. |
| Synced | All files are up to date |
| Syncing... | Files are being transferred (shows count) |
| Paused | Sync is paused |
| Sync Error | An error occurred during sync |
Hover over the tray icon to see real-time status:
Filen - Syncedwhen idleFilen - Syncing 5 fileswhen transferring
The tooltip updates in real-time, even while the menu is open.
┌─────────────────────────────────────────────────┐
│ Filen Menubar │
├─────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ macOS Tray │ │ Linux Tray │ │
│ │ (Tauri Icon) │ │ (ksni) │ │
│ └────────┬────────┘ └──────────┬──────────┘ │
│ │ │ │
│ └──────────┬───────────┘ │
│ │ │
│ ┌───────────────────▼──────────────────────┐ │
│ │ Optional Login Window │ │
│ │ local UI → PTY → interactive CLI auth │ │
│ └───────────────────┬──────────────────────┘ │
│ │ │
│ ┌───────────────────▼──────────────────────┐ │
│ │ App State │ │
│ │ (sync status, login state, pending cnt) │ │
│ └───────────────────┬──────────────────────┘ │
│ │ │
│ ┌───────────────────▼──────────────────────┐ │
│ │ CLI Manager │ │
│ │ (subprocess, JSON event parsing) │ │
│ └───────────────────┬──────────────────────┘ │
│ │ │
└──────────────────────┼──────────────────────────┘
│
┌────────▼────────┐
│ Bundled CLI fork│
│ @filen/sync .3.7│
│ --verbose mode │
└─────────────────┘
The app runs the Filen CLI with --verbose flag to get JSON event output. Key events:
| Event | Description |
|---|---|
cycleProcessingTasksStarted |
Sync cycle starting, set state to Syncing |
deltasCount |
Number of files to sync |
task-level transfer + success/error |
A file operation completed; update pending count and recent activity |
cycleSuccess |
Sync cycle completed, set state to Synced |
cycleError |
Sync cycle failed, set state to Error |
- Tauri v2 - Cross-platform app framework
- Rust - Backend logic
- ksni - Linux StatusNotifierItem (KDE support)
- tokio - Async runtime for subprocess management
- portable-pty - Interactive CLI login without exposing secrets as arguments
- zeroize - Clears credentials from memory after use
- tauri-plugin-dialog - Native dialogs
- The app hides from the Dock (menubar-only)
- Uses Tauri's native TrayIcon with in-place menu updates
- Template icon support for automatic dark/light mode
- The login and Recent Activity windows follow macOS typography, spacing, controls, and window sizing
- Settings open in TextEdit for easy editing
- Uses ksni for native StatusNotifierItem support
- First-class KDE Plasma integration
- No libappindicator fallback issues
- The login and Recent Activity windows follow KDE/Plasma control and color conventions
- Requires AppIndicator extension
- Works via ksni's SNI protocol
- CLI lineage: The bundled backend remains the classic TypeScript CLI, run by its app-owned Node.js runtime. The Rust rewrite is not a drop-in replacement for the current continuous-sync event integration.
- Backend scope: The focused helper includes the sync and interactive-login surfaces used by Filen Menubar. It does not bundle the classic CLI's filesystem utilities, drive, S3, or WebDAV servers.
- Storage Display: The current CLI integration does not expose account storage quota.
# Install the pinned JavaScript dependencies, then start with debug logging
npm ci
RUST_LOG=debug npm run tauri devThe scripts/ directory contains helper scripts for common tasks:
| Script | Description |
|---|---|
./scripts/build-filen-cli.sh |
Build and verify the pinned bundled backend |
./scripts/check-filen-cli-version.sh |
Verify the generated backend version and runtime |
./scripts/check-filen-cli-state-patch.sh |
Verify the isolated state-v3 patch |
./scripts/package-filen-cli-source.sh |
Create the backend corresponding-source archive |
./scripts/install-linux.sh |
Build and install from source on Linux |
./scripts/logs.sh |
Open log folder for current platform |
# Install the pinned JavaScript dependencies
npm ci
# Build the pinned patched CLI (also runs automatically before checks/builds)
npm run build:filen-cli
# Run with info logging
RUST_LOG=info npm run tauri dev
# Formatting, Clippy, and all Rust tests
npm run check
# Build an unsigned local production bundle
npm run tauri buildApplication versions must match in package.json, package-lock.json,
src-tauri/Cargo.toml, src-tauri/Cargo.lock, and
src-tauri/tauri.conf.json.
Create a reviewed v* tag and dispatch the Release workflow from main
with its numeric version. The workflow rejects a tag whose commit is not already
on main or whose five app version manifests disagree. It then:
- Rebuilds and verifies the pinned CLI fork and runs the test suite on macOS and Linux.
- Builds a signed and notarized Apple Silicon DMG.
- Builds Debian, RPM, and Arch Linux packages.
- Produces corresponding source, an SBOM, third-party notices, and checksums, then creates a draft GitHub release containing all artifacts.
- Publishes
filen-menubar-binto the AUR after the draft release is reviewed and published.
Locale changes not reflected?
The rust_i18n crate compiles translations at build time. If you modify locale files (src-tauri/locales/*.yml), you need a clean rebuild:
cargo clean --manifest-path src-tauri/Cargo.toml
RUST_LOG=debug npm run tauri devsrc/
├── login.html # Optional local sign-in window
├── login.css # macOS and KDE/Plasma presentation
└── login.js # Login UI state and Tauri commands
src-tauri/
├── src/
│ ├── lib.rs # Main app setup, action dispatch, status loop
│ ├── actions.rs # Tray action handlers (command pattern)
│ ├── cli/ # CLI subprocess management, JSON event parsing
│ ├── config.rs # Configuration loading/saving
│ ├── credentials.rs # CLI session detection
│ ├── login.rs # PTY-driven interactive login and lifecycle handling
│ ├── state.rs # Shared app state (sync status, pending count)
│ ├── update.rs # GitHub release update check
│ └── tray/
│ ├── mod.rs # TrayInterface trait
│ ├── macos.rs # macOS tray implementation (Tauri TrayIcon)
│ └── linux.rs # Linux tray implementation (ksni)
├── Cargo.toml
└── tauri.conf.json
The Filen Menubar host application is MIT-licensed. The separately executed, modified Filen CLI backend is AGPL-3.0-only. Its app-owned Node.js runtime is MIT-licensed and carries Node.js's third-party notices. Complete notices and corresponding source are included with release artifacts. Bun is used only as a pinned build/test tool and is not distributed in the application bundles.