A Quickshell bar-widget for Omarchy that watches
mbpfan on Apple hardware: it shows CPU temperature
and fan speed right in the top bar, and opens a small panel where you can view and edit
mbpfan’s temperature thresholds (low_temp, high_temp, max_temp).
Designed to be cheap: it reads the sensors with one tiny shell call every few seconds and only
polls while the panel is open — the monitoring widget itself does not burn CPU.
low_temp, high_temp, max_temp.polling_interval at the upstream one-second default so mbpfan remains responsive./etc/mbpfan.conf and restarts mbpfan throughpkexec on fixed trusted system binaries only (sed, systemctl) — nothing is installed63 / 66 / 86 · 1s) after confirmation; Apply is still required to save them.This release is tested on a 15-inch Retina MacBook Pro (Late 2013). It targets Intel Apple
hardware that runs mbpfan through the applesmc and coretemp drivers, but its monitoring path
currently expects the two-fan ApplesMC layout described below. Other Mac models may expose a
different fan count or thermal-zone number and can require a small read-script adjustment.
This widget is only useful if mbpfan is installed, configured, and actually reading your
machine’s sensors. Before installing, confirm that the exact paths in the verification steps below
exist on your machine.
omarchy pkg add mbpfan
Create or edit /etc/mbpfan.conf. A minimal working config looks like:
[general]
min_fan1_speed = 2160
max_fan1_speed = 6200
low_temp = 63
high_temp = 66
max_temp = 86
polling_interval = 1
low_temp — below this the fans idle at minimum speed.high_temp — above this the fans ramp up.max_temp — above this the fans run at maximum speed.polling_interval — how often (in seconds) mbpfan polls the sensors.min_fan*_speed / max_fan*_speed keys override the values read from theapplesmc driver. You may omit them to let mbpfan auto-detect from the driver.Adjust the thresholds to your own machine’s thermal profile; the values above are typical but
not universal. The widget’s Apply accepts only 20 ≤ low_temp ≤ 63,
low_temp < high_temp ≤ 66, and high_temp < max_temp ≤ 90. It also writes
polling_interval = 1, the current upstream default. These conservative limits prevent accepted
settings from leaving the fans at minimum until an excessive temperature or delaying sensor
response. Values outside those ranges are rejected without touching the config.
sudo systemctl enable --now mbpfan
sudo systemctl status mbpfan # confirm it shows active (running)
Verify the hardware, driver, and config are all in place so the widget has data to show:
# The applesmc driver is loaded and exposes fan + temp sensors
ls /sys/devices/platform/applesmc.768/fan1_input # should exist
# A live CPU temperature (divide by 1000 for degrees Celsius)
cat /sys/class/thermal/thermal_zone1/temp # e.g. 78000 → 78°C
# Live fan speeds in RPM
cat /sys/devices/platform/applesmc.768/fan1_input
cat /sys/devices/platform/applesmc.768/fan2_input
# mbpfan is running and actively managing the fans
systemctl is-active mbpfan # should print "active"
# mbpfan can parse your config (look for a successful start in the log)
sudo systemctl status mbpfan --no-pager | tail -5
If any of the above returns nothing or an error, fix that first — the widget will show the same
result as these commands.
The widget’s bar icon is a Nerd Font glyph (the thermometer). Omarchy’s default monospace font is
already a Nerd Font, so this is usually already satisfied. If the icon appears as a hollow box
(tofu) rather than a thermometer, your bar font is not a Nerd Font and the glyph is missing.
Use the official Omarchy plugin command (from a git URL of this repo):
omarchy plugin add <this-repo-url> --enable
The plugin lands in ~/.config/omarchy/plugins/io.github.deadjoe.mbpfan/ and the widget is placed in the
right section of the top bar (per barWidget.defaultSection). If it doesn’t appear, open
~/.config/omarchy/shell.json and ensure the right layout contains { "id": "io.github.deadjoe.mbpfan" },
then reload the shell.
Run the read script manually; if it prints real numbers but the bar shows 0, re-read the
applesmc path (some machines expose a different fan numbering):
~/.config/omarchy/plugins/io.github.deadjoe.mbpfan/bin/mbpfan-status
Then check the prerequisites above (mbpfan service active, config present, sensors readable).
omarchy plugin update io.github.deadjoe.mbpfan
An update reloads the plugin in the running shell automatically, so no manual omarchy restart shell is needed; restart the shell only if the widget misbehaves after an update.
bin/mbpfan-status reads the applesmc sysfs files directly:
/sys/class/thermal/thermal_zone1/temp (CPU package)./sys/devices/platform/applesmc.768/fan1_input and fan2_input.It prints a single line TEMP FAN1 FAN2 every refresh. Nothing is written by the read path.
Applying needs no helper and installs nothing: both privileged steps use only fixed trusted
system binaries, and the only user-controlled input is the three digits-only temperature values.
20 ≤ low ≤ 63, low < high ≤ 66,high < max ≤ 90), canonicalizes them to short decimal strings, and fixes polling at thepkexec /usr/bin/sed -i … /etc/mbpfan.conf, where each expression is built from alow_temp, high_temp, max_temp, polling_interval) and either a validated1 — no user-controlled path, file, or code is in the expressions.pkexec /usr/bin/systemctl restart mbpfan to reload the service.No plugin code is ever executed as root, no user-writable file or path is ever opened by root, and
there is nothing to install — so there is no script-elevation, file/symlink TOCTOU, or install-source
race surface at all. Polkit may request authorization for the config write and service restart.
omarchy plugin disable io.github.deadjoe.mbpfan
omarchy plugin remove io.github.deadjoe.mbpfan
Removing also resets the bar layout that referenced the widget.
omarchy-shell process (like all Omarchy/usr/bin/sed, /usr/bin/systemctl) when you press Apply; nothing from the plugin is installedomarchy.* id namespace is reserved; this plugin uses io.github.deadjoe.mbpfan. Change theid (and the script paths in mbpfan.qml/Panel.qml) if you fork it under your ownMIT. See LICENSE.