A themed desktop cockpit panel for Omarchy v4 ("Quattro"): clock, media, system state, quick controls, and style — one keystroke away, fully dormant when closed.
- Header (every page) — accent clock, date, and focused workspace beside now-playing artwork (accent glow while something plays), over a quiet hostname · kernel · uptime line.
- Overview — media with a draggable seek bar (elapsed/total labels, capability-gated) and a player-switcher chip when several players are active; capability-gated transport; CPU, memory, storage, and battery arc meters — battery with time-to-empty/full when UPower knows it, CPU and memory with a two-minute trend sparkline under the arc; live network throughput as a dual down/up sparkline (loopback, container bridges, tunnels, and other common virtual interfaces are excluded so their mirrored traffic does not double-count) with split-path latency: the LAN router leg vs the internet leg, so one look answers "my network or my ISP". Sensor rows color by the hardware's own declared thermal limits (NVMe and DDR5 DIMM sensors declare them; rows without limits stay plain), including a Memory row for the hottest DIMM.
- Controls — output volume slider, brightness slider for the focused monitor (DDC or backlight via Omarchy's own CLI; hidden when the display cannot be controlled), output/input mute with a live microphone peak meter (-55 dBFS floor, native PipeWire monitor — no process), Do Not Disturb, night light, stay awake, Bluetooth, and Game Mode (strip compositor effects via Omarchy's toggle mechanism — shared state with the community.game-mode bar widget), plus Capture and Power quick actions that hand off to the Omarchy menu (its own second click confirms destructive power actions).
- Style — theme and background pickers, delegated to the built-in Omarchy selectors; a Wallpaper Hub button appears when the community.wallpaper-hub plugin is installed and enabled.
- Keys (parked) — a searchable cheatsheet of every live Hyprland keybind
(from
hyprctl binds, so it never goes stale). Currently unlisted from the tab row; re-addPAGE_KEYStoPAGESinmodel/NexusModel.jsto restore. - Media page — every active player with its own transport, selection, and per-player Left/Right track skipping.
- Notes — one quick markdown scratch file with debounced autosave.
- Command palette — start typing anywhere in the panel (or press
/) to fuzzy-search every action it knows: toggle any control, jump to a page, play/pause a player, restore a minimized window, flip a setting, step brightness, copy a pinned snippet, or look up a keybind (Enter copies it). Title matches always outrank description matches, the top result ghost-completes inline (Tab accepts), and Esc backs out to the page you were on. - Clipboard — recent text clips, click to copy back; image clips hand
off to the full first-party manager. Pin (
) the snippets you paste weekly: pins keep a starred section above the history, survive reboots in Nexus's own state file, and are searchable from the palette. - Minimizer — windows stashed on
special:minimized(pairs with a Super+M minimize-to-tray script setup), newest first with their origin workspace, a hover/cursor preview (the scripts' pre-captured thumbnail, falling back to a live toplevel capture), and click/Enter to restore to the current workspace. A per-row close asks for a confirming second click, then sends the compositor's graceful close (never a kill). The scripts' sidecar files are read-only to Nexus. - Alerts — failed systemd units (both scopes) with one-click restart and reset-failed (system-scope actions authenticate through the polkit agent), pending and recent notification history (mark-all-seen, per-row dismiss, one-click clearing, an "open" action on rows whose sender still accepts one), and shell self-diagnostics: QML errors from the running shell's own log since the last config load, secret-bearing lines dropped whole, home paths redacted.
- Bar — edit the bar from the panel: reorder widgets, move them between sections, remove or add them. Every mutation goes through the host's plugin registry, so inline widget settings survive moves and the render-pinned tray is honestly marked instead of pretending to move.
- Sensors — CPU/GPU/NVMe temperatures and fan RPMs on Overview,
discovered per machine (hybrid-GPU aware: an NVIDIA display GPU is read
via
nvidia-smi, AMD via sysfs; fans hide when a machine has none). - Audio visualizer — subtle spectrum bars inside the media card while
something plays (needs the
cavapackage; hides cleanly without it). - Settings — the cog in the tab row: choose which Overview cards show
(hide the battery meter on a desktop, drop the media card, and so on)
and pick exactly which effects Game Mode strips (animations, blur,
shadows, gaps, rounding, tearing). Changes persist immediately to
~/.local/state/omarchy/settings/nexus.json. - Bar shortcut — an optional bar widget that toggles the panel, lights up while it is open, and carries a badge counting unseen notifications (one watched state file, no polling).
- Deterministic media — one MPRIS adapter with proxy-aware player selection (playerctld and browser-integration proxies never shadow the real player) and stable ordering, so the shown player never flaps.
- Theme-native — colors, borders, and spacing derive from the shared Omarchy tokens; the panel re-themes with your shell.
- Dormant when closed — no timers, no processes, no media or PipeWire bindings while hidden; the panel unloads entirely between summons (measured cold summon: p95 88 ms).
- Keyboard-driven — every actionable row on every page is reachable without a pointer: media transport, seek, and player switcher on Overview; all toggles plus Capture and Power on Controls; Theme and Background on Style (see the table below). The tab row also cycles on mouse wheel, and page changes slide in from the direction of travel.
omarchy plugin add https://github.com/devmobasa/omarchy-nexus --enableThen toggle it:
omarchy-shell shell toggle community.omarchy-nexus '{}'The payload may name a page directly: '{"page":"controls"}' (pages:
overview, media, controls, style, notes, clipboard,
minimizer, alerts, bar, settings).
The manifest also ships a bar widget. If it does not appear after
installing, add it to your bar layout in ~/.config/omarchy/shell.json:
{ "bar": { "layout": { "right": [ { "id": "community.omarchy-nexus" } ] } } }(append the entry to your existing right array), then
omarchy bar move community.omarchy-nexus <left|center|right> to
reposition it.
Add to ~/.config/hypr/bindings.lua:
o.bind("SUPER + SHIFT + J", "Nexus cockpit", "omarchy-shell shell toggle community.omarchy-nexus '{}'")Then reload Hyprland and check for config errors:
hyprctl reload
hyprctl configerrors| Key | Action |
|---|---|
Esc |
Close the panel |
Tab / Shift+Tab |
Cycle pages |
Down / Up |
Walk the current page's rows |
Enter / Space |
Activate the focused row — on the volume row it toggles mute; the seek bar has no activate action |
Left / Right |
Act on the focused row when it can — volume slider (±5%), media transport (previous/next), seek bar (±5 s) — otherwise cycle pages |
All optional, read from your plugin entry in
~/.config/omarchy/shell.json — the fields sit inline on the entry itself.
Invalid values fall back to defaults; Nexus never writes settings.
{
"version": 1,
"plugins": [
{
"id": "community.omarchy-nexus",
"defaultPage": "controls",
"monitor": "DP-3",
"showMedia": true,
"showMetrics": true,
"showNetwork": true,
"showFetch": true,
"preferredMediaIdentity": "spotify"
}
]
}Presence of the entry is what enables the plugin; remove it or run
omarchy plugin disable community.omarchy-nexus to switch Nexus off.
| Field | Default | Meaning |
|---|---|---|
defaultPage |
"overview" |
Page shown when the summon payload names none |
monitor |
"focused" |
Output name to open on, or "focused" |
showMedia |
true |
Show the media artwork, transport, and seek bar |
showMetrics |
true |
Show the metric arc meters |
showNetwork |
true |
Show the network throughput sparkline (needs showMetrics) |
showFetch |
true |
Show the hostname · kernel · uptime line |
showCpu / showMemory / showStorage / showBattery |
true |
Per-meter visibility |
showSensors |
true |
Hardware sensors card |
showVisualizer |
true |
Audio spectrum in the media card (needs cava) |
gmAnimations / gmBlur / gmShadows / gmGaps / gmRounding / gmTearing |
true |
What Game Mode strips |
preferredMediaIdentity |
"" |
Prefer this player identity (case-insensitive) among active players |
The boolean toggles are also editable interactively on the Settings page
(the cog); interactive changes are stored in
~/.local/state/omarchy/settings/nexus.json and win over the shell.json
layer. Nexus never writes shell.json itself.
The static suite (model fixtures, manifest validation, contract pins,
qmllint) runs against the Omarchy shell source, which it reads from
/usr/share/omarchy by default, and needs node, omarchy, and qmllint
on PATH:
./test/allSet OMARCHY_PATH to point at a different Omarchy source tree:
OMARCHY_PATH=/path/to/omarchy ./test/alltest/live installs a throwaway copy into your running session, so it needs
a system where Nexus is not installed (it refuses if the plugin directory,
a shell.json entry, or a registry record already exists), and it removes
everything it created:
./test/live --confirm-live # guarded install/summon/teardown round triptest/benchmark and test/stress measure an existing install instead, so
they need Nexus already installed and enabled. They leave the panel closed
and the install in place; test/benchmark writes its report into
test-output/:
./test/benchmark # cold-summon latency (keepLoaded decision data)
./test/stress # repeated summon cycles, surface + unload proofCI runs the node model and contract tests on every push.
The plugin entry point is intentionally a thin composition facade:
Nexus.qmlowns the shell lifecycle and routes interactions.state/owns effectful integrations such as media, metrics, and files.ui/owns the panel shell and focused visual sections.model/contains dependency-free calculations shared with Node tests.
omarchy plugin add leaves a git checkout at
~/.config/omarchy/plugins/community.omarchy-nexus/, so you can edit there
directly. If you work in a separate clone, copy it over first:
cp -RP -- . ~/.config/omarchy/plugins/community.omarchy-nexus/Either way, restart the shell after every change:
omarchy restart shellThe restart matters: current Quickshell builds do not expose
Qt.clearComponentCache, so the shell's plugin hot-reload cannot swap
already-compiled QML — a rescan alone keeps serving the old component.