Arrr! β because every good notification deserves a pirate's welcome.
There are already plenty of tools that forward notifications: ntfy, Gotify, Pushover, Apprise, and a dozen others. Arrr is not trying to replace or replicate any of them.
The problem I wanted to solve is simpler and more specific: I have notifications coming from many different places β RSS feeds, Telegram, WhatsApp, email, GitHub, calendar reminders, task due dates β and I had no single place where I could see all of them together. Every source lived in its own app, its own window, its own silo. I'd miss things, or I'd have to check six places just to know what happened.
Arrr's only job is aggregation. One daemon that pulls from every source I care about, puts everything into a single stream, and lets me consume that stream however I want β as a desktop popup, an email digest, a push notification, or just a history log I can search later. The digest feature in particular was the tipping point: I don't want to be interrupted by every single RSS item, but I do want a morning summary of what came in overnight.
That's it. No cloud account, no mobile app, no SaaS. A daemon that runs on my Linux machine, knows about all my sources, and keeps everything in one place.
Arrr runs as a background service, collects notifications from multiple sources via a plugin system, and delivers them to your desktop through D-Bus and configurable sink plugins. A built-in web UI lets you browse notification history, manage plugins and sinks, and tweak settings β all from a browser.
Web UI β plugin and sink management
Web UI β plugin cards with status and controls
- Plugin system β load notification sources from external
.dllassemblies at runtime; each plugin runs in isolation and can't crash the daemon - Sink system β fan-out to any number of destinations: desktop popups, email, push notifications, webhooks, and more
- Web UI β React dashboard for history, plugins, sinks, logs, and config
- Notification history β optional SQLite-backed history with full-text search, source filter, and pagination (encrypted at rest)
- D-Bus delivery β notifications appear as native desktop popups via
org.freedesktop.Notifications - REST API β HTTP endpoints to send notifications from any language and manage plugins/sinks
- gRPC streaming β server-streaming endpoint so remote clients (e.g. a PC) can subscribe to live notifications over the network
- Routing rules β filter or redirect notifications by source, title, body, priority, extras, and time-of-day; first-match-wins, disabled by default
- Do Not Disturb β pause all sink delivery with a single toggle (REST or gRPC), without stopping sources
- Digest β schedule batched notification summaries (hourly, daily, β¦) delivered via any sink
- Deduplication β configurable time window to suppress duplicate notifications
- NuGet installer β install community plugins directly from NuGet.org via the API or web UI
- Docker image β
tgiachi/arrron Docker Hub; first-start API key generation,/datavolume for persistence - systemd user service β runs as a user unit, logs to the journal
- Self-contained binary β no .NET runtime required on the target machine
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Arrr.Service β
β β
β Source Plugins βββ β
β REST /api/notify βΌβββΆ EventBus βββΆ SinkOrchestrator βββΆ D-Bus popup
β β β β β βββΆ Ntfy / SMTP / Pushover
β β β RoutingRules β βββΆ Webhook / WebSocket
β β β DnD guard β βββΆ SignalR hub
β β β β β βββΆ β¦ (sink plugins)
β β β HistoryService β
β β β β
β β ββββΆ NotificationGrpcService β
β β β β
β gRPC stream :5150 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
Web UI :5150
- The daemon starts and loads plugins from the configured
plugins/directory. - Each plugin receives an
IPluginContext(event bus, logger, shared HTTP client, per-plugin config) and runs on its own task. - Plugins publish
Notificationevents onto the internal event bus. SinkOrchestratorevaluates routing rules and the DND flag, then fans matching notifications out to enabled sinks.- If
historyEnabled: true, every notification is persisted to an encrypted SQLite database. NotificationGrpcServicestreams events (notifications and DND changes) to all connected gRPC clients.- External processes can inject notifications via
POST /api/notify.
| Package | AUR | Description |
|---|---|---|
arrr-bin |
Pre-built binary (fast install) | |
arrr-git |
Built from latest git HEAD |
# Pre-built binary (fast):
yay -S arrr-bin
# Build from source (latest git HEAD):
yay -S arrr-gitDownload the latest .deb, .rpm, or .pkg.tar.zst from the releases page.
Debian / Ubuntu
sudo dpkg -i arrr_<version>_amd64.debFedora / RHEL
sudo rpm -i arrr-<version>-1.x86_64.rpmArch Linux (manual)
sudo pacman -U arrr-<version>-1-x86_64.pkg.tar.zstdocker run -d \
--name arrr \
-p 5150:5150 \
-v arrr-data:/data \
tgiachi/arrr:latestOn first start Arrr prints a randomly generated API key to the log. Pass ARRR_API_KEY to use a fixed key:
docker run -d \
--name arrr \
-p 5150:5150 \
-v arrr-data:/data \
-e ARRR_API_KEY=my-secret-key \
tgiachi/arrr:latestD-Bus and Unix socket sinks are disabled in the Docker image. Use Ntfy, SMTP, Webhook, or gRPC clients to receive notifications from a containerised instance.
systemctl --user enable --now arrr
journalctl --user -u arrr -fThe web UI is available at http://localhost:5150 once the service is running.
git clone https://github.com/tgiachi/Arrr
cd Arrr
dotnet build -c ReleaseRun directly:
dotnet run --project src/Arrr.Service -- --rootDirectory ~/.local/share/arrrOnce installed (or built from source), the daemon is a single self-contained binary:
# Run in the foreground (useful to check the first-run output)
arrr
# Common flags
arrr --logLevelType Debug # verbose logging
arrr --rootDirectory /custom/dir # use a non-default data directory
arrr --logToFile false # console only, no rolling log filesOn first start Arrr generates a random API key and writes it to the log. Note it down and put it in the web UI settings or in arrr.config β it is required for every API call and for arrr-tray to connect.
The service exposes a single port (default 5150):
http://localhost:5150β web UI and REST APIhttp://localhost:5150/streamβ SignalR hub (used byarrr-trayand the built-in stream view)
Once running, open http://localhost:5150 in your browser to install plugins, configure sinks, and browse notification history.
arrr-tray is a lightweight Linux system tray application that connects to a running Arrr service and delivers notifications to your desktop via D-Bus (org.freedesktop.Notifications) β the same mechanism used by your notification daemon (Dunst, Mako, SDDM, etc.).
What it does:
- Sits in the system tray and shows whether the service is connected or not
- Forwards every notification received from the service to the desktop as a native popup
- Uses the plugin's icon for the popup when available, falls back to a default icon
- Sends a "Connected" desktop notification when it (re)connects to the service
- Lets you toggle Do Not Disturb from the tray menu without opening a browser
- Shows an About window with tray and service versions
What it does NOT do:
- It does not run the Arrr service itself β you need the daemon running separately
- It does not store or search notification history β use the web UI for that
Install (Arch Linux):
yay -S arrr-tray-bin # or arrr-tray-git for latest HEADOr build from source:
dotnet build src/Arrr.Tray -c ReleaseFirst-time setup:
- Start
arrr-trayβ it appears in the system tray - Right-click β Settings
- Set Server URL (e.g.
http://localhost:5150) and API Key - Click Save β the tray reconnects immediately
arrr-trayis currently Linux-only. It requires a D-Bus session bus and a compatible notification daemon.
| Doc | Description |
|---|---|
| Configuration | Config file reference, data directory layout |
| REST API | All HTTP endpoints with examples |
| SignalR streaming | Live event streaming for clients |
| Routing Rules | Filter and redirect notifications by source, time, priority |
| Writing a Plugin | Build your own source or sink plugin |
| Sink | NuGet | Description |
|---|---|---|
| D-Bus | built-in | Native desktop popups via org.freedesktop.Notifications |
| Ntfy | Push to a ntfy topic | |
| SMTP | Send notifications by email (single or digest mode) | |
| Gotify | Push to a self-hosted Gotify server | |
| Pushover | Push to iOS/Android via Pushover | |
| Bark | Push to iOS via the Bark app | |
| Telegram Bot | Send notifications to a Telegram chat via Bot API | |
| Home Assistant | Call a HA notify service |
|
| Webhook | POST notifications as JSON to any HTTP endpoint | |
| WebSocket | Broadcast JSON frames to connected WebSocket clients | |
| SignalR | Broadcast to SignalR clients via a hub | |
| macOS Notify | Native macOS notifications via osascript |
Want to build your own plugin? See docs/writing-a-plugin.md.
MIT β see LICENSE.
