Skip to content

Latest commit

Β 

History

History
43 lines (30 loc) Β· 3.49 KB

File metadata and controls

43 lines (30 loc) Β· 3.49 KB

mad-eye

Product

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.

Stack

  • 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/dobby as 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.

Module map

  • 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.ts bootstraps; styles.css is the dark panel theme.
    • src/popover/ β€” the Popover panel: renders a Snapshot (Rust-mirrored type + mockSnapshot for the dev URL) (CONTEXT).

Each module gets its own CONTEXT.md (purpose Β· Files Β· Interface Β· Invariants Β· What's NOT here) as it is built.

Conventions

  • 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.

Workflow config

  • /dobby:execute runs bunx dobby up and reads the dev URL from bunx 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 dev plus human/screenshot checks.
  • The Rust side is gated by the cargo test extra in dobby.config.json; the inferred gate covers the TS side.
  • Issue tracker: GitHub Issues (tracker.type: "github" in dobby.config.json).