An unofficial watcher that shows the status of local Codex desktop tasks on a BUSY Bar, without unlocking your Mac.
Front RGB LED matrix:
Back monochrome OLED:
These are direct framebuffer captures from the bar, enlarged with nearest-neighbor scaling to keep the physical pixels crisp. No display content was mocked or recreated.
- Working: a large blue count of active tasks, gently breathing between 75% and 100% brightness. Two lines show the newest available Codex activity summary in steady white.
- Waiting: a large flashing amber
DONEonce no tasks remain active. - Acknowledge: pressing the BUSY Bar's physical start/pause button clears
DONE. It stays clear until another task starts and finishes. - Completion sound: the bundled CC0
jump.wavplays whenever the active task count decreases. The default volume is 50%.
Both the front and back displays are updated. When a Codex turn does not emit an
activity summary, the display uses WORKING... rather than showing stale text
from a previous turn.
- macOS with
launchd - Python 3.10 or newer
- Codex desktop app
- A BUSY Bar reachable over USB or Wi-Fi
The installer creates an isolated .venv, installs the pinned dependency in
requirements.txt, and registers a per-user launch agent.
Clone the repository, then run:
./install.shThe default USB API address is http://10.0.4.20. Pass a different address as
the first argument for Wi-Fi or a non-default setup:
./install.sh http://BUSY-BAR-IPWi-Fi HTTP access must first be enabled in the bar's Network settings. If it uses an API token, save the token in a private file and pass that file as the second argument:
./install.sh http://BUSY-BAR-IP /path/to/token-fileKeep that file private, for example with chmod 600 /path/to/token-file.
The included jump.wav comes from OwlishMedia's CC0
8-Bit Sound Effect Pack.
Its provenance is recorded in THIRD_PARTY_LICENSES.md.
To use another WAV, pass it as the third installer argument:
./install.sh http://10.0.4.20 "" /path/to/completion.wavThe watcher uploads it to the bar and sets the device-wide audio volume to 50%.
The same settings can be supplied through BUSYBAR_URL,
BUSYBAR_TOKEN_FILE, and BUSYBAR_SOUND_FILE. Set BUSYBAR_CODEX_LABEL if a
custom launch-agent label is needed. If Codex data lives somewhere other than
~/.codex, set CODEX_HOME when running the installer.
Inspect the default service and follow its log:
launchctl print gui/$(id -u)/io.github.busybar-codex
tail -f ~/Library/Logs/busybar-codex/busybar-codex.logStop it and move its launch-agent plist to the Trash:
./uninstall.shPreview either state:
.venv/bin/python busybar_codex.py --state working --once
.venv/bin/python busybar_codex.py --state waiting --onceInspect the detected Codex state without changing the display:
.venv/bin/python busybar_codex.py --dry-runSee every option:
.venv/bin/python busybar_codex.py --help.venv/bin/python -m unittest -vThe watcher runs entirely on the Mac. It reads lifecycle and activity-summary
events from rollout JSONL files in ~/.codex and sends display/audio commands
directly to the BUSY Bar. The physical button is received through the official
BUSY Bar WebSocket state stream provided by
busylib and the documented
BUSY Bar HTTP API.
There is no screen scraping, Accessibility permission, cloud service, or Codex account access. It intentionally does not inspect or modify the desktop app's private unread UI state. Codex's local rollout format is an implementation detail and could change in a future release.
Display priority is 80. It overrides ordinary built-in apps at priority 10,
while an active BUSY/CUSTOM work session at priority 90 still wins. The physical
start/pause button retains its normal firmware behavior in addition to
dismissing this watcher's DONE overlay.
The code is MIT licensed. The bundled completion sound is available under CC0; see THIRD_PARTY_LICENSES.md.

