BUILDINGapp

devHUD

A Codenotch-style side pill for macOS: AI usage rings for Claude, Copilot and Codex, and the dev servers listening on the machine, one hover away.

CREATED SEP 4, 2026 · UPDATED SEP 5, 2026

PROBLEM

Three AI coding tools, three rate-limit windows, none of them visible without leaving the editor. Claude Code has a /usage command, Codex writes its limits into session logs, Copilot has an undocumented endpoint, and each one resets on its own clock. Add the dev servers left running across a dozen projects and the machine's state lives in six terminals.

Codenotch showed the shape of the answer: a black pill on the screen edge that hides to a sliver and opens on hover. It only covers the usage half, and it is not open.

HYPOTHESIS

Every number worth glancing at is already on the machine. Claude Code's credentials file, the Codex session JSONL, the gh CLI's token, lsof and libproc: no new account, no telemetry, no backend. A read-only app that polls those sources and paints them into a hover pill should be buildable in a day and cost nothing to run.

ARCHITECTURE

Two borderless non-activating NSPanels, the pill and a card, drawn with SwiftUI and hit-tested from window frames rather than view tracking areas, because a never-key panel cannot be trusted to deliver enter and exit events in order. Hover is a pure function from cursor location to target; drag snaps the pill to the nearer edge of whichever display the cursor is on.

Three stores poll on their own tasks: usage every two minutes (one provider slot per Claude account, plus Copilot and Codex), listening ports every four seconds through lsof with libproc enrichment, portless routes every twelve. Each provider caches last-good data and backs off on failure. Every parser is a pure function over Data and is what the test suite covers.

The servers card is the one place the app acts: open a web UI, kill with an in-row confirm, restart by re-running the kernel-reported executable with every argument quoted, or open the cwd in an editor or terminal.

STACK

SwiftSwiftUIAppKitXcodeGenlibprocHomebrew

RESULT

Running as a login item on the Mac mini from the first day. Version 0.3.1 has a release script that refuses to tag anything unsigned or unnotarized, a Homebrew cask that lints clean, a CI workflow for tag pushes, and a SECURITY.md. The one open item is a Developer ID certificate; until then it ships nowhere but here.

MEASURED

metricvaluebaseline
unit tests76 · parsers, geometry, hover resolution, shell quoting—
resident memory after 25 s91.5 MB · before the Codex tail read1 GB peak
idle CPU0.1 % · lsof every 4 s at about 44 ms each—
Codex session bytes read per poll4 MB · tail of the newest rollout file239 MB
adversarial review findings74 · 54 fixed, 3 rejected with measurements, the rest accepted in writing—
empty repo to running app1 session · 2026-09-04—

LEARNINGS

  • Hover on a non-key panel is a geometry problem, not a view problem. Resolving the cursor against window frames made the state machine testable and killed a class of stuck-card bugs.
  • A SwiftUI shadow on a transparent window is not transparent to clicks. The window's own shadow is.
  • NSScreen.main follows the active app and will move your window to another display when nobody is looking.
  • The libproc rusage call writes into the struct whose address you pass, not into a pointer you pass the address of. The stack overflow was instant and the test host died with it.
  • Reading whole Codex session files cost a gigabyte every two minutes. The newest rate-limit event is always in the last four megabytes.
  • Four adversarial review passes on one day's code found 74 issues. The three rejected ones were rejected with measurements, not opinions.

PROVENANCE

Built on 2026-09-04 and 2026-09-05 in Claude Code with Fable 5.1 writing the code, Opus and Codex reviewing it adversarially, and a separate security pass before packaging. Seven tasks, each with intent, spec, plan, claims and verify artifacts under .buildloop/ in the repository. Screenshots were the live check throughout, because the machine grants no Accessibility rights to synthetic input.

TAGS

macosswiftuiappkitclaude-codedeveloper-toolshud