Skip to content

Native macOS notifications, readable text, one alert per condition - #52

Merged
vishr merged 4 commits into
mainfrom
fix/native-notifications
Oct 24, 2026
Merged

vishr merged 4 commits into
mainfrom
fix/native-notifications

Conversation

@vishr

@vishr vishr commented Oct 24, 2026

Copy link
Copy Markdown
Member

Fixes three problems with desktop notifications on macOS.

1. They came from Script Editor. Notifications went out through terminal-notifier or, when it wasn't found, AppleScript's display notification. macOS treats Script Editor as the sender of AppleScript notifications, so "Show" opened Script Editor.

Driga.app now posts notifications itself through UNUserNotificationCenter:

  • cgo-free: uses github.com/ebitengine/purego and its objc package. It was already in go.sum and is now a direct dependency.
  • Driga as sender: notifications show Driga's name and icon.
  • Click to jump: clicking runs driga inbox jump <id> as separate arguments, with no shell. Remote items and multi-item summaries have no click target.
  • Re-sends replace: request identifiers come from machine and item, so a re-sent item replaces its earlier notification.
  • Collector only: driga collect is the only command that starts the Cocoa run loop. Every other command and hook skips AppKit; a bundled driga --version takes about 9 ms.
  • Helpers removed: the terminal-notifier and AppleScript notification paths are deleted. AppleScript remains only for terminal jumps.
  • Unbundled builds: doctor says notifications need Driga.app.
  • Other platforms: Windows toast and Linux notify-send are unchanged.

2. Raw text. Low disk now reads Low disk space · 12.2 GB free, below 20 GB. The inbox keeps the explanation, with the current driga cleanup list --sizes hint.

3. Repeats. Machine-health items skipped the seen-item guard, so an unresolved episode alerted again at every repeat interval. The 3-in-a-row case is reproduced by a regression test, which failed before the fix. Now:

  • health alerts fire once per episode;
  • several at once are combined into one notification per machine;
  • an alert re-arms only after the condition recovers;
  • unknown readings no longer reset pressure.

Migration 0003_health_alert_once.sql updates the partial index without resetting delivery state.

Checks:

  • just check and just race pass, and Windows and Linux vet are clean.
  • Native mapping, ABI, concurrency and click tests use a fake notification center; tests never post a real notification.
  • An ad-hoc bundled build reports native notifications in doctor.

Still to verify by hand on a Mac after release with the signed app:

  • the permission prompt;
  • Driga's icon on the notification;
  • clicking jumps to the session;
  • no repeat while the disk stays low.

https://claude.ai/code/session_01T2vtcW6ihn1ywy9vxUq9a4

vishr added 4 commits October 23, 2026 20:34
Driga.app now posts notifications itself through UserNotifications
(purego, still cgo-free), so they show Driga's name and icon and a click
jumps to the item. The terminal-notifier and AppleScript paths are gone;
AppleScript notifications belonged to Script Editor, which is why Show
opened it. Only `driga collect` starts the Cocoa run loop; other
commands and hooks are unaffected. Unbundled builds report in doctor that
notifications need the app.

Machine-health alerts were exempt from the seen-item guard, so an
unresolved low-disk episode re-alerted every repeat interval. Health
alerts now fire once per episode, coalesce per machine, and re-arm only
after recovery (migration 0003).

Low disk reads "Low disk space · 12.2 GB free, below 20 GB"; the inbox
keeps the detail and the current `driga cleanup list --sizes` hint.

Claude-Session: https://claude.ai/code/session_01T2vtcW6ihn1ywy9vxUq9a4
doctor now reads Driga's macOS notification permission without prompting
and warns when it is off, pointing at System Settings. After a refusal the
collector re-checks permission on the next notification, so allowing
Driga later takes effect without restarting the service.

Claude-Session: https://claude.ai/code/session_01T2vtcW6ihn1ywy9vxUq9a4
- Startup no longer fails when notifications are denied: only the bundle
  identity is required, so allowing Driga later works without a restart.
- Low disk ends an episode only at 10% above the limit, and memory
  pressure only on a return to normal, so hovering or flapping cannot
  raise an alert on every crossing.
- A viewer without the service no longer consumes alerts it cannot show.
- Alerts queued during the permission prompt coalesce per destination.
- Free space is truncated, never rounded up to the limit.
- `collect` is detected after global flags; doctor's install hint uses the
  tap (`brew install --cask labstack/tap/driga`).

Claude-Session: https://claude.ai/code/session_01T2vtcW6ihn1ywy9vxUq9a4
@vishr
vishr merged commit 1f9e1be into main Oct 24, 2026
4 checks passed
@vishr
vishr deleted the fix/native-notifications branch October 24, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant