A macOS menubar app showing Claude subscription usage limits (the /usage panel percentages) as an animated eye β Mad-Eye Moody style. The Eye gets more agitated as usage approaches a limit; clicking it opens a Popover with the detailed Gauges. Personal tool. Domain terms live in CONTEXT.md.
- Tauri v2 β macOS only. Rust core owns the interesting parts: the Eye (tray icon + Agitation animation), usage fetching, Keychain access.
- Vanilla TypeScript + Vite for the Popover webview. No frontend framework.
- bun as package manager;
@kvnwolf/dobbyas the workflow dev dependency (gate + lifecycle + toolchain). - Usage data: Anthropic's OAuth usage endpoint, authenticated with the credentials Claude Code stores in the macOS Keychain.
Dev: the web side runs via dobby up / dobby dev β dobby infers the dev command and wraps it in portless, so do NOT pin a dev command or hardcode a dev URL here. The NATIVE app (menubar Eye, real tray behavior) runs via bun tauri dev, which boots Vite itself on the fixed port 1420 that src-tauri/tauri.conf.json expects.
Release: /dobby:release delegates to the config-driven dobby release flow: bump, gate, universal DMG, Developer ID signing, notarization via the mad-eye-notary Keychain profile, GitHub Release, Homebrew cask update, and smoke check (ADR 0005). Releases are built locally only β CI never runs tauri build.
src-tauri/β Rust core: the Eye, Agitation, usage fetching, Keychain.src-tauri/src/eye/β renders one Eye pose to a template tray icon (CONTEXT).src-tauri/src/tray/β builds the menubar Eye and toggles/positions the Popover it opens (CONTEXT).src-tauri/src/usage/β headless data core: fetch/parse the usage endpoint into Gauges, compute Driving Gauge + Mood +Snapshot(CONTEXT).src-tauri/src/keychain/β read Claude Code's OAuth credentials from the Keychain, read-only (CONTEXT).
src/β the Popover webview (vanilla TS).main.tsbootstraps;styles.cssis the dark panel theme.src/popover/β the Popover panel: renders aSnapshot(Rust-mirrored type +mockSnapshotfor the dev URL) (CONTEXT).
Each module gets its own CONTEXT.md (purpose Β· Files Β· Interface Β· Invariants Β· What's NOT here) as it is built.
- Organize by feature/domain β no type-based
components//services//lib/buckets. - No barrels: callers import by deep path; each file is named by its role (the filename is the interface).
- Co-locate the slice; inline by default; extract only on the second caller.
- Each module carries its own CONTEXT.md. What works for humans is also great for AI.
- Rust side follows the same philosophy: modules by domain (tray, usage, keychain), not by layer.
/dobby:executerunsbunx dobby upand reads the dev URL frombunx dobby env(portless-resolved, worktree-aware β never hardcode it). That URL serves the Popover UI in a browser for programmatic verification.- Native behavior (menubar icon, Agitation, Keychain reads) is NOT reachable through the dev URL β verify it via
bun tauri devplus human/screenshot checks. - The Rust side is gated by the
cargo testextra indobby.config.json; the inferred gate covers the TS side. - Issue tracker: GitHub Issues (
tracker.type: "github"indobby.config.json).