GO-2026-4340, GO-2026-4337, GO-2025-4175 — all fixed in Go 1.24.13. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

SyncWarden
Lightweight system tray wrapper for Syncthing. Cross-platform, native-feeling, ~10 MB.
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.
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<br/><small>long-poll /rest/events</small>"]
poll["Health Poller<br/><small>every 3s</small>"]
proc["Process Manager<br/><small>auto-start + restart</small>"]
cfg["Config<br/><small>JSON file</small>"]
end
panel_bin["syncwarden-panel<br/><small>(embedded browser)</small>"]
setup_bin["syncwarden-setup<br/><small>(installer)</small>"]
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
- Event Listener long-polls
GET /rest/events— receives real-time sync events (file changes, device connections, folder state changes) - Health Poller checks
/rest/noauth/healthand/rest/system/connectionsevery 3 seconds — detects connection loss and calculates transfer rates - Monitor aggregates both streams into a single status snapshot (icon state, device count, rates, recent files, conflicts)
- 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 and run syncwarden-setup.
If Syncthing is not installed, the setup will open the download page for you.
From source
Requires Go 1.24+ and CGO (MinGW-w64 on Windows) for the panel binary.
# 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 | System tray integration (icon, menu, click events) |
| fogleman/gg | 2D graphics for icon rendering |
| gen2brain/beeep | Cross-platform OS notifications |
Panel binary (syncwarden-panel)
| Dependency | Purpose |
|---|---|
| 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 | .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