← All projects

macOS and Linux

NtfyBar

Server alerts in the menu bar. A native client for ntfy, whether ntfy.sh or self-hosted, with one inbox per topic.

View
Status
Version 1.0, installable via Homebrew
First commit
20 August 2026
macOS menu bar client for ntfy.kaiserlich.dev
Stack
Swift, SwiftUI, Homebrew, QML, Python

Why I built it

Everything I run reports through ntfy. Deployments, monitors, failed jobs, for my own servers and for systems I run for clients. ntfy is a simple push service that I host myself.

On my computer I wanted those messages where I’m already looking: up in the menu bar. No browser tab I have to keep open, no web app in the background.

What it does

  • Lives in the menu bar and keeps a connection to the ntfy server open.
  • Shows new messages as native macOS banners.
  • Collects everything in one inbox, grouped by topic. One click opens the link from the message.
  • Works with ntfy.sh or any self-hosted server, with username and password or a token. Credentials live in the macOS keychain.
  • Install with brew install --cask ntfybar from my own Homebrew tap.

Because I also work on Linux, there’s been a port for the Omarchy bar since the day after: a bell in the bar, the same banners, the same inbox, installed with a single omarchy plugin add.

Technical decisions

Native, not Electron. A menu bar app that runs all day should use almost no memory and feel like macOS. So Swift and SwiftUI, about 1,600 lines, no dependencies besides the operating system.

For me first, then general. The first version was hardwired to my own server. The same day I turned that into generic settings and built a Homebrew package. My server is now just a default.

Homebrew as distribution. No App Store, no custom updater. One tap, one cask, one release zip on GitHub. For a tool this size, that’s enough.

From the sessions

NtfyBar came together in one afternoon in August 2026, the Linux version the next morning. It’s a small tool, but it’s attached to something bigger.

In September I took it a step further: if an alert lands with me anyway, why should I have to pass it on to an agent myself? Since then, actionable messages from selected topics automatically become an agent thread that starts investigating. All-clears get filtered out, and the same message only creates one thread. In testing, one alert turned into exactly one thread, no duplicates.

NtfyBar tells me something happened. Often the agent has already started before I click.