Detect missing Syncthing, rewrite README with architecture diagram
Some checks failed
Release / build (push) Failing after 2m53s

Add Syncthing installation detection (PATH + config file check) to both
the tray app and setup installer. When missing, the tray shows an
"Install Syncthing..." menu item and the setup opens the download page.

Rewrite README with Mermaid topology graph, per-binary dependency tables,
project layout, API endpoint reference, and shields.io badges.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-03-04 00:08:34 +01:00
parent 11e5c9b915
commit 99eeffcbe4
6 changed files with 259 additions and 26 deletions

192
README.md
View File

@@ -1,41 +1,160 @@
# SyncWarden
<h1 align="center">
<img src="assets/icon-128.png" width="80" alt="SyncWarden icon" /><br />
SyncWarden
</h1>
Lightweight system tray wrapper for [Syncthing](https://syncthing.net/). Cross-platform, native-feeling, ~10 MB.
<p align="center">
Lightweight system tray wrapper for <a href="https://syncthing.net/">Syncthing</a>. Cross-platform, native-feeling, ~10 MB.
</p>
<p align="center">
<img src="https://img.shields.io/badge/Go-1.24+-00ADD8?logo=go&logoColor=white" alt="Go 1.24+" />
<img src="https://img.shields.io/badge/Platform-Windows%20|%20Linux%20|%20macOS-informational" alt="Platform: Windows | Linux | macOS" />
<img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License" />
<br />
<a href="https://git.davoryn.de/calic/syncwarden/releases"><img src="https://img.shields.io/badge/release-v0.2.0-blue?logo=gitea&logoColor=white" alt="Latest Release" /></a>
<a href="https://git.davoryn.de/calic/syncwarden/actions"><img src="https://img.shields.io/badge/CI-Gitea%20Actions-success?logo=gitea&logoColor=white" alt="CI" /></a>
</p>
<p align="center">
<img src="assets/icon-preview.png" alt="Tray icon states: idle, syncing, paused, error, disconnected" />
</p>
## 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)
- **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
- **API key auto-discovery** from Syncthing's config.xml
- **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<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
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
| Binary | Purpose |
|--------|---------|
| `syncwarden` | Tray icon, menu, API polling, notifications, process management |
| `syncwarden-panel` | Embedded browser showing Syncthing admin panel |
| `syncwarden-setup` | Cross-platform installer |
SyncWarden ships as three separate binaries to avoid main-thread conflicts between systray and webview:
Separate binaries 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 and run `syncwarden-setup`.
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).
Requires Go 1.24+ and CGO (MinGW-w64 on Windows) for the panel binary.
```bash
# Tray binary (pure Go on Windows)
# Tray binary (pure Go, no CGO needed)
go build -o syncwarden ./cmd/syncwarden
# Panel binary (requires CGO + C++ compiler)
@@ -52,14 +171,49 @@ Config file location:
- **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.
The API key is auto-discovered from Syncthing's `config.xml` on first run. All settings are configurable via the tray menu.
## Dependencies
- [energye/systray](https://github.com/energye/systray) — System tray
- [webview/webview_go](https://github.com/webview/webview_go) — Embedded browser
- [fogleman/gg](https://github.com/fogleman/gg) — Icon rendering
- [gen2brain/beeep](https://github.com/gen2brain/beeep) — OS notifications
### 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