A KDE Plasma 6 panel widget for tracking AI API quota usage across 18 provider services. Monitor subscription windows, account balances, local activity, and per-model usage through the shared backend, with animated segmented bars, live countdown timers, and account status.
| Claude | Antigravity |
|---|---|
| Claude | Antigravity |
|---|---|
| OpenAI | Usage history |
| Overview | Sessions |
| Usage & Spend | Settings |
- Multi-service support β 18 providers in one popup, each on its own tab
- Panel view β Compact percentage readouts in the taskbar, color-coded by usage level, with an inline spark-line trend
- Popup view β Segmented bars showing exact fill level with reset times and live countdowns that show "resetting..." when a window flips
- Usage chart β Smooth, glowing area chart of historical usage with availability-aware 5H / 24H / 7D choices and hover-scrub
- Burn-rate ETA β Estimates time to 100% from your recent trend (e.g. "β ~3h to 100%") for each available window
- Period comparison β Shows how today/this week compares to the same point last period (e.g. "+12% vs last week")
- Cost aggregation β Combined API spend across Claude, OpenAI, and OpenRouter in the footer
- Model breakdown β Usage per model for providers that expose it
- Theme-aware accent β Follows your Plasma accent color by default, or use per-service brand colors
- Glassmorphism popup β Translucent, blurred popup styling, with percentages that roll up and down smoothly
- Color thresholds β Amber at 70%, red at 90%
- Pin services β Pin one or more tabs so they stay visible on the panel; with no pins, the panel mirrors the active tab
- Optional Plasma panel rotation β Choose Off, 30 seconds, 1 minute, 2 minutes, 5 minutes, or 10 minutes in Appearance to show pinned providers one at a time in pin order; disabled by default
- History export / import β Save and restore usage history as JSON; history is mirrored to disk so it survives reinstalls
- Robust refresh β Poll interval from 1 to 30 minutes, respects
retry-afterheaders, dims and shows the error inline when a fetch fails - Optional Overview / Usage & Spend / Sessions tabs, turn on in Settings β Views. Overview shows every enabled provider at a glance, Usage & Spend shows provider-reported spend and non-navigable local source rows, and Sessions lists recent local Claude Code / Codex / Grok CLI / Cline / OpenCode / MiMo Code / Antigravity / Muse activity, local title previews and recency; previews may contain sensitive text, with a β§ button to resume a session in your terminal (
get-ai-usage --sessions/--open-session <key>; not available for Muse, which ships no resume command)
Sessions may include structured costUSD and costStatus fields. The status is
exact, partial, or unavailable. Token-derived costs are exact only when
the model matches the cached pricing catalog. Finite USD costs reported by a
provider can be exact. A mix of known and unknown models is partial. Unknown,
missing, or invalid model usage is unpriced and never estimated.
The optional costProvenance field says where a numeric session cost came from:
actual is a finite provider-reported USD amount, estimated is calculated
from exact local token usage and an exact cached model rate, and mixed contains
both kinds. A mixed row also carries finite non-negative
costBreakdown.actualUSD and costBreakdown.estimatedUSD values whose sum
matches costUSD; it is not a bill. Provenance is independent of coverage:
partial means some usage could not be priced, while unavailable means there
is no trustworthy numeric result.
Token estimates use exact OpenCode provider/model IDs and USD-per-million-token rates from models.dev first, with LiteLLM fallback for Anthropic and OpenAI. The shared catalog is cached for seven days; missing or unknown exact rates stay unavailable rather than being inferred.
Current local cost coverage includes Claude, Codex/OpenAI, Cline, and OpenCode
when explicit structured local usage is available. Cline's aggregate provider
totalCost remains provider-owned and is not surfaced as a per-session or local
actual; local Cline costs are estimates only when trustworthy per-session model
and token fields exist. OpenCode reads read-only structured assistant usage
across every provider it routed, aggregated per provider and model, and rolls
multi-provider sessions up per upstream provider; metadata-only sessions remain
unavailable.
Antigravity remains metadata-only and unavailable for cost because its verified
local schema has no structured billing data. Other providers are not implied to
have local session cost support.
Usage & Spend keeps provider-reported spend separate from non-navigable local source rows. Local actual and estimated rollups are merged by source, so an OpenCode row remains OpenCode; its secondary text identifies whether the amount is actual, estimated, or mixed and whether coverage is exact or partial. Local rows are never included in provider/API totals or presented as invoices. Session resume is a separate Sessions action that uses an opaque handle.
The local aggregate contains only totals and provider rollups. It emits no prompts, transcripts, paths, or raw session IDs. Local session costs therefore depend on the data and exact cached model pricing available on the machine. For the full contract and provider details, see docs/provider-contract.md and docs/providers.md.
Session search is handled by the backend with get-ai-usage --sessions --query <text>. Empty, whitespace-only, and non-empty searches all return 60-session pages with exact totals and offer Load more when additional sessions exist. In the desktop sessions views, refresh shows the current cached page immediately while providers are scanned in the background, then shows the updated page once the scan finishes. The Sessions view offers a cache-backed source filter beside the search field. It uses --source <id[,id...]> or --source=<id[,id...]>; omitting it means All, and multiple sources are combined with OR semantics. The filter is view-local, resets pagination when changed, and is preserved by refresh and Load more. All appears only when more than one cached source is available.
The backend returns the additive sources descriptor list with verified IDs and labels, in canonical order: Cline (cline), Muse (muse), Codex (openai), Grok (grok), Claude Code (claude), OpenCode (opencode), MiMo Code (mimo), and Antigravity (antigravity). Only sources with cached parsed rows appear. Query-only searches read that cache and do not scan local stores. Non-empty searches check all underlying session records using only provider, title, sessionName, state, and detail; fullTitle, opaque resume keys, IDs, paths, and transcripts are not searchable or exposed. Claude titles are clipped opening-prompt previews; raw prompt text never leaves the backend. See the provider contract for response, refresh, incomplete-cache, privacy, and cross-platform details.
Also runs on Hyprland, on Windows, on macOS and in a terminal β every frontend shares one backend.
Captured with demo data. See the macOS guide for usage history, settings, menu bar styles, and build instructions.
| Service | What the widget shows | Support status |
|---|---|---|
| Claude (Anthropic) | Subscription windows reported by Anthropic, reset times, and local activity stats | Supported |
| Antigravity / Google AI Studio | Overall quota, per-model Gemini usage, and reset times | Supported |
| OpenAI | 30-day API token/cost usage plus Codex/ChatGPT plan limits and account status | Supported |
| Grok (xAI) | CLI billing credits when exposed, free-tier exhaustion, and local session totals | Free tier tested; paid plans unverified |
| Kiro | Monthly credits, remaining balance, reset date, overage, and plan β from kiro-cli's login or the Kiro IDE | Supported |
| Mistral AI | Key status, available models, and local vibe CLI cost/token statistics | Supported |
| OpenRouter | Spend, credit limit, usage percentage, and account label | Untested |
| Local Models | Telemetry from configured Ollama, vLLM, or llama.cpp servers without generation requests | Supported |
| Z.AI | 5-hour token quota, monthly tools quota, reset countdowns, model details, and today's token consumption | Supported |
| Ollama Cloud | Account usage limits and recent activity cost via API key or OpenCode login | Supported |
| GitHub Copilot | Premium request usage against the plan's own entitlement, the real reset day, and local Copilot CLI activity stats | Personal billing supported; organization/enterprise billing not yet supported |
| DeepSeek | Available balance with granted and topped-up breakdown | Supported |
| Kimi / Moonshot AI | Kimi Code plan windows (5-hour and weekly) and extra-usage wallet; Moonshot API balance with voucher and cash breakdown | Moonshot balance supported; Kimi Code quota tested on a used-up plan only |
| Muse | Local session stats: tokens, offline spend estimate, sessions, tool calls, workspaces, streaks. Plan windows available behind an opt-in switch | Supported (the plan quota costs tokens to read β off by default) |
| Cursor | Included usage for the billing cycle, the Auto/API split, on-demand spend, and plan name | Free login/stats tested; free agent quota unavailable; paid plans unverified |
| Cline | Tokens, sessions and spend for today / 7 / 30 days, plus all-time stats per model and workspace, from the CLI's own session logs | Supported (local stats; account balance not yet shown) |
| MiMo Code | Local tokens, model breakdowns, session history and recorded or estimated costs | Local database verified; live subscription quota unavailable |
What each provider needs signed in, and what it reads, is in docs/providers.md.
Provider startup is zero based. On first start the widget enables the providers whose tools are installed (a CLI or desktop app β old logs don't count), while seven providers remain manual-only. Settings β Providers β Detect installed providers re-syncs later: it turns on newly installed tools and turns off uninstalled ones unless you gave them an API key. Several Plasma widgets (other panels or screens) share their settings; each keeps its own pins. The complete policy, platform paths, and future-provider checklist are in docs/provider-detection.md.
MiMo Code is detected through the mimo executable. Enable MiMo Code in
provider settings to show local token usage, model breakdowns and recorded or
estimated costs. Its sessions can also be reopened from the Sessions tab.
The reader uses $XDG_DATA_HOME/mimocode/mimocode*.db (normally
~/.local/share/mimocode/mimocode.db); MIMO_DB overrides the database path.
It reads SQLite without starting the CLI or requiring an active subscription.
Subscription limits and remaining account quota are not available.
| Dependency | Notes |
|---|---|
| KDE Plasma 6.0+ | X-Plasma-API-Minimum-Version: 6.0. Needed for the widget only β the Hyprland shell and the terminal frontend run without it |
plasma5support |
Provides the executable DataEngine for running the backend |
| Python 3.8+ | Runs the shared provider backend (standard library only, no pip install). Auto-detected from PATH as python3, a versioned python3.x, or bare python. To pin a specific interpreter β a virtualenv, a non-standard prefix β set it under Settings β Advanced β Python, or export $PYTHON3. NixOS installs need no PATH entry at all: the flake pins the interpreter at build time |
git clone https://github.com/Muddyblack/ai-usage-widget.git
cd ai-usage-widget
./translate/build.sh # compile the translations (needs gettext); skip for English only
kpackagetool6 -t Plasma/Applet -i package
# or to update an existing install:
kpackagetool6 -t Plasma/Applet -u packageThen right-click your panel β Add Widgets β search "AI Usage".
A release .plasmoid or the KDE Store version already has the translations
built in. Installing from a clone like this compiles them with gettext; the
full list of tools for working on the source is in
CONTRIBUTING.md.
To remove:
kpackagetool6 -t Plasma/Applet -r org.muddyblack.aiUsageWidgetOr install it from the KDE Store.
NixOS (flake)
# flake.nix
{
inputs.ai-usage.url = "github:Muddyblack/ai-usage-widget";
outputs = { self, nixpkgs, ai-usage, ... }: {
nixosConfigurations.mybox = nixpkgs.lib.nixosSystem {
modules = [
({ pkgs, ... }: {
environment.systemPackages = [
ai-usage.packages.${pkgs.system}.default
];
})
];
};
};
}All configuration is done in the widget's settings panel (right-click the widget β Configure).
| docs/providers.md | What each provider tab reads, credential resolution, API quirks, usage history |
| docs/cli.md | ai-usage-cli β the terminal frontend, for SSH, status bars and non-Plasma desktops |
| docs/hyprland.md | Running the Quickshell panel on Hyprland, Caelestia or Waybar |
| docs/windows.md | The Windows tray app: installing, using and building it |
| docs/macos.md | The macOS menu bar app: why it is native Swift, where each provider's data is on a Mac, and how to build it |
| docs/provider-contract.md | The JSON model every frontend reads, and the backend architecture behind it |
| docs/provider-detection.md | Zero-default detection policy, platform settings, privacy limits, and provider addition checklist |
| CONTRIBUTING.md | Development install, tests, packaging, releasing |
Credentials entered in widget settings are stored locally in the desktop's
widget/config file and are sent only to the corresponding provider endpoints.
Automatically discovered credentials remain in their original local files. Tokens
never leave the backend: the JSON model handed to either frontend carries
presence flags (hasApiKey, keyValid, β¦) but no credential, and a contract
test enforces that. Usage history (timestamps plus usage values) is written
locally to ~/.local/share/ai-usage-widget/.

