Pixel Buds battery and listening-mode control, right in the Omarchy bar.
- Per-bud and case battery with charging and in-case state. The case only reports while a bud is docked (it has no radio of its own), so the last reading is cached and shown with a "last seen" age — same trick Android uses.
- Listening-mode panel: Off / Noise Cancelling / Transparency, plus
Adaptive when the installed
pbpctrlsupports it; clickable or keyboard-navigable. - Quick ANC cycling: right- or middle-click the bar icon to cycle modes without opening the panel, following the same mode loop configured on the buds themselves.
- Shared volume and swipe OSD: shows the buds' native Bluetooth absolute volume and summons Omarchy's volume OSD when either bud changes it.
- Device toggles: multipoint audio, speech detection (auto-transparency while you talk), on-head detection, and volume level alerts. Rows are capability-gated — a control only appears if your buds answer for it.
- Touch controls: enable/disable gestures, choose ANC or Assistant for each bud's hold action, and select the listening modes that hold cycles.
- Advanced sound, tucked behind a collapsed section: volume-dependent EQ, mono audio, balance, and the 5-band EQ.
- Low battery turns a battery row the urgent color at 20% or less.
- Event-driven: subscribes to BlueZ D-Bus signals via
gdbus, so the icon appears within about a second of the buds connecting — and while they're disconnected the plugin polls nothing at all.
The bar icon is the closed charging case, drawn to the proportions of the real thing.
- the
pbpctrlpackage from the AUR. If your Pixel Buds connect while it is missing, the bar icon shows in the urgent color and the popup explains, showing the install command with a button that copies it to your clipboard — paste it into a terminal to install. The plugin itself never installs software and never elevates privileges. - BlueZ (
bluetoothctl) and glib2 (gdbus) — both ship with Omarchy. python3(ships with Omarchy) for the descriptor-safepbpctrlruntime lock (fcntl flock on a no-follow fd) and the race-free case-battery cache helper. The lock fails closed without it.- Pixel Buds supported by
pbpctrl(Pixel Buds Pro generation).
omarchy plugin add https://github.com/rdoupe/omarchy-pixelbuds.git --enableomarchy plugin remove io.github.rdoupe.pixelbudsThe only file written outside the plugin directory is the cached case-battery
reading at ${XDG_STATE_HOME:-~/.local/state}/omarchy-pixelbuds/case, which
you can delete freely.
| Setting | Default | Meaning |
|---|---|---|
pollIntervalSec |
30 | Battery/ANC poll interval while connected (the panel polls faster while open) |
hideWhenDisconnected |
true | Hide the bar icon entirely while no Pixel Buds are connected; set false to keep a dimmed icon |
Configure via the bar widget settings or directly in
~/.config/omarchy/shell.json.
The widget exposes the IPC target io.github.rdoupe.pixelbuds with methods open,
close, toggle, showAdvanced, refresh, cycleAnc, and setAnc(mode) where mode is one
of off, active, aware, adaptive:
omarchy-shell io.github.rdoupe.pixelbuds cycleAnc
omarchy-shell io.github.rdoupe.pixelbuds setAnc awareHandy for keybindings.
status.sh first does a cheap bluetoothctl check for a connected pair; only
then does it talk to the buds over RFCOMM via pbpctrl for battery, placement,
and ANC state. Because Omarchy creates a bar instance on each monitor, all
pbpctrl calls share a runtime lock so their BlueZ profile registrations never
overlap. The lock is an atomic no-follow descriptor open of a private XDG
runtime file: owner, type, and link-count are checked on the opened fd, never
by stating a pathname and opening it later. Every helper is launched from a
closed environment (clearEnvironment + PATH=/usr/bin:/bin) using trusted
absolute identities (/usr/bin/sh, /usr/bin/timeout, /usr/bin/gdbus,
/usr/bin/python3 -I); helper shebangs must be exactly #!/usr/bin/python3 -I
(isolated — a plain /usr/bin/python3 shebang is a regression). pbpctrl
itself is resolved from /usr/bin:/bin and execve'd, never via ambient PATH. Connect/disconnect detection is
event-driven: a gdbus signal subscription on org.bluez triggers a refresh
the moment any device's Connected state flips, with a short follow-up pass
once the buds' RFCOMM channel settles.