Skip to content

How notifications are routed

Samy Lemcelli edited this page Aug 24, 2026 · 1 revision

How notifications are routed

The decision, in order

When a notification arrives, four questions decide whether you see it.

Is it critical? Urgency 2 in the freedesktop spec. Critical notifications bypass filtering entirely, because losing a low battery or disk full warning to a context filter is a worse outcome than seeing one message from the wrong space. Set "criticalBypass": false at the top level of the config to turn this off.

Which space owns it? The sender's app name is matched against every space's apps list, case insensitively, with a trailing .desktop stripped. The first space that claims it owns it. An app claimed by nobody is unassigned.

What does the policy allow right now? The active space's schedule is checked against the wall clock. The first window that contains the current minute wins. If no window matches, the space's baseline notifications.allowFrom applies.

Is the owner in that list? If yes, the notification shows. If the app is unassigned, allowUnassigned decides instead.

Schedule windows

"schedule": [
  { "from": "08:00", "to": "17:00", "allowFrom": ["personal", "work"] },
  { "from": "17:00", "to": "22:00", "allowFrom": ["personal"] },
  { "from": "22:00", "to": "08:00", "allowFrom": [], "allowUnassigned": false }
]

That reads as: everything during working hours, personal only in the evening, silent overnight.

The end bound is exclusive. 08:00 to 17:00 covers 08:00 through 16:59, so adjacent windows never both match and you do not need gaps between them.

Windows may wrap past midnight. 22:00 to 08:00 is one window covering the late evening and the early morning, not two.

Order matters. The first matching window wins, so keep them non overlapping. omarchy-spaces validate flags overlaps and gaps.

label is optional and shows up in omarchy-spaces status, which makes it much easier to tell which rule is firing.

Seeing the current policy

omarchy-spaces status
space      Personal (personal)
email      you@example.com
browser    brave profile=Default
time       19:42
window     17:00 to 22:00  Evening, personal only
allowing   personal
unassigned shown

omarchy-spaces status --json gives the same thing for scripts.

The bar indicator

The bar widget appends a mark when filtering is active.

No mark means everything currently reaches you.

A hollow circle means at least one space is blocked, but not everything.

A filled circle means the policy blocks everything. The widget also switches to the urgent color.

Nothing is deleted

A blocked notification is not thrown away. Omarchy's notification service still receives it, writes it to history, and this plugin removes the popup afterwards. Switch back to the space that owns it and the message is waiting in history.

The consequence worth knowing is that filtering is about interruption, not secrecy. Anyone reading your notification history sees everything regardless of which space was active.

Why post filtering

This plugin does not replace Omarchy's notification daemon. It lets omarchy.notifications accept everything, then removes the popups the policy blocks.

That choice buys three things. History stays complete. The stock do not disturb toggle keeps working, because when a policy blocks everything the service mirrors that into the built in flag. And Omarchy keeps ownership of the D-Bus name, so history, images, actions, and the popup lifecycle keep working when Omarchy changes them.

The one caveat is a blocked popup may flash for a frame before removal on a loaded system.

Interaction with manual do not disturb

When a policy blocks everything, the plugin turns on Omarchy's do not disturb flag so the normal bar icon tells the truth. It only turns it off again if it was the one that turned it on. Toggling do not disturb yourself is never undone by a schedule boundary.

Clone this wiki locally