aboutsummaryrefslogtreecommitdiffstats

notifyd

A freedesktop notification daemon for this desktop, replacing dunst.

The daemon owns org.freedesktop.Notifications and holds the state. It publishes the live queue and the history ring as JSON under $XDG_RUNTIME_DIR/notifyd/ for a quickshell renderer to draw, and notifyctl is the only thing that talks back over D-Bus.

go build ./...

The design and the exact file contract are in the quickshell repo, at docs/superpowers/specs/2026-09-15-notification-daemon-design.md.

Install and handover

Build and install the two binaries and the script, beside the statusctl CLI:

go build -o ~/bin/notifyd ./cmd/notifyd
go build -o ~/bin/notifyctl ./cmd/notifyctl
install -m 755 scripts/notify-snooze.sh ~/bin/notify-snooze.sh

dunst is not removed until this proves itself. To switch:

  1. Stop dunst (pkill -x dunst or its service) so the bus name is free.
  2. Add hl.exec_cmd("notifyd") to ~/.config/hypr/sections/autostart.lua, beside the quickshell lines.
  3. Change rofipass's one dunstctl close-all to notifyctl close-all.
  4. Start notifyd and send a test notification.

The renderer that draws the balloons is a separate plan; until it ships the queue is visible through notifyctl list.

Configuration

~/.config/notifyd/config.json ($XDG_CONFIG_HOME is honoured). Every key is optional and the defaults are the behaviour without the file:

{
  "timeouts": { "low": 10, "normal": 10, "critical": 0 },
  "liveCap": 20,
  "historyCap": 20,
  "soundTheme": "freedesktop"
}

Timeouts are seconds up to a day (86400), 0 is never, and apply only when a client sends expire_timeout -1. Caps clamp to 1..100; a lowered cap applies at the next notification. A broken file is logged and read as the defaults.

soundTheme is the freedesktop sound theme an app's sound-name hint is looked up in (then its Inherits, then freedesktop). The daemon publishes each notification's resolved sound (a path, or "") and silent (the app's suppress-sound); a sound-file hint wins over sound-name when it is an absolute path to an existing file. Playing is the renderer's job.

The daemon reads it at start and on notifyctl reload. The quickshell settings page writes it; the same file carries the balloon shell's keys (balloons, dndPassCritical, muted), which the daemon ignores.

License

GPLv2 only. See LICENSE.

Development Approach

This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback.

All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions.

The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability.