Each layout entry is now an object — {id, ...inline settings} — instead
of a (name, separate modules map) pair. Multiple instances of the same
widget are trivially supported (spacer is the main beneficiary). Settings
travel with the entry, so reordering keeps them attached.
shell.qml:
- normalizeLayout converts string entries to {id} and drops invalid ones
- ModuleSlot binds to a full entry; moduleName and moduleSettings derive
from it via entryId/entrySettings helpers
- centerAnchor lookup walks layoutEntries directly
- builtinBarConfig defaults use the object form
- README + bar-defaults.json updated to the new schema
bar-settings/ (new Quickshell config):
- Top toolbar with Reset / Save and Position / centerAnchor dropdowns
- Three section editors (left/center/right) with current widgets shown
as cards: name + description + move up/down/settings/remove buttons
- '+ Add widget' menu per section, sorted alphabetically by display name
(only spacer can repeat; everything else is one per bar)
- Per-widget settings dialog (FloatingWindow) loads an inline schema for
widgets in the catalog. Initial schemas: spacer (size), calendar
(formats), brightness (step)
- FileView { atomicWrites } writes to ~/.config/omarchy/bar.json on Save
omarchy-launch-bar-settings + hypr window rules pin the settings window
to a 760px floating square. controlCenter gains a 'Customize bar…' button
that launches it.
6.3 KiB
Omarchy bar
This is the Quickshell implementation of the Omarchy status bar.
shell.qmlis Omarchy-owned bar engine code. Users should not edit it directly.bar-defaults.jsonis 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.jsonand are merged over defaults at runtime. omarchy-style-bar-positionupdates 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 familybar.position—"top" | "bottom" | "left" | "right"bar.vertical— boolean shortcutbar.barSize— 26 horizontal / 28 verticalbar.run(command)— fire-and-forget bash execbar.shellQuote(value)— safe shell-quote a stringbar.showTooltip(target, text)/bar.hideTooltip(target)— shared tooltip popupbar.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.