Files
omarchycn/default/quickshell/omarchy-shell/plugins/bar
Ryan Hughes c101591284 Replace mako with quickshell-backed notification daemon
Adds first-party omarchy.notifications service plugin that hosts a
freedesktop notification server and renders popups + a history popup
inside the shell. Uninstalls mako and retargets every helper, keybind,
indicator, and migration entry to the new daemon.

Plugin (default/quickshell/omarchy-shell/plugins/notifications/):
- Service.qml: NotificationServer, popupModel + pendingModel + pastModel
  (two-tier history, see below), DND via PersistentProperties +
  cache-file backstop, image cache for /tmp screenshots, IpcHandler with
  toggleDnd/setDnd/isDnd/showHistory/clear/clearPending/markAllSeen/
  dismissAll/dismissOne/invokeLast/dismiss, per-theme override file
  ~/.config/omarchy/current/theme/notifications.json honoring
  borderColor/backgroundColor/textColor/countdownColor.
- components/NotificationCard.qml: theme-driven card (Color.foreground/
  background/border tokens from Commons/Color.qml), 32x32 icon slot,
  Nerd Font glyph fallback via omarchy-glyph hint, hero image strip
  for screenshot/image-path notifications, hover-pause progress bar,
  uses bar.fontFamily so all surfaces share one font.

Filtering and DND:
- transient hint and CLI-style senders (app_name in notify-send /
  omarchy-action) bypass history but still pop.
- DND only allows omarchy-action toasts and notify-send -u critical
  through; real-app urgency=critical (Discord, Slack, Vesktop) is
  silenced and lands in pending instead.
- Pending vs past split surfaced via tabs in the bar widget popup;
  past tab is auto-pruned at the 15-minute mark.
- Click-to-jump: notifications without a libnotify default action focus
  the matching Hyprland window via class lookup.

Shell host:
- shell.qml: generic first-party service loader (mirrors the existing
  noctalia-compat path) and an alias for the bar so plugins can read
  barSize / barHidden / position for anchoring.
- Commons/Color.qml: parses the theme's hyprland.conf for
  $activeBorderColor so notifications match Hyprland window borders;
  picks the explicit accent= key over the color4= alias.

Bar widget rebase (plugins/bar/widgets/notificationCenter.qml):
- Drops the chunk-1 stub server, binds count/dnd state to the service,
  hosts the history popup via PopupCard so it drops down from the
  notification glyph the same way Quick Settings does.
- Pending/Past tabs, dismiss-individual close X, mark-all-as-seen and
  clear-recent action buttons, theme-driven palette.

Quick Settings rework (plugins/bar/widgets/controlCenter.qml):
- DND tile binds directly to service.doNotDisturb for instant feedback.
- Drops the volume slider (already in audioPanel) and the no-op Theme
  tile; adds a Bluetooth toggle bound to Quickshell.Bluetooth.
- Bigger 44x44 wallet was scaled back to 32x32 for tighter rows.

Notification scripts (bin/omarchy-*):
- omarchy-notification-send: passes glyph as a custom hint instead of
  prepending to the summary; adds -a omarchy-action and -u urgency
  automatically; supports -e/--transient passthrough.
- User-action toasts in the capture / toggle / hyprland / default-*
  scripts and bindings/utilities.lua now tag themselves
  -a omarchy-action so DND treats them as intent-based bypass.
- omarchy-toggle-notification-silencing, omarchy-notification-dismiss,
  default/waybar/indicators/notification-silencing.sh, and the Hyprland
  comma-keybinds all route through omarchy-shell-ipc notifications.
- omarchy-capture-screenshot / -screenrecording set the image-path
  hint properly so the hero-image rendering kicks in.

Mako removal (migrations/1778743515.sh):
- pkill -x mako, systemctl --user stop mako.service, pacman -Rns mako
  (uninstalling deletes /usr/lib/systemd/user/mako.service so D-Bus
  activation can't respawn it). Removes ~/.config/mako/ and the legacy
  toggle file. Restarts quickshell so it claims the bus name.
- Drops mako from install/omarchy-base.packages, autostart.lua,
  install/config/theme.sh + toggles.sh, default/themed/mako.ini.tpl,
  default/mako/, the omarchy-menu Mako restart row, bin/omarchy
  GROUP_DESCRIPTIONS, the settings panel catalogue, and the
  default/omarchy-skill paths table.
- Removed scripts: bin/omarchy-restart-mako,
  bin/omarchy-style-corners-mako.
- bin/omarchy-style-corners summary updated; corner radius for the
  notification card reads ~/.local/state/omarchy/toggles/quickshell-menu.json
  alongside the rest of the shell.
2026-05-14 14:21:07 -04:00
..

Omarchy bar

This is the Quickshell implementation of the Omarchy status bar. It is shipped as a first-party plugin of omarchy-shell, the long-running shell host. The bar is mounted at startup and lives inside the shell for its whole session.

  • manifest.json declares the plugin (id: omarchy.bar, kind: bar, activation: persistent) and points at Bar.qml as the entry point.
  • Bar.qml is Omarchy-owned bar engine code, loaded by the omarchy-shell host. Users should not edit it directly.
  • widgets/ holds first-party widgets — modular, interactive components shipped with Omarchy.
  • common/ holds shared QML helpers (buttons, sliders, popup cards).
  • The bar receives its config from the host shell as a barConfig property; the host loads it from ~/.config/omarchy/shell.json (or shell-defaults.json when the user has no file).
  • omarchy-style-bar-position updates only the user shell.json file.

Customizing

The bar config lives under the bar: key of ~/.config/omarchy/shell.json. Out of the box the shell uses shell-defaults.json. Once you customize anything via omarchy launch settings or by editing shell.json directly, your file is canonical — there is no deep-merge.

Launch the visual editor with omarchy launch settings (or run omarchy-launch-settings) to reorder widgets, add/remove them, and tweak per-widget options without editing JSON by hand.

Example shell.json (bar subtree only shown):

{
  "version": 1,
  "bar": {
    "position": "top",
    "centerAnchor": "calendar",
    "layout": {
      "left": [
        { "id": "omarchy" },
        { "id": "spacer", "size": 12 },
        { "id": "workspaces" }
      ],
      "center": [
        { "id": "media" },
        { "id": "calendar", "format": "HH:mm" }
      ],
      "right": [
        { "id": "systemStats" },
        { "id": "audioPanel" },
        { "id": "battery" },
        { "id": "controlCenter" }
      ]
    }
  }
}

centerAnchor pins one center module to the exact horizontal/vertical center and flanks others around it. Set to an empty string to disable anchoring (the center list is centered as a group).

Module catalogue

First-party interactive widgets (in widgets/)

Name What it does Interactions
media MPRIS now-playing — scrolling track + artist, cover-art popup left = play/pause · middle = next · scroll = prev/next · right = popup
audioPanel Volume icon + popup with master slider, output-device picker, per-app mixer left = popup · right = mute · middle = audio TUI · scroll = volume
networkPanel Wi-Fi/Ethernet icon + popup with Wi-Fi scan, signal, connect left = popup · right = nmtui
bluetoothPanel Bluetooth icon + popup with device list, connect/disconnect, battery left = popup · right = toggle radio · middle = bluetoothctl TUI
calendar Clock + popup with month-grid calendar left = popup · right = tz selector
notificationCenter Bell with badge + popup with recent notifications, DND toggle left = popup · right = toggle DND
systemStats Inline CPU + memory sparklines, popup with detail left = popup · right = terminal
weatherFlyout Weather icon + popup with forecast left = popup · right = full notification
idleInhibitor Coffee-cup that toggles omarchy-toggle-idle left = toggle
microphone Mic icon + scroll volume left = mute toggle · middle = audio TUI · scroll = source volume

Built-in legacy modules (in shell.qml)

omarchy, workspaces, clock, weather, update, voxtype, screenRecording, idle, notifications, tray, bluetooth, network, audio, cpu, battery.

These remain available — set them in layout to use them instead of the richer widget versions.

Orientation

All widgets work in top, bottom, left, and right positions. Popups anchor on the side opposite the bar edge, sliding into the workspace. Vertical bars use 28px width; widgets that show text fall back to compact icon-only forms (e.g. media hides its scrolling label).

Custom user modules

The schema accepts arbitrary module ids that you provide. Set type to command for shell-driven output or qml for a custom QML widget. Both still go under bar.layout.<section> in shell.json.

Command module:

{
  "version": 1,
  "bar": {
    "layout": {
      "right": [
        { "id": "tray" },
        { "id": "vpn", "type": "command", "exec": "~/.config/omarchy/bar/scripts/vpn-status", "interval": 5, "tooltip": "VPN", "onClick": "nm-connection-editor" },
        { "id": "audioPanel" }
      ]
    }
  }
}

The command may print plain text or Waybar-style JSON, for example:

{"text":"󰌆","tooltip":"Work VPN","class":"active"}

QML module:

{
  "version": 1,
  "bar": {
    "layout": {
      "right": [
        { "id": "gpu", "type": "qml" },
        { "id": "audioPanel" }
      ]
    }
  }
}

Then create ~/.config/omarchy/bar/modules/gpu.qml. If you want to store it elsewhere, add a source path.

Custom QML modules should be an Item with implicitWidth and implicitHeight. They may optionally define these properties, which the bar fills after loading:

import QtQuick

Item {
  property var bar
  property string moduleName
  property var settings

  implicitWidth: 28
  implicitHeight: bar ? bar.barSize : 26

  Text {
    anchors.centerIn: parent
    text: "GPU"
    color: bar ? bar.foreground : "white"
    font.family: bar ? bar.fontFamily : "monospace"
    font.pixelSize: 12
  }

  MouseArea {
    anchors.fill: parent
    onClicked: if (bar) bar.run("omarchy-launch-or-focus-tui btop")
  }
}

Bar properties available to widgets

Widgets receive bar (the shell root), moduleName (string), and settings (object) injected at load time. The bar exposes:

  • bar.foreground, bar.background, bar.urgent — theme colors (live-updated)
  • bar.fontFamily — current monospace family
  • bar.position"top" | "bottom" | "left" | "right"
  • bar.vertical — boolean shortcut
  • bar.barSize — 26 horizontal / 28 vertical
  • bar.run(command) — fire-and-forget bash exec
  • bar.shellQuote(value) — safe shell-quote a string
  • bar.showTooltip(target, text) / bar.hideTooltip(target) — shared tooltip popup
  • bar.requestPopout(owner) / bar.releasePopout(owner) — one-popup-at-a-time coordinator

First-party widgets live in widgets/<name>.qml and are picked up by the shell's BarWidgetRegistry at startup; reference one by id in any layout list.

Third-party widgets ship as separate plugins under ~/.config/omarchy/plugins/<plugin-id>/ with their own manifest.json declaring kinds: ["bar-widget"] and a barWidget entry point. See ../../README.md for the manifest schema and the Plugin Manager tab in omarchy launch settings for enable/disable controls.