Header image source: Colorful bus Pakistani via Wikimedia Commons.
Bright, bus-art Waybar for niri on Wayland.
- Loud per-chip gradients with compact, tooltip-heavy modules.
- A two-strip layout: the main working bar at the bottom and a compact telemetry strip at the top-left.
- Custom helpers for CPU temperature smoothing, disk I/O, clipboard preview, Codex quota display, VPN device display, media metadata, Bluetooth HID battery readings, external IP with click-through IP lookup, system and user
systemdfailure monitoring, Niri keyboard layout state, a hidden-by-default YubiKey touch chip, and a Vocalinux activity chip with separate listening and processing states. - A
stasischip on the top strip shows idle-manager state as words instead of ambiguous icons:WAIT,RUN,HOLD,DBUS,CALL,APP,PAUSE,DOWN. Left click toggles manual inhibit, middle click reloads config, right click restarts the service. These user-triggered actions show their result through SwayOSD on the focused output. - A screenshot helper so bar changes can be checked against the live UI instead of config-only guesses.
waybarniripython3playerctlfor the media chipcurlfor the external IP chipwf-recorderandffmpegforcapture-waybar.shwl-gammarelay-rsand optionallywl-gammarelay-appletswayosd-clientif you want layout-switch, hardware-backlight, and gamma-brightness OSDvocalinuxif you want the dictation activity chipsystemctlfor thesystemdfailure chip
This repo is meant to live at ~/.config/waybar.
mkdir -p ~/.config/waybar
cp -r . ~/.config/waybar/
chmod +x ~/.config/waybar/*.py ~/.config/waybar/*.sh
~/.local/bin/restart-waybarPrivate local values live in ignored local.env. Copy
local.env.example to local.env and fill a work-calendar URL there instead
of committing it to config.jsonc.
- The config is pinned to
eDP-1right now. - Startup logging for login-time failures goes to
~/.local/state/waybar/startup.log, and each launch also gets a dedicated run directory under~/.local/state/waybar/runs/with a small allowlisted environment snapshot,systemdstatus, user-journal snapshots, and the rawwaybarwarning-level log.~/.local/state/waybar/latestpoints at the newest run. - Run directories older than 2 days are pruned by
start-with-log.shon each Waybar startup so diagnostics stay local and bounded. - Flat helper logs such as
startup.logandclipboard-watch.logare trimmed to the latest 2000 lines once they exceed 1 MiB. - The default
nirispawn-at-startup "waybar"is intentionally intercepted via~/.local/bin/waybar, which forwards intostart-with-log.shbefore starting the real binary so login-time failures survive after the session is gone. - Waybar uses deterministic visibility signals:
SIGUSR1shows the bars andSIGUSR2hides them. Config/style watch reloads must use~/.local/bin/restart-waybarinstead ofSIGUSR2. - Right-clicking the bottom bar's power chip hides both bars.
Mod+Atoggles sticky Waybar visibility. Bare Mod opens Walker throughwalker-with-waybar; on a single active output that wrapper shows Waybar temporarily while Walker is open, but it will not hide a bar that was made sticky-visible byMod+A.Mod+Dlaunches~/.local/bin/walker-with-waybar; when Niri reports exactly one output, the wrapper shows Waybar temporarily before opening Walker and hides it again only if the wrapper itself showed it. Multi-output sessions leave Waybar visibility alone.clipboard-watch.shdoes not signal Waybar immediately on startup and skips the firstwl-paste --watchevent for each selection. Waybar renders clipboard modules during its own startup, and an immediateSIGRTMIN+10can kill a just-spawned Waybar before it installs the custom signal handler. Later clipboard changes still signal Waybar and are logged in~/.local/state/waybar/clipboard-watch.log.- The power chip uses
power-menu-action.shinstead of rawsystemctlcalls sochallengeresponses from logind are handled cleanly. When Waybar runs outside the real logind session, the helper delegates the action throughpower-menu-session-bridge.sh, which is started by the login fish shell and listens on a private FIFO under$XDG_RUNTIME_DIR/waybar-power-menu/. - The top strip owns the newer status chips first: Codex,
systemd, Vocalinux, top-processes, clipboard preview, and external IP. The disk I/O chip stays on the bottom bar. When the bottom bar gets crowded, newer chips should move to the top before older baseline controls. - Expensive polling chips are intentionally not 1 Hz: top-process sampling runs every 10 seconds, while disk/network/VPN/loopback and built-in CPU/memory refresh every 5 seconds. Keep the bar responsive through signals for eventful chips instead of returning to broad 1-second polling.
- Critical chips use static high-contrast colors and glow rather than infinite CSS blink animations. GTK keeps repainting animated Waybar CSS even while the bars are hidden, so avoid reintroducing always-on animations for status chips.
- The CPU temperature chip reads
coretemp/Package id 0fromhwmonfirst so it matchessensorspackage-temperature output;x86_pkg_tempthermal-zone data is only a fallback. - The YubiKey chip is hidden by default.
~/.local/bin/yubikey-touch-osdwrites its state under$XDG_RUNTIME_DIR/yubikey-touch-osd/waybar.jsonand signals Waybar withSIGRTMIN+11;yubikey-touch-status.pyonly shows a blinkingYK ...chip while the detector reports an activeGPG,U2F, orMACtouch wait. On the inactive-to-active transition the same watcher plays the cached speech prompt~/.local/share/yubikey-touch-osd/waiting-for-yubikey-v2.mp3through~/.local/bin/play-audio-with-afk-volume. - For
stasis,RUNdeliberately means "the idle plan is currently advancing" rather than "the monitor is off". It can correspond to a lock countdown or any later action stage, so the exact meaning lives in the tooltip, not in the short chip text. The tooltip also includes a full legend for every short state code. - The
stasischip actions call~/.local/bin/stasis-action-osd. The helper reports pause/resume, config reload, restart, and failures through SwayOSD on the focused Niri output. Automatic idle-state transitions remain quiet. - The audio chip uses private-use glyphs through Nerd Font. Keep its icons to codepoints present in
Symbols Nerd Font; older Font Awesome glyphs such asU+F590andU+F6A9render as missing boxes on this machine. - When the default sink is muted, the audio chip shows a blinking
MUTEDlabel instead of relying on a small icon, because mute can otherwise be easy to forget during speech-notification tests. - The gamma-brightness chip scroll actions call
~/.local/bin/gamma-brightness-osdinstead of rawbusctl, so Waybar scrolls use the sharedwl-gammarelay-rsupdate and focused-output SwayOSD path. - The hardware backlight chip scroll actions call
~/wb/radar/bin/adaptive-brightness-osd. With only the built-in Niri output active, it controlsintel_backlightthroughhw-backlight-osd; with any external output active, it controlswl-gammarelay-rsgamma brightness throughgamma-brightness-osd. Both paths keep SwayOSD pinned to the focused Niri output. - The top-strip Bluetooth HID battery chip reads connected Bluetooth devices
from
bluetoothctl, keeps keyboard/mouse-like HID devices with battery data, and hides itself when none are connected. It blinks only below 10% so low external-device battery is hard to miss without being noisy at normal charge levels. capture-waybar.shstill captures the bottom bar strip intentionally.- Network chips use
net-dev.pyfor the bottom-left Ethernet-like and Wi-Fi chips. The Ethernet-like chip prefers the active default-route non-Wi-Fi, non-VPN interface, so USB tethering interfaces such asenp0s20f0u1win over an unplugged onboard Ethernet port. The Wi-Fi chip is hidden when no Wi-Fi interface is up with an IPv4 address. Loopback still uses Waybar's built-innetwork#loopbackmodule. - Clipboard preview treats only real plain-text MIME types as text. Browser image copies often expose
text/htmlplusimage/*; in that case the chip should prefer the image path and render[img]instead of showing HTML preview markup.
./capture-waybar.sh assets/waybar.pngThat keeps the README screenshot aligned with the live bottom bar.