feat: cross-platform tray / menu-bar app showing today's spend#39
Open
jakduch wants to merge 5 commits into
Open
feat: cross-platform tray / menu-bar app showing today's spend#39jakduch wants to merge 5 commits into
jakduch wants to merge 5 commits into
Conversation
Adds 'python cli.py tray' — a glanceable menu-bar icon that polls the running dashboard every 60s and shows today's + this month's Claude spend in a dropdown, with a one-click 'Open Dashboard'. - macOS: rumps (native NSStatusBar) - Linux / Windows: pystray + Pillow - Both backends optional & lazy-imported (import tray always works) - Optional badge colour: green < $1, amber $1-$10, red > $10 Files: tray.py — new module, ~300 LOC, two backends + pure helpers cli.py — new 'tray' command with --url override tests/test_tray.py — 19 tests (lazy import, helpers, CLI wiring, polling) README.md — new 'Menu bar app' section with install + usage No new hard dependencies — rumps/pystray are optional extras the user installs only if they want the tray feature.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this add and why do you believe it belongs in this dashboard?
This adds a cross-platform tray / menu-bar companion that surfaces today's Claude Code spend right in the system tray (Linux/Windows) or macOS menu bar, with a single click to open the full dashboard in the browser.
The case for it fitting a personal Claude Code usage dashboard: cost awareness only changes behaviour when it is glanceable. Opening the dashboard is a deliberate act — by the time a heavy day is noticed, the spend has already happened. A persistent indicator turns that into ambient feedback: the running dollar figure is always in the corner of the screen, colour-coded green / amber / red against the existing $1 and $10 thresholds, and refreshed every 60 seconds from the dashboard’s own
/api/dataendpoint. No new server, no new data path, no duplicate pricing logic — it reusespricing.calc_costand the running dashboard as the single source of truth. Clicking the indicator opens the dashboard for the full drill-down. Both backends (rumpson macOS,pystrayelsewhere) are optional and lazy-imported, so nothing changes for users who don’t opt in.Checklist
Code correctness
calcCost()calls pass 6 arguments:(model, inp, out, cache_read, cache_creation, cache_1h)`), not escaped ones (\`)Tests
python3 -m unittest discover -s tests -v— all passingpython3 -m unittest tests.test_browser -v— all passingScope
dashboard.py,scanner.py,cli.py,pricing.py,cowork.py,tests/) — or I’ve explained below why a new file is neededtray.pyis a new top-level module. It is isolated by design: the tray UI is an optional, lazily-loaded companion process with its own platform backends (rumps/pystray), and putting it next tocli.pykeepsdashboard.pyandscanner.pyfree of GUI concerns.tests/test_tray.pyis added alongside it. No third-party imports are added at module top level — both GUI libraries are imported insiderun()soimport trayalways succeeds (CI, headless dev, users who never enable it).