Files
arthur-os/default/quickshell/bar
Ryan Hughes 9862aeb661 Resolve first-party widgets relative to the shell.qml directory
Quickshell.shellDir points at the directory holding the loaded
shell.qml, so the bar can find its own widgets and bar-defaults.json
without depending on OMARCHY_PATH being set in the environment. The
old behaviour silently fell back to ~/.local/share/omarchy when the
env var was unset, which is fine for the installed shell but caused
'No such file or directory' for every first-party widget when running
quickshell -p straight from the repo.

- firstPartyWidgetSource now uses Qt.resolvedUrl("widgets/<name>.qml")
  so the resolution is anchored to shell.qml itself.
- deriveOmarchyPath() in both bar/shell.qml and bar-settings/shell.qml
  walks back from Quickshell.shellDir to find the omarchy root, with
  OMARCHY_PATH still allowed as an explicit override and the install
  default as a final fallback.
2026-05-14 02:21:47 -04:00
..
2026-05-14 02:21:47 -04:00
2026-05-14 02:21:47 -04:00
2026-05-14 02:21:47 -04:00

Omarchy bar

This is the Quickshell implementation of the Omarchy status bar.

  • shell.qml is Omarchy-owned bar engine code. Users should not edit it directly.
  • bar-defaults.json is the Omarchy-owned default layout and module settings.
  • widgets/ holds first-party widgets — modular, interactive components shipped with Omarchy.
  • common/ holds shared QML helpers (buttons, sliders, popup cards).
  • User overrides live in ~/.config/omarchy/bar.json and are merged over defaults at runtime.
  • omarchy-style-bar-position updates only the user override file.

Customizing

The bar reads ~/.local/share/omarchy/default/quickshell/bar/bar-defaults.json, then deep-merges ~/.config/omarchy/bar.json on top of it. Each layout.{left,center,right} entry is an object: at minimum { "id": "<widget>" }, plus any inline settings the widget reads.

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

Example bar.json:

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

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
brightness Brightness slider + scroll scroll = adjust · left = popup · middle = reset to 80%
powerProfile Current power profile + popup picker left = popup
systemStats Inline CPU + memory sparklines, popup with detail left = popup · right = terminal
weatherFlyout Weather icon + popup with forecast left = popup · right = full notification
workspacesPro Animated focus indicator that slides between workspaces left = focus · right = move window · scroll = cycle
powerMenu Power icon → popup with lock/suspend/log out/reboot/shutdown left = popup
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.

Command module:

{
  "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:

{
  "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

Drop new widgets into widgets/<name>.qml, add the name to the firstPartyWidgets registry in shell.qml, and reference it by name in any layout list.