Desktop client for one or more self-hosted Gotify servers. The app shows new messages as desktop notifications, keeps a short mixed history, and stays available from the system tray.
Prebuilt packages are available for Linux (x86_64), Windows (x86_64), and macOS (Apple Silicon).
Connect or manage servers. The password is not stored. |
Recent notifications (mixed timeline with server labels) |
Send a message to an application on a chosen server |
- Connect to one or more Gotify servers with username and password. The password is not stored; the app creates a client token per server.
- Parallel live streams: desktop notifications from every enabled server. With more than one server, toast titles are prefixed with the server label.
- System tray on Linux, Windows, and macOS: open the window, Servers (switch active), recent notifications, send a message, settings, start at login, and quit. macOS also keeps the application menu.
- Settings: list of servers (set active, rename, remove) plus a form to add another account. Re-connecting the same URL and username refreshes that account instead of duplicating it.
- History of the last 100 notifications across all servers, each with a server label. Copy an entry as Markdown or clear the list. Store toast notifications only, or every message.
- Send a message: choose a server, pick one of its Gotify applications, and submit a title, body, and priority. Application tokens stay inside the app.
- Updates on startup (at most every 24 hours) and via Check for Updates. The app asks before installing and checks the file against
SHA256SUMS. - Start at login.
- Closing the window leaves the app in the tray. Quit from the tray menu or the application menu.
- Window size, position, and maximised state are remembered. Positions on a monitor left of or above the primary display may be discarded. Under Wayland the system often reports
0,0, so only size and maximised state are restored. - The Gotify web UI for the active server is embedded in the app. Switching the active server reloads that UI.
- Interface languages: German, English, French, and Spanish. The default is the operating-system language, or English if that language is not bundled. Change it via Language in the tray or the application menu.
The current version is on the releases page. The links below always point at that release.
| System | Recommended | Alternative |
|---|---|---|
| Linux x86_64 | AppImage | Binary |
| Windows x86_64 | Setup | Portable EXE |
| macOS Apple Silicon | DMG | ZIP |
Checksums: SHA256SUMS. The packages are not signed.
Other architectures (Linux arm64, Windows ARM, Intel Macs) are not built.
The AppImage and the binary need GTK 4 and WebKitGTK 6.0 from the system. The AppImage does not bundle those libraries. The tray icon also needs an AppIndicator library and a panel that hosts status icons.
Ubuntu 24.04:
sudo apt install libgtk-4-1 libwebkitgtk-6.0-4 libayatana-appindicator3-1 libfuse2t64libfuse2t64 is only required for the AppImage. Without FUSE:
chmod +x gotify-desktop-linux-amd64.AppImage
APPIMAGE_EXTRACT_AND_RUN=1 ./gotify-desktop-linux-amd64.AppImageWith FUSE:
chmod +x gotify-desktop-linux-amd64.AppImage
./gotify-desktop-linux-amd64.AppImageThe binary:
chmod +x gotify-desktop-linux-amd64
./gotify-desktop-linux-amd64Verify the download (SHA256SUMS in the same directory):
sha256sum -c SHA256SUMSFedora and similar distributions, tray library:
sudo dnf install libappindicator-gtk3 gnome-shell-extension-appindicatorArch:
sudo pacman -S libappindicator-gtk3GTK 4 and WebKitGTK 6.0 must be installed there as well.
KDE Plasma, Xfce, MATE, and Cinnamon usually show the icon on their own. GNOME 45 and later has no classic tray. Without an extension the app still runs, but after sign-in the window disappears on purpose because it moves to the tray.
Ubuntu GNOME:
sudo apt install libayatana-appindicator3-1 gnome-shell-extension-appindicatorThen enable AppIndicator and KStatusNotifierItem Support and log out and back in if the icon is missing. It sits in the top bar, not in the Activities grid.
If the switch stays greyed out:
gsettings set org.gnome.shell disable-user-extensions false
gnome-extensions enable appindicatorsupport@rgcjonas.gmail.comHyprland, Sway, and other wlroots setups need a panel with a Status Notifier host, for example Waybar's tray module. WSL without a desktop session often has no tray at all.
The app runs under Wayland. Size and maximised state are saved; the screen position often is not. Notifications go through xdg-desktop-portal. Plasma and GNOME provide one. A minimal Hyprland session needs the portal package as well. If the app starts before the session bus is ready, the tray or notifications can miss the first attempt; restarting the app afterwards is enough.
The setup (gotify-desktop-windows-amd64-setup.exe) installs the app. gotify-desktop-windows-amd64.exe is portable and needs no installer. Automatic updates replace that EXE, not the setup.
Windows 10 and 11 usually already include the WebView2 runtime. If it is missing, the window stays blank until the runtime is installed.
The packages are not signed. SmartScreen may warn on the first launch.
Apple Silicon (arm64) only. The DMG contains Gotify Desktop.app and a link to Applications. The ZIP contains gotify-desktop.app.
Builds are unsigned and not notarized, so macOS blocks the first launch. In Finder, right-click the app, choose Open, then Open again. Or, depending on which bundle you installed:
xattr -dr com.apple.quarantine "/Applications/Gotify Desktop.app"Automatic updates use the ZIP, not the DMG.
Configuration and history are stored in the user directory:
| System | Folder |
|---|---|
| Linux | ~/.config/gotify-desktop/ |
| macOS | ~/Library/Application Support/gotify-desktop/ |
| Windows | %AppData%\gotify-desktop\ |
That folder holds config.json (servers, active server, language, autostart, window, last update check), history.json (the last 100 notifications), and notify.log (notes when notifications do not appear). An older single-server config.json is migrated on first load.
| Platform | To build |
|---|---|
| Linux | Go 1.26+, Node.js 24+, libgtk-4-dev, libwebkitgtk-6.0-dev, gcc, pkg-config |
| Windows | Go 1.26+, Node.js 24+, WebView2 runtime |
| macOS | Go 1.26+, Node.js 24+, Xcode Command Line Tools |
Ubuntu 24.04:
sudo apt install build-essential pkg-config libgtk-4-dev libwebkitgtk-6.0-devWails v3 CLI ($HOME/go/bin on PATH). On Linux the default install may need GTK 4 / WebKitGTK headers; under WSL you can install the CLI without CGO:
# Linux with GTK headers available
go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0
# WSL / cross-compile helper without linking GTK
CGO_ENABLED=0 go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0Running a prebuilt binary only needs the runtime packages in Linux. The dev packages are for building. Cross-compiling a Windows EXE from Linux/WSL does not need GTK:
CGO_ENABLED=0 wails3 build GOOS=windows GOARCH=amd64cd frontend && npm install && cd ..
wails3 devwails3 buildThe binary is bin/gotify-desktop (.exe on Windows, .app on macOS).
wails3 build GOOS=windows GOARCH=amd64
wails3 build GOOS=darwin GOARCH=arm64
wails3 build GOOS=linux GOARCH=amd64Local packages:
# Windows (NSIS on PATH)
wails3 package GOOS=windows GOARCH=amd64
# Linux AppImage (after wails3 build)
./packaging/linux/build-appimage.sh bin/gotify-desktop dist linux-amd64
# macOS DMG (after wails3 build)
./packaging/darwin/build-dmg.sh bin/gotify-desktop.app dist darwin-arm64A version tag creates the GitHub release:
git tag v0.1.9
git push origin v0.1.9.github/workflows/ci.yml runs on pushes and pull requests to main and on v* tags:
- Unit tests
- Builds for Linux amd64, Windows amd64, and macOS arm64
- Packages as workflow artifacts, and on tags also attached to the GitHub release
| Platform | Files |
|---|---|
| Windows | gotify-desktop-windows-amd64-setup.exe, gotify-desktop-windows-amd64.exe |
| Linux | gotify-desktop-linux-amd64.AppImage, gotify-desktop-linux-amd64 |
| macOS | gotify-desktop-darwin-arm64.dmg, gotify-desktop-darwin-arm64.zip |
| All | SHA256SUMS (GNU sha256sum, two spaces) |
The app queries releases/latest over HTTPS (User-Agent gotify-desktop/<version>). When a newer major.minor.patch is published, a dialog asks to install. After confirmation the matching package and SHA256SUMS are downloaded, the hash is checked, and a helper process replaces the running install.
| Running as | Update package |
|---|---|
Linux AppImage (APPIMAGE set) |
gotify-desktop-linux-<arch>.AppImage |
| Linux binary | gotify-desktop-linux-<arch> |
| Windows EXE | gotify-desktop-windows-<arch>.exe (not the NSIS setup) |
macOS .app |
gotify-desktop-darwin-<arch>.zip |
Builds with version 0.0.0 skip the check. If the matching package is missing, the app shows an error and the releases URL. Integrity comes from HTTPS and SHA256SUMS, not from a signature. Manual check: About → Check for Updates.
Top-level fields in config.json:
| Field | Meaning |
|---|---|
servers |
List of Gotify accounts |
active_server_id |
Which account drives the embedded UI and the default send target |
autostart |
Start at login |
locale |
Optional BCP-47 tag such as de or en; empty = OS language |
history_mode |
toasts (default) or all |
window_* |
Size, position (window_pos_set so 0,0 is valid), maximised |
update_checked_unix |
Last automatic update check |
Each entry in servers:
| Field | Meaning |
|---|---|
id |
Stable UUID |
label |
Display name (default: hostname) |
server_url |
Gotify base URL |
username |
Remembered login name (no password) |
client_token |
Client token for stream and UI |
min_priority |
Minimum priority for toasts (default 0) |
last_message_id |
Dedup cursor for that server’s stream |
enabled |
When false, the stream is not started |
Legacy single-server keys (server_url, client_token, …) at the top level are read once and rewritten into servers.
UI strings live in internal/i18n/locales/*.json. English is the fallback. Bundled languages: en, de, fr, es.
Check only the WebSocket stream:
GOTIFY_URL=https://gotify.example.com GOTIFY_TOKEN=... go run ./cmd/streamcheckQuick check that the Linux tray host is reachable:
ldconfig -p | grep -i appindicator
echo "$DBUS_SESSION_BUS_ADDRESS"
echo "$XDG_SESSION_TYPE"
gnome-extensions list 2>/dev/null | grep -i indicator || trueMIT — see LICENSE.


