cd /news/ai-tools/show-hn-llm-usage-desktop-widget · home › topics › ai-tools › article
[ARTICLE · art-152496] src=github.com ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Show HN: LLM Usage Desktop Widget

A developer released LLM Usage Widget, a desktop app for Linux, macOS, and Windows that displays Claude and Codex plan usage limits — session and weekly windows, model-scoped limits, and reset countdowns — in the system tray or menu bar. The widget reuses logins already stored by Claude Code and the Codex CLI, reading credentials from the macOS Keychain or ~/.claude/.credentials.json for Claude and ~/.codex/auth.json for Codex, and sends each token only to the provider that issued it. It queries the same undocumented internal endpoints the official CLIs use for their /usage and /status screens (api.anthropic.com/api/oauth/usage and chatgpt.com/backend-api/wham/usage), turns bars amber at 75% and red at 90%, and keeps the last numbers marked stale if a refresh fails.

read10 min views12 publishedOct 18, 2026
Show HN: LLM Usage Desktop Widget
Image: Michielbdejong (auto-discovered)

Shows your Claude and Codex plan usage limits (session / weekly windows, model-scoped limits, and time until each resets) where your system status icons live:

Linux (Ubuntu) macOS Windows
OS Where it appears What it shows
Linux Top bar / panel, next to Wi-Fi and sound (AppIndicator) Icon + Claude 99% Codex 13% ; click for details
macOS Menu bar, top right Gauge icon + Claude 99% Codex 13% ; click for details
Windows An empty spot on the taskbar, plus a tray icon Claude 99% Codex 13% on the taskbar and a two-bar gauge icon; click either for details

The dropdown lists every limit with its percentage and reset countdown, plus Refresh now, links to each provider's usage page, and Quit. Bars and icons turn amber at 75% and red at 90% (or whatever severity the provider reports). If a refresh fails, the last numbers are kept and marked stale.

There is also a floating always-on-top window (--widget) for desktops without a tray.

It reuses the logins that Claude Code (claude) and the Codex CLI ( codex) already store on your machine, so there is nothing to configure. Credentials are only read, never modified, and each token is sent only to the provider that issued it.

Provider Credentials read from Endpoint
Claude macOS Keychain Claude Code-credentials , else~/.claude/.credentials.json ($CLAUDE_CONFIG_DIR ) api.anthropic.com/api/oauth/usage
Codex ~/.codex/auth.json ($CODEX_HOME ) chatgpt.com/backend-api/wham/usage
Bedrock Your AWS credentials (profile, SSO, env vars), via boto3 AWS Budgets, Cost Explorer, CloudWatch

These are the same internal endpoints the official CLIs use for their /usage and /status screens. They are undocumented and may change; if a provider shows an error after an update, check the parser for that provider in usage_widget.py.

First log in to each CLI once with your subscription: claude → /login, and codex login. Each installer puts the app where it belongs for the OS, starts it right away, and starts it again every time you log in.

Download from the GitHub release (built by .github/workflows/build-installers.yml):

OS File Notes
Linux (Debian/Ubuntu) llm-usage-widget_<ver>_all.deb sudo apt install ./llm-usage-widget_*.deb . Starts right away for every logged-in user, and at login via/etc/xdg/autostart .
macOS LLM-Usage-Widget-<ver>-macos-arm64.pkg (Apple Silicon) or-x86_64.pkg (Intel) Installs /Applications/LLM Usage.app plus a login LaunchAgent. Release builds are signed with a Developer ID and notarized by Apple.
Windows LLM-Usage-Widget-<ver>-windows-setup.exe Per-user install, no admin rights needed. "Start automatically when I sign in" is ticked by default. The build is unsigned, so SmartScreen may warn: click More info → Run anyway . Uninstall fromSettings → Apps , theUninstall LLM Usage Widget Start Menu entry, or by runningLLM-Usage-Widget-<ver>-windows-uninstall.exe from the same release (add/VERYSILENT to skip the prompts). Settings in%APPDATA%\llm-usage-widget are kept.

To uninstall the macOS package, open LLM-Usage-Widget-<ver>-macos-uninstall.pkg from the same release (it asks for an administrator password), or run the copy of the uninstaller inside the app:

sudo "/Applications/LLM Usage.app/Contents/Resources/uninstall.sh"

Either one stops the widget for every logged-in user and removes the app, its LaunchAgent and the package receipt. Settings in ~/Library/Application Support/llm-usage-widget are left in place.

On Debian/Ubuntu: sudo apt remove llm-usage-widget.

OS Install Uninstall
Linux / macOS ./install.sh ./install.sh --uninstall
Windows double-click install.cmd (orpowershell -ExecutionPolicy Bypass -File install.ps1 ) uninstall.cmd
  • Linux: copies to~/.local/share/llm-usage-widget , adds an app-menu launcher and~/.config/autostart/llm-usage-widget.desktop . Uses the system Python's PyGObject and AppIndicator (preinstalled on Ubuntu; the script prints the package command for your distro if they're missing). On GNOME the AppIndicator extension must be enabled (the default on Ubuntu; elsewhere install "AppIndicator and KStatusNotifierItem Support"). KDE, XFCE, Cinnamon and others work out of the box, though some panels show only the icon, not the text label.
  • macOS: needs Python 3.9+ (python.org or Homebrew). Copies to~/Library/Application Support/llm-usage-widget with its own virtualenv and registers~/Library/LaunchAgents/local.llm-usage-widget.plist . Logs go to~/Library/Logs/llm-usage-widget.log .
  • Windows: needs Python 3.9+ from python.org. Copies to%LOCALAPPDATA%\llm-usage-widget with its own virtualenv and adds Start Menu and Startup shortcuts.

On macOS the first run may ask for Keychain access to Claude Code-credentials; choose Always Allow. On Windows the numbers are drawn on the taskbar itself: left of the ^ arrow when there is room, otherwise in the next empty gap (with centered taskbar buttons, usually left of Start), on two smaller lines if that is what fits. It never covers taskbar buttons; if the taskbar is completely full it hides until there is room. Windows has no API for text in the taskbar, so this is a small always-on-top window that follows the taskbar and steps aside for full-screen apps and an auto-hidden or vertical taskbar. Turn it off with Show usage on the taskbar in the menu. The tray icon may be tucked into the overflow (^) menu; drag it onto the taskbar to keep it visible.

/usr/bin/python3 usage_widget.py               # Linux (system Python, for PyGObject)
python3 -m pip install -r requirements.txt     # macOS / Windows: pystray + Pillow
python3 usage_widget.py                         # Windows: pythonw usage_widget.py (no console window)

Only one copy runs at a time; starting a second one exits immediately.

usage_widget.py                  # tray / top bar / menu bar (default)
usage_widget.py --widget         # floating always-on-top window instead
usage_widget.py --widget --framed    # ...with a normal title bar
usage_widget.py --once           # print usage in the terminal and exit
usage_widget.py --interval 300   # refresh every 5 minutes (default 180 s, min 60 s)

Claude Code and Codex refresh their own tokens while you use them. If you haven't used one for a while, its access token may expire and the widget will say so. Open that CLI once and the widget picks up the new token on its next refresh. The widget deliberately does not refresh tokens itself, because rotating the refresh token would log the CLI out.

The Ubuntu AppIndicators extension shipped with GNOME 50 comes up half-broken at login: until it is reloaded, apps that start after its initial bus scan get No such method "RegisterStatusNotifierItem" and don't appear (this also hits Remmina, update-notifier, etc.). Apps already running during that scan do appear, so starting the widget at login usually works. install.sh detects the broken state and reloads the extension once so the icon appears immediately. If the icon is missing, reload it by hand:

gnome-extensions disable ubuntu-appindicators@ubuntu.com && gnome-extensions enable ubuntu-appindicators@ubuntu.com

The GitHub Actions workflow builds every installer on its own OS. Push a tag matching __version__ in usage_widget.py (e.g. v1.0.0) to build them and attach them to a release, or run the workflow by hand to download them as build artifacts. To build locally on each OS:

packaging/linux/build-deb.sh                                   # Linux → dist/*.deb
python3 -m pip install pyinstaller -r requirements.txt
packaging/macos/build-pkg.sh                                   # macOS → dist/*.pkg
powershell -File packaging\windows\build.ps1                   # Windows → dist\*-setup.exe (needs Inno Setup 6)

To sign the macOS build locally, set CODESIGN_IDENTITY (a "Developer ID Application" identity) and INSTALLER_SIGN_IDENTITY ("Developer ID Installer"). The app is signed with the hardened runtime and a secure timestamp, which is what notarization requires. Then notarize and staple the pkg:

xcrun notarytool submit dist/*.pkg --keychain-profile <profile> --wait
xcrun stapler staple dist/*.pkg

In CI, the macOS job signs, notarizes and staples the pkg when these repository secrets are set. A tag release fails without them:

Secret Contents
MAC_CERT_P12_BASE64 /MAC_CERT_PASSWORD The Developer ID Application certificate and private key, as a base64-encoded .p12 , and its export password
MAC_INSTALLER_CERT_P12_BASE64 /MAC_INSTALLER_CERT_PASSWORD The same for the Developer ID Installer certificate
AC_API_KEY_P8_BASE64 /AC_API_KEY_ID /AC_API_ISSUER_ID An App Store Connect API key (the base64-encoded .p8 ), its key ID and issuer ID, used bynotarytool

The workflow Authenticode-signs LLMUsageWidget.exe and the setup .exe with Azure Trusted Signing (the same setup as Virux), timestamps both, and checks the signatures before up. A tag build fails rather than publish an unsigned installer; a manual run without the secrets builds unsigned with a warning. It needs these repository (or organization) secrets:

Secret What it is
AZURE_TENANT_ID Entra ID tenant of the app registration that signs
AZURE_CLIENT_ID That app registration's client ID
AZURE_CLIENT_SECRET A client secret for it; also how the workflow decides whether to sign
AZ_TS_ENDPOINT The Trusted Signing account's regional endpoint, e.g. https://eus.codesigning.azure.net
AZ_TS_ACCOUNT Trusted Signing account name
AZ_TS_PROFILE Certificate profile name

The app registration needs the Trusted Signing Certificate Profile Signer role on the account.

Publisher name only, no address. Windows shows the certificate's common name, the validated organization name ("Aleph Void LLC"), as the publisher in SmartScreen, the UAC prompt and the file's Digital Signatures tab. Create the Public Trust certificate profile with Include street address and Include postal code both unticked (the default) so the certificate carries no address. City, state and country are always part of a Public Trust certificate's details and can't be removed. packaging/windows/verify-signature.ps1 fails the build if a signature is invalid, not timestamped, or its certificate includes a street address or postal code. Run it on a downloaded installer to check it yourself:

powershell -File packaging\windows\verify-signature.ps1 .\LLM-Usage-Widget-<ver>-windows-setup.exe

The release's -windows-uninstall.exe is signed the same way. The uninstaller that Inno Setup writes into the install folder at install time is not signed. It runs without elevation (the install is per-user), so Windows doesn't show a publisher prompt for it.

If Claude Code or Codex runs on Amazon Bedrock instead of a subscription, there are no session or weekly limits to show. Instead the widget adds a Bedrock section that shows:

  • Budget: spend against anAWS Budget as a percentage bar that resets with the budget period. This only appears if you name a budget (see below).
  • This month: month-to-date spend for every service with "Bedrock" in its name, from Cost Explorer. Third-party models such as Claude are billed as Marketplace services named likeClaude Sonnet 4.5 (Amazon Bedrock Edition) , and these are included.
  • Tokens today: input and output tokens since local midnight, from CloudWatch. This covers both thebedrock-runtime endpoint (AWS/Bedrock ) and the OpenAI/Anthropic-compatiblebedrock-mantle endpoint (AWS/BedrockMantle ).

The section turns on automatically when Claude Code's settings set CLAUDE_CODE_USE_BEDROCK (or an ANTHROPIC_BASE_URL containing bedrock), or when a base_url in ~/.codex/config.toml points at Bedrock. The AWS profile and region come from the same place: AWS_PROFILE and AWS_REGION in Claude Code's env block, or the region in Codex's base_url. In that case the Claude or Codex section is hidden if that CLI has no subscription login. To override any of this, add a bedrock entry to config.json in the widget's config folder (~/.config/llm-usage-widget/ on Linux, ~/Library/Application Support/llm-usage-widget/ on macOS, %APPDATA%\llm-usage-widget\ on Windows):

{
  "bedrock": {
    "profile": "work",
    "regions": ["us-east-1", "us-west-2"],
    "budget": "bedrock-monthly",
    "cost_explorer": true,
    "cost_interval": 21600,
    "metrics_interval": 900
  }
}

Use "bedrock": true to turn the section on with the defaults, or false to hide it.

This needs boto3: it is in requirements.txt and in the macOS and Windows packages. On Linux, run sudo apt install python3-boto3 (or install it for the system Python another way). The IAM identity needs ce:GetCostAndUsage, cloudwatch:GetMetricData, and, for a budget, budgets:ViewBudget and sts:GetCallerIdentity. If a permission is missing, only that row shows an error. If the credentials have expired (for example an SSO session), the section says to run aws sso login.

Cost: Cost Explorer charges $0.01 per request and its data only updates a few times a day, so spend (and the budget) is fetched at most every cost_interval seconds (6 h by default, about $1.20 a month). Token counts are fetched every metrics_interval seconds (15 min). Both are cached in bedrock-cache.json next to config.json, so restarts don't refetch them, and Refresh now doesn't bypass the cache either. Billing data can lag by a day or more, so don't treat this as a spending alarm.

Write a fetch_<name>() that returns a ProviderUsage and add it to PROVIDERS.

MIT. See LICENSE.

── more in #ai-tools 4 stories · sorted by recency
── more on @llm usage widget 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-llm-usage-de…] indexed:0 read:10min 2026-10-18 · —