Your AI limits in the tray: how Bumeter's menu bar icon works
Most of the time you do not want another window. You want to glance up and know whether you can keep going. That is what Bumeter's tray icon is for: one small face in the menu bar, one click for the numbers, and the full app only when you ask for it.
What you see without clicking
Bumeter sits in the system tray: the menu bar on macOS, the notification area on Windows, the top bar on Linux. Two things are always visible:
- Bum, the mascot. Its face tells you how things are going before you read a single number.
- The highest percentage across your limits, next to the icon (macOS and Linux). On Windows, hovering the icon shows a one-line summary instead.
The rules are checked in that order, so the most urgent face wins. "On pace to run out" counts every tool, so Kiro credits running low worry Bum too, not only Claude's windows. Both thresholds come from Settings, the same numbers that trigger notifications.
What the menu shows
Click the icon and the menu opens with one block per tool you have installed. Tools Bumeter supports but that are not on your machine are left out.
- Claude Code has two rows, the 5-hour and the 7-day window, each with its percentage and when it resets.
- Kiro bills in monthly credits, so it gets one row: credits used out of your limit, and the next reset date.
- A tool with no limit to track shows what it used today instead, for example
OpenCode · today 340K tokens · 12 turns. - When your current pace would hit a limit before it resets, the row says when:
5 hours · 78% · out ~14:32 · reset 15:10. - When no reading has arrived for 10 minutes, the ring turns grey and the row says how old the number is (
updated 25 min ago), rather than pretending it is current.
On macOS and Windows each row has a small ring: orange as it fills, red from your warning threshold or when you are on pace to run out, grey when the data is old. Linux menus cannot show those icons, so the same information is drawn in text: a ten-cell bar and a coloured dot.
How to use it
- Install and start Bumeter. It goes straight to the tray and starts reading your logs; there is nothing to configure for tokens.
- Turn on limit tracking for the Claude Code percentages: Settings → Limit tracking. Bumeter reads them from Claude Code's status line (the previous post explains how). For Kiro, Bumeter asks
kiro-clifor your real credit usage by itself, at startup and every 15 minutes; if that is not available, set your monthly credit limit in Settings. - Click a tool's row to open the app already filtered to that tool.
- Pause notifications for 1 hour when you are in a meeting or presenting. The tray keeps updating; only the pop-ups stop.
- Close the window when you are done. Bumeter keeps running in the tray. Use Quit to stop it.
The menu speaks your language (English or Vietnamese, from Settings) and follows Settings immediately: change a threshold and the next refresh uses it.
How it is built
The tray is part of the Bumeter desktop app, built with Tauri. The interesting parts are less about the tray API and more about keeping a small icon honest, cheap and identical on three operating systems.
One source of truth for the text
The text of every row is not written in the app. It comes from meter::render_tray in bum-core, the same library that serves the CLI. That is why bum status in a terminal prints the same tool lines as the tray menu: they are the same function. The app only places the rows into the menu.
The menu is built once, when the app starts, with a fixed number of rows per tool (the tool registry decides how many). After that, each refresh only changes the text (and, where it changed, the icon) of the items that are already there; the menu itself is never rebuilt.
When it refreshes
The tray updates when there is something new, and otherwise stays quiet:
- after new log lines are read (you finished a turn),
- when a new quota reading arrives from the status line,
- and every 30 seconds, so "updated 25 min ago" and reset times stay correct while you are idle.
Each refresh reads the settings file again, so a change in Settings shows up without a restart.
Ring icons drawn in Rust
Each ring is a 32×32 image drawn in plain Rust, anti-aliased by sampling every pixel 4×4 times, with a translucent grey track so it looks right on light and dark menus. There is no image library and no SVG renderer. Percentages are rounded to whole numbers, so there are at most 101 rings per colour, and each one is drawn once and cached. A row's icon is only replaced when its rounded value or colour actually changes.
Linux is different, so it gets text
On Linux the tray goes through AppIndicator and D-Bus menus. Two limits there shaped the design: menu item icons are not shown in the GNOME top bar, and an item that has an icon cannot change its label afterwards. So on Linux every row is a plain text item, and the ring becomes text:
▰▰▰▰▰▱▱▱▱▱ 🟢 5 hours · 49% · reset 13:10
The bar comes first on purpose: menu fonts are proportional, and starting each line with the fixed-width bar keeps them lined up. A used limit shows at least one cell, and the bar is only full at 100%, so 99.6% never looks like "blocked". Menu text cannot be coloured, but emoji can, so the dot carries the colour.
The mascot is a pure function
The face is chosen by a small function, face_for, from a handful of facts: how old the quota data is, minutes since your last turn, the 5-hour percentage and your two thresholds, minutes since the last unusually expensive turn, today's tokens against your 30-day average, and whether any tool is on pace to run out. It has no side effects, so every rule has a unit test, and the Bum on the app's screens follows the same rules.
Light when idle
The window exists only while it is open. Closing it destroys the web view instead of hiding it, so the app sitting in your tray all day costs little memory. Clicking Open Bumeter builds a fresh window, and clicking a tool row opens it straight on that tool.
Bumeter is free and open source (GPL-3.0), and everything stays on your machine. The source is at github.com/chieund/bumeter. The tray code lives mostly in app/src-tauri/src/tray.rs, crates/bum-core/src/meter.rs, ring.rs and face.rs.