SyncWarden icon
SyncWarden

Lightweight system tray wrapper for Syncthing. Cross-platform, native-feeling, ~10 MB.

Go 1.24+ Platform: Windows | Linux | macOS MIT License
Latest Release CI

Tray icon states: idle, syncing, paused, error, disconnected

## Features - **Tray icon** with 5 states: idle (green), syncing (blue), paused (gray), error (red), disconnected (dark gray) - **Real-time monitoring** via Syncthing event API (long-polling) + periodic health checks - **Transfer rates** in tooltip and menu - **Context menu**: folder list, recent files, conflict counter, pause/resume, rescan, restart - **Embedded admin panel** using the system browser engine (Edge WebView2 / WebKit / WebKit2GTK) - **OS notifications** for sync complete, device connect/disconnect, new device requests, conflicts - **Settings** toggleable via menu checkboxes (persisted to JSON config) - **Auto-start Syncthing** with crash recovery and supervised restart - **API key auto-discovery** from Syncthing's `config.xml` - **Syncthing detection** — prompts with download link if Syncthing is not installed ## How It Works SyncWarden sits in the system tray and communicates with a local Syncthing instance via its REST API. It never touches your files directly — all sync operations are handled by Syncthing itself. ```mermaid graph TB subgraph OS["Operating System"] tray["System Tray Icon"] notif["OS Notifications"] browser["Default Browser"] fm["File Manager"] end subgraph SW["SyncWarden"] subgraph tray_bin["syncwarden (tray binary)"] app["Tray App"] menu["Context Menu"] mon["Monitor"] evl["Event Listener
long-poll /rest/events"] poll["Health Poller
every 3s"] proc["Process Manager
auto-start + restart"] cfg["Config
JSON file"] end panel_bin["syncwarden-panel
(embedded browser)"] setup_bin["syncwarden-setup
(installer)"] end subgraph ST["Syncthing (localhost:8384)"] api["REST API"] webui["Web UI"] sync["Sync Engine"] end remote["Remote Devices"] %% Tray app connections app --> tray app --> notif app --> menu menu -- "Open folder" --> fm menu -- "Open Admin Panel" --> panel_bin panel_bin -- "renders" --> webui menu -- "Install Syncthing..." --> browser %% Monitor connections app --> mon mon --> evl mon --> poll evl -- "events" --> api poll -- "health + connections" --> api menu -- "pause / rescan / restart" --> api %% Process management app --> proc proc -- "start / stop / supervise" --> ST %% Config app --> cfg %% Syncthing sync <--> remote %% Styling classDef swbin fill:#2d5a27,stroke:#4a8,color:#fff classDef stbox fill:#1a4a6a,stroke:#3a8abf,color:#fff classDef osbox fill:#555,stroke:#888,color:#fff class app,menu,mon,evl,poll,proc,cfg swbin class panel_bin,setup_bin swbin class api,webui,sync stbox class tray,notif,browser,fm osbox ``` ### Data Flow 1. **Event Listener** long-polls `GET /rest/events` — receives real-time sync events (file changes, device connections, folder state changes) 2. **Health Poller** checks `/rest/noauth/health` and `/rest/system/connections` every 3 seconds — detects connection loss and calculates transfer rates 3. **Monitor** aggregates both streams into a single status snapshot (icon state, device count, rates, recent files, conflicts) 4. **Tray App** renders the status as an icon + tooltip + menu updates, and dispatches OS notifications for configured events ## Architecture SyncWarden ships as three separate binaries to avoid main-thread conflicts between systray and webview: | Binary | Purpose | CGO | |--------|---------|-----| | `syncwarden` | Tray icon, menu, monitoring, notifications, process management | No | | `syncwarden-panel` | Embedded browser showing Syncthing admin UI | Yes | | `syncwarden-setup` | Cross-platform installer / uninstaller | No | ### Project Layout ``` cmd/ syncwarden/ Entry point for tray binary panel/ Entry point for embedded browser panel setup/ Cross-platform installer icongen/ Icon generation utility (dev tool) internal/ config/ Config persistence + platform-specific paths icons/ Pre-rendered tray icons (5 states, PNG + ICO) monitor/ State aggregation: folders, speed, recent files, conflicts notify/ OS notification wrapper syncthing/ REST API client, event listener, process manager, detection tray/ Tray UI: menu, tooltip, panel launcher ``` ## Installation ### From release Download the latest release for your platform from [Releases](https://git.davoryn.de/calic/syncwarden/releases) and run `syncwarden-setup`. If Syncthing is not installed, the setup will open the [download page](https://syncthing.net/downloads/) for you. ### From source Requires Go 1.24+ and CGO (MinGW-w64 on Windows) for the panel binary. ```bash # Tray binary (pure Go, no CGO needed) go build -o syncwarden ./cmd/syncwarden # Panel binary (requires CGO + C++ compiler) CGO_ENABLED=1 go build -o syncwarden-panel ./cmd/panel # Setup go build -o syncwarden-setup ./cmd/setup ``` ## Configuration Config file location: - **Windows**: `%LOCALAPPDATA%\syncwarden\config.json` - **Linux**: `~/.config/syncwarden/config.json` - **macOS**: `~/Library/Application Support/syncwarden/config.json` The API key is auto-discovered from Syncthing's `config.xml` on first run. All settings are configurable via the tray menu. ## Dependencies ### Tray binary (`syncwarden`) | Dependency | Purpose | |------------|---------| | [energye/systray](https://github.com/energye/systray) | System tray integration (icon, menu, click events) | | [fogleman/gg](https://github.com/fogleman/gg) | 2D graphics for icon rendering | | [gen2brain/beeep](https://github.com/gen2brain/beeep) | Cross-platform OS notifications | ### Panel binary (`syncwarden-panel`) | Dependency | Purpose | |------------|---------| | [webview/webview_go](https://github.com/webview/webview_go) | Embedded browser (Edge WebView2 / WebKit / WebKit2GTK) | ### Setup binary (`syncwarden-setup`) No external dependencies — uses only the Go standard library and `internal/config` for path resolution. ### Build-time only | Tool | Purpose | |------|---------| | [goreleaser/nfpm](https://github.com/goreleaser/nfpm) | `.deb` package generation (CI only) | ## Syncthing REST API Usage SyncWarden communicates with Syncthing via its local REST API. All requests go to `localhost:8384` (configurable) and are authenticated with the `X-API-Key` header. | Endpoint | Purpose | |----------|---------| | `GET /rest/noauth/health` | Connection health check (no auth) | | `GET /rest/system/connections` | Device status + byte counters for rate calculation | | `GET /rest/config` | Folder and device configuration | | `GET /rest/db/status` | Per-folder sync state | | `GET /rest/events` | Long-poll event stream (30s timeout) | | `POST /rest/system/pause` | Pause all syncing | | `POST /rest/system/resume` | Resume all syncing | | `POST /rest/db/scan` | Trigger folder rescan | | `POST /rest/system/restart` | Restart Syncthing | ## License MIT