Whole-project review pass over the entire crate. No new features. All function definitions preserved; layout and visibility reorganised. Bug fixes: - bubble: ExtractIconExW HICON pair was leaked per bubble toggle. Extract once into a process-wide OnceLock, reuse forever (bounded). - usage/anthropic: parse_iso8601 was stripping the UTC offset without applying it — negative-offset users saw countdowns up to 14h wrong. Now parses signed minutes and computes utc_secs = local - off*60. Also rejects y<1970, mo∉[1,12], d∉[1,max_day(mo,y)] up front so malformed API responses can't index DAYS_IN_MONTH out of bounds. - usage: clamp utilization to [0,100] at all four Window construction sites so a misbehaving server can't render "121%". - bubble: GetDC and CreateCompatibleDC results weren't checked. Guard both; release the screen DC on the CreateCompatibleDC failure path. Refactor: - Drop type TrayIconKind = ProviderId aliases (5 sites); use ProviderId directly everywhere. Inline the identity-function kind_to_provider. - Delete panel::bar_color_for shim (was just argument-reorder glue). - Replace local scale_to_dpi fns in bubble.rs and panel.rs with use crate::os::dpi::scale as scale_to_dpi (brings os::dpi into the live import graph; was unused before). - Delete dead PCWSTR import + #[allow(dead_code)] sentinel in tray/badge.rs; fold the trailing `use BOOL` into the top imports. - Inline app::primary_dpi() to crate::os::dpi::for_system(). app.rs: - Add update_settings(|s: &mut AppState|) helper that locks state, runs the closure, snapshots Settings, drops the lock, then saves to disk. Convert four pure-mutate-then-save callsites. Layering: bubble.rs no longer reaches upward into crate::app::. Introduce bubble::Callbacks (fn-pointers), OnceLock<Callbacks>, and bubble::install_callbacks(). The wnd_proc dispatches the six prior upward calls via a private dispatch() helper. app::run installs callbacks once at startup; the six on_bubble_* / recheck_theme fns are demoted from pub fn to fn. Resource-warning logs added: dispatch() warns on uninstalled callbacks; app_icons() warns when ExtractIconExW returns nulls. Build: cargo build --release clean; cargo clippy reports zero new warnings (11 pre-existing, all in untouched code).
Claude Code Usage Bubble
A floating, draggable circular bubble that shows your Claude Code and/or Codex usage on Windows — inspired by the floating "memory boost ball" UX of 360 Security and IObit Advanced SystemCare.
Drop it anywhere on screen, drag it around, snap it to a monitor edge, left-click for a panel with both your 5-hour and 7-day windows, right-click for the menu.
Acknowledgements
Inspired by CodeZeno/Claude-Code-Usage-Monitor, which solves the same "how close am I to the Claude Code limit?" problem with a horizontal taskbar widget. This project takes the UX in a different direction — a floating, draggable circular bubble that the user can place anywhere on screen — and is a clean-room implementation: the HTTP client, provider polling, credential discovery, localisation, tray rendering, and self-updater are all written from scratch against the same public APIs (Anthropic, ChatGPT, GitHub Releases).
What you get
- A circular floating bubble showing your current 5-hour Claude Code or Codex usage as a percentage and a colored progress ring
- Drag anywhere — the bubble snaps to monitor work-area edges when released
- Resize with
Ctrl + MouseWheelon the bubble (32–128 pixels) - Left-click the bubble for an expanded panel with both 5h and 7d bars plus reset countdowns
- Right-click for refresh, displayed models, update frequency, language, startup, updates, exit
- Optional system tray icons (one per enabled model)
- Auto-hide when a fullscreen app is in the foreground (games, video, presentations) — reappears when you leave fullscreen
Who this is for
Windows 10/11 users who already have Claude Code (CLI or App) installed and signed in. Codex support is optional — install and sign in to the Codex CLI, then enable Codex from the right-click Models menu.
If you use Claude Code through WSL, that is supported too. The monitor can read your Claude Code credentials from Windows or from your WSL environment.
Requirements
- Windows 10 or Windows 11
- Claude Code (CLI or App) installed and authenticated
- Optional: Codex CLI installed and authenticated, if you want Codex usage
Install
Download the latest release
Grab claude-code-usage-bubble.exe from the
Releases page.
Put it anywhere on disk (e.g. %LOCALAPPDATA%\ClaudeCodeUsageBubble\) and
run it. The app self-updates from the same Releases feed.
First-run note: the binary is unsigned, so SmartScreen will show "Windows protected your PC". Click More info → Run anyway. Code signing is on the roadmap.
Build from source
git clone https://github.com/tiennm99/claude-code-usage-bubble
cd claude-code-usage-bubble
cargo build --release
The binary lands at target/release/claude-code-usage-bubble.exe.
Use
Run claude-code-usage-bubble.exe. The bubble appears near the bottom-right
corner of your primary monitor on first launch. Drag it where you want it,
release to snap to the nearest edge if you let go close to one.
- Left-click the bubble to open the expanded panel (5h + 7d + countdowns)
- Right-click for refresh, models, refresh frequency, language, "Start with Windows", auto-update check (Disabled / Hourly / Daily / Weekly), manual "Check for updates", exit
- Drag anywhere — it floats on top of all other windows
- Ctrl + MouseWheel on the bubble to resize it
- Tray icon (if enabled): left-click toggles the bubble visibility, right-click opens the same menu
Models
Use the right-click Models menu to choose what is shown:
- Claude Code is enabled by default
- Codex can be enabled alongside Claude Code or shown by itself
When both models are shown, each gets its own bubble that you can position independently.
Diagnostics
claude-code-usage-bubble.exe --diagnose
This writes a log file to:
%TEMP%\claude-code-usage-bubble.log
Settings are saved to:
%APPDATA%\ClaudeCodeUsageBubble\settings.json
Privacy and security
What the app reads:
- Your local Claude Code OAuth credentials from
~/.claude/.credentials.json - If needed, the same credentials file inside an installed WSL distro
- If Codex is enabled, your local Codex credentials from
$CODEX_HOME/auth.jsonor~/.codex/auth.json
What the app sends over the network:
- Requests to Anthropic's Claude endpoints to read your usage
- Requests to ChatGPT's Codex usage endpoint, if Codex is enabled
- Requests to GitHub only if you use the app's update-check feature
What the app stores locally:
- Bubble position(s) per model
- Bubble size
- Polling frequency
- Language preference
- Last update check time
- Displayed model preferences
What it does not do: send credentials to any third-party server, run a
backend service, collect analytics, upload your project files, or write to
your Codex auth.json directly.
License
Apache License 2.0 — see LICENSE.