Skip to content

Repository files navigation

System Monitor — Omarchy plugin

A native system-monitoring panel for Omarchy: CPU, memory, GPU, disk, network and processes in one large floating window, keyboard-driven, in the spirit of btop but drawn by the shell itself. A bar cell with a quick-reference dropdown sits alongside it for a lighter glance — the full panel stays the deep-dive view.

kind kind shell

Install

omarchy plugin add https://github.com/PixelatedContinuum/omarchy-sysmonitor.git --enable

Then bind it. In ~/.config/hypr/bindings.lua:

o.bind("SUPER + CTRL + SHIFT + T", "System Monitor", "omarchy-shell shell toggle jharrison.sysmonitor")

It is a Quickshell FloatingWindow, so Hyprland tiles it by default. To float and centre it like btop's window, in ~/.config/hypr/hyprland.lua:

o.window({ class = "^org\\.quickshell$", title = "^System Monitor$" }, { tag = "+sysmonitor-window" })
o.window({ tag = "sysmonitor-window" }, { float = true })
o.window({ tag = "sysmonitor-window" }, { center = true })
o.window({ tag = "sysmonitor-window" }, { size = { 1180, 900 } })

-- Omarchy tags every window "+default-opacity" (0.985/0.96). On a dense grid
-- of small numbers even 4% of bleed-through costs legibility.
o.window({ tag = "sysmonitor-window" }, { tag = "-default-opacity" })
o.window({ tag = "sysmonitor-window" }, { opacity = "1 1" })

Update with omarchy plugin update jharrison.sysmonitor.

Bar widget

Installing the plugin also registers a bar-widget kind — a compact row of icon-prefixed readouts (CPU, GPU if a discrete AMD card is detected, memory, CPU temperature, network throughput), using the same Nerd Font glyph family Quadrant's own bar cell uses so the two read as one visual language rather than two clashing styles. Click it for a condensed quick-reference dropdown: the same headline numbers plus disk in an animated grid, and the top few processes broken into two sections — by CPU and separately by memory. It polls independently of the full panel, so it stays current whether or not the big window is open.

Not shown anywhere by default; place it in ~/.config/omarchy/shell.json under bar.layout (left, center, or right):

{ "id": "jharrison.sysmonitor" }

It reserves its own edge margin on both sides — the same convention WidgetButton gives every ordinary bar widget by default — so it won't crowd whatever ends up next to it, no matter which section it's placed in or which side that neighbor is on. If you'd like even more breathing room than that as a matter of taste, Omarchy ships a first-party omarchy.spacer bar-widget — drop one into the array with a pixel size:

{ "id": "omarchy.spacer", "size": 24 }

omarchy-restart-shell afterwards. The dropdown has an "Open full monitor" link that runs the same omarchy-shell shell toggle jharrison.sysmonitor command as the keybinding above — a second door into the same panel, not a second implementation of it.

Uninstall

omarchy plugin remove jharrison.sysmonitor

That is the whole uninstall. The panel writes nothing outside its own plugin directory, grants no capability to any binary, installs no helper script and adds no system policy file, so removing it leaves no permission behind to revoke and no file elsewhere on the system to clean up.

The keybinding in bindings.lua and the window rules in hyprland.lua from Install are just a few lines you added by hand — removing the plugin does not touch either file. Leaving them in place is harmless (the panel's window class simply never appears again), but delete them too for a clean config.

What it shows

Section Detail
CPU Model, total usage with a rolling history graph, a per-thread heatmap that colours each core by load, load average, and pressure stall (cpu/io/mem)
Memory RAM with a history graph, swap, and zram compression ratio
GPU AMD: model, core and memory-controller utilisation with a history graph, VRAM, power against cap, sclk/mclk, and fan
Thermal Every temperature the machine exposes in one place: CPU package, the GPU's edge/junction/memory sensors, and each NVMe drive, with the hottest summarised in the heading
Disk Per-filesystem usage as an animated ring gauge with the percentage in its center, deduplicated by device
Network Per-interface throughput, with separate down and up history graphs on a shared scale
Processes CPU, threads, runtime, memory; search by name or pid; click for executable path, working directory and full ancestry; terminate, force-kill, renice, or open in lsof

The three headline percentages sit in the top strip as ring gauges. Each section heading takes its own colour, drawn from the active Omarchy theme's palette, so switching themes recolours the panel with it.

Keys

Key Action
j / k, arrows Move the cursor
h / l Previous / next section
19 Jump to a section
/ Search processes by name or pid
Enter Process detail (or, while searching, apply the filter)
x Terminate the selected process
s Sort by CPU or memory
p Pause the process list
r Refresh everything
PgUp / PgDn, Home / End Scroll
Esc Back, then close (or, while searching, clear the filter)

Search matches the process name, its full command line (so --flag value style arguments count), and pid, all as substrings — and, unlike the plain process list, is never limited to the top processCount rows. That distinction is the point of the feature: a stuck or idle process (a game window that will not exit, holding ~0% CPU and memory) sorts to the bottom on every key and drops out of the capped view entirely, so search is what makes it findable again.

A note on the CPU column

ps %cpu reports CPU time ÷ elapsed time averaged over a process's whole lifetime, scaled to one core. A scanner holding one core of sixteen reports "98%", which reads as nearly the whole machine while the headline says 12%. Both numbers are right and they measure different things.

This panel computes CPU the way btop does — utime+stime deltas between polls, read from /proc/[0-9]*/stat — and the column is share of the whole machine, so it sums toward the headline instead of contradicting it. The per-core figure is in the detail view: "6.1% of 16 threads (98% of one core)".

Permissions

None. The panel runs entirely as your own user and asks for nothing.

Everything on screen comes from /proc and /sys, both world-readable, plus ps, df and free, which are ordinary unprivileged commands. The plugin performs no privilege escalation of any kind: it raises no authentication prompt, installs no system policy file and no helper into a system directory, grants no file capability to any binary, and asks you to join no group. It writes nothing outside its own plugin directory. Install it and it works.

The one thing this costs is per-process network bandwidth. Attributing traffic to a process needs raw socket or eBPF access, which is privileged no matter which tool does it, so the NETWORK section reports per-interface throughput only. Drive temperature is unaffected and still shown, read from hwmon like every other sensor on the panel; the SMART fields that genuinely need root, wear level and error counts, are the deliberate omission.

Process actions are bounded the same way. Terminate, force-kill and renice are offered only for processes you already own, and the panel re-checks the target's owner, command name and elapsed time in the same shell invocation that sends the signal, so a pid reused between the last poll and the keypress cannot be signalled by mistake.

Configuration

manifest.jsonpanel.defaults:

Key Default Meaning
pollInterval 2000 Base poll in ms
showCpuPerCore true Per-thread CPU grid
processCount 14 Rows in the process table
showAllSensors false Every hwmon reading rather than one per device
fontScale 1.25 Multiplier over the theme's font tokens

A panel-kind plugin receives no settings injection from the shell, so the manifest is the config surface. Edit it and run omarchy-restart-shell.

Layout

The window is resizable and tileable; nothing assumes the 1180px it opens at. Cores reflow 4 → 2 → 1, the dashboard stacks below 700px, and process columns drop right-to-left as width runs out, with COMMAND absorbing the slack. minimumSize is 360×280.

Development

node test-model.js

All parsing lives in Model.js: pure functions plus the collector shell scripts, so the panel and the tests run byte-identical commands. The suite exercises them against this machine's real /proc, sysfs, ps and df output. Checks report PASS, FAIL or SKIP; a skip is never counted as a pass. Because nothing here needs privileges, skips should normally be zero: one appearing means a genuine hardware gap on the machine running the suite (no zram, no PSI, no AMD GPU), not something the tests could not reach.

A QML edit needs omarchy-restart-shell to take effect — the FloatingWindow survives hide/show, so reopening the panel keeps the old object and its stale property values.

docs/PLAN.md carries the design history and the traps found along the way.

Requirements

Omarchy shell (Quickshell). The AMD GPU section needs an amdgpu card present; everything else reads /proc and sysfs directly, with no package to install and no permission to grant. Sections whose source is missing hide themselves rather than rendering empty.

Licence

MIT.

About

System monitoring panel for Omarchy — CPU, memory, GPU, disk, network and processes in one keyboard-driven floating window

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages