Native Omarchy Quattro panel, Waybar widget, and tabbed TUI for AI plan usage across Claude, Codex/ChatGPT, Z.AI (GLM), OpenRouter, DeepSeek, Kimi, Nous Research, OpenCode Go, and other supported AI coding services.
ai-usagebar began as a Rust port of
claudebar and remains drop-in
compatible. It keeps claudebar's Pango tooltip, Omarchy theme detection, and
flock-protected OAuth refresh while adding more providers and a testable Rust
codebase.


ai-usagebar-tui opens with a compact provider overview and refreshes every
60 seconds. Its navigation can use a sidebar, navbar, or no vendor box.[ui] primary controls the
initial provider in both the widget and TUI.--pretty, --watch N, and make smoke help with local testing and API
response changes.Run either application directly from GitHub:
nix run github:akitaonrails/ai-usagebar
nix run github:akitaonrails/ai-usagebar#tui
Install both ai-usagebar and ai-usagebar-tui into your user profile:
nix profile install github:akitaonrails/ai-usagebar
For a flake-based NixOS or Home Manager configuration, add the input in your
root flake.nix:
inputs.ai-usagebar.url = "github:akitaonrails/ai-usagebar";
Pass inputs to your NixOS modules with specialArgs:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; };
modules = [ ./configuration.nix ];
}
For standalone Home Manager, use extraSpecialArgs:
let
system = "x86_64-linux";
in
home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.${system};
extraSpecialArgs = { inherit inputs; };
modules = [ ./home.nix ];
}
If your configuration already passes inputs through these arguments, you do
not need to add it again. Then consume the package in a NixOS module:
{ inputs, pkgs, ... }:
{
environment.systemPackages = [
inputs.ai-usagebar.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
The equivalent Home Manager module is:
{ inputs, pkgs, ... }:
{
home.packages = [
inputs.ai-usagebar.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
Alternatively, apply the overlay when you want the package available as
pkgs.ai-usagebar:
{ inputs, pkgs, ... }:
{
nixpkgs.overlays = [ inputs.ai-usagebar.overlays.default ];
environment.systemPackages = [ pkgs.ai-usagebar ];
}
The native plugin is a display frontend and does not bundle the
ai-usagebar executable. Install the binary first, then add and enable the
plugin:
omarchy pkg aur add ai-usagebar-bin
omarchy plugin add https://github.com/akitaonrails/ai-usagebar.git --enable
Quattro enables its own omarchy.agents status widget by default. Disable it
if you want AI Usage to be the only agent status item in the bar:
omarchy plugin disable omarchy.agents
Once enabled, left-click the AI Usage widget to open the native Quattro
usage panel. From that panel, click the gear or press s to open the native
QML settings page. Right-click intentionally opens ai-usagebar-tui in a
terminal; it is not the settings shortcut. Middle-click or use the mouse
wheel to switch providers. In QML settings, turn off Show usage value in the
top bar for an icon-only widget; the panel and tooltip keep the full details.
Turn on Show provider name in the top bar to prefix the entry with the same
three-letter code Waybar's {vendor_short} prints, so a bar cycling several
providers says which one it is showing.
The source-built ai-usagebar AUR package can replace ai-usagebar-bin in
the first command.
Two packages. Pick one:
yay -S ai-usagebar-bin # prebuilt binary from GitHub Releases (fast, ~5s install)
yay -S ai-usagebar # compiles from source (~30-60s, hermetic)
The -bin variant downloads the same x86_64 ELF that CI built and tested. The source variant compiles locally with your toolchain. Both install identical binaries to /usr/bin/. If you already have one installed, switch with yay -S the other package; pacman handles the swap through conflicts/provides.
cargo install ai-usagebar # compile from source (needs rustup)
cargo binstall ai-usagebar # download prebuilt binary (needs cargo-binstall, no rustup)
cargo binstall fetches the same x86_64 / aarch64 Linux tarball the AUR -bin package uses. Both install ai-usagebar + ai-usagebar-tui to ~/.cargo/bin/.
cargo build --release
sudo make install # → /usr/local/bin
# or
make install PREFIX=$HOME/.local # → ~/.local/bin
The Waybar widget is Wayland-only and does not apply to Windows. The
ai-usagebar-tui binary, however, runs natively, and ai-usagebar --json
/ --pretty work too (handy for feeding a custom tray/widget). Build with a
standard Rust toolchain:
cargo build --release
# binaries land in target\release\ai-usagebar.exe and ai-usagebar-tui.exe
Credentials are read from the Windows user profile rather than $HOME:
%USERPROFILE%\.claude\.credentials.json (Anthropic) and
%USERPROFILE%\.codex\auth.json (OpenAI Codex). Run the official claude /
codex CLI once on Windows to populate them, exactly as on Linux/macOS.
API-key vendors work unchanged via environment variables or config.toml.
Claude and Codex reuse OAuth credentials from their official CLIs. Other
providers use API keys, an existing app login, or a local service. API keys can
come from environment variables or config.toml.
| Vendor | Method | Action required |
|---|---|---|
| Claude | OAuth from ~/.claude/.credentials.json or the macOS login Keychain | Run claude once. Tokens refresh automatically. |
| Anthropic API | Organization Admin key | Opt in with ANTHROPIC_ADMIN_KEY or [anthropic_api] api_key. Inference and Claude Code keys do not work. |
| Codex | OAuth, read from ~/.codex/auth.json | Run codex login once. Token auto-refreshes. |
| Z.AI | API key (ZAI_API_KEY env or [zai] api_key in config) | Set either. |
| OpenRouter | API key (OPENROUTER_API_KEY env or [openrouter] api_key in config) | Set either. Named keys are supported. |
| DeepSeek | API key (DEEPSEEK_API_KEY or config) | Set either and opt in. |
| Kimi | API key (KIMI_API_KEY or config) | Set either and opt in. |
| Kilo | API key (KILO_API_KEY env or [kilo] api_key in config) | Set either. Opt-in. For a team balance, also set [kilo] organization_id; omit it for the personal balance. |
| Novita | API key (NOVITA_API_KEY env or [novita] api_key in config) | Set either. Opt-in. |
| Moonshot | API key (MOONSHOT_API_KEY or config) | Opt in. Set region cn for CNY; global uses USD. |
| Grok (xAI) | Management key | Opt in with XAI_MANAGEMENT_KEY or config. An inference key does not work. |
| SuperGrok | Official Grok Build ACP extension | Opt in, install Grok Build, and run grok login. This reports subscription usage, not the Management API balance. |
| MiniMax | Token Plan subscription key | Opt in with MINIMAX_API_KEY or config. Choose the matching global or China region; pay-as-you-go keys do not work. |
| Google Antigravity | Local Antigravity server | Opt in and keep Antigravity or an interactive agy session running. |
| Cursor | Existing Cursor IDE or cursor-agent login | Opt in and sign in once. cursor-agent is the headless fallback. |
| Kiro CLI | Existing kiro-cli login | Opt in and run kiro-cli login once. ai-usagebar refreshes the session when needed. |
| Nous Research | OAuth device flow | Enable [nous], click Log in with Nous Research in the Omarchy settings panel, or run ai-usagebar auth nous login. Credentials are kept in ai-usagebar's separate platform config directory (~/.config/ai-usagebar/credentials.json on Linux). |
| OpenCode Go | API key (OPENCODE_GO_API_KEY env or [opencode-go] api_key in config) | Enable [opencode-go], then enter the key in the Omarchy settings panel or set the environment variable. |
Nous usage percentage is calculated from the subscription-credit pool only:
(monthly subscription credits - subscription credits remaining) / monthly subscription credits.
Top-up/purchased credits are not mixed into that percentage. When the Portal
reports them, the tooltip and TUI show subscription credits, top-up credits, and
total usable credits as separate values.
Nous login is interactive because the device code is authorized in the browser.
Leave the terminal open until it reports that login completed, then refresh the
Omarchy panel. The login never reads Hermes Agent credentials. On Unix, newly
created credential directories use mode 0700, and credential and lock files
use mode 0600; an existing current-user-owned config directory also works when
it is not group- or world-writable. Windows uses the user's platform config
directory and inherited per-user access controls.
OpenCode Go uses the official usage endpoint and the percent field. Its key can
be entered through the native Settings panel; stored values are sent to the Rust
settings command over stdin and are never placed in QML command arguments. Cache
entries are tied to the endpoint and a one-way key fingerprint, so changing
accounts cannot reuse another account's fresh or stale usage.
The balance lives at /v1/billing/teams/{team}/prepaid/balance, so a team has to
be identified. With a team-scoped management key the team is read
automatically from the key. An organization-scoped key cannot provide it
because that key's scopeId is an organization id rather than a team. Set the
team explicitly in that case:
[grok]
team_id = "your-team-id"
Without it, an organization-scoped key reports an error saying exactly this rather than silently querying the wrong URL.
enabled = true is what makes a vendor fetch. Anthropic API, DeepSeek, Kimi,
Kilo, Novita, Moonshot, Grok, SuperGrok, Antigravity, Cursor, MiniMax, and Kiro CLI all default to disabled so that existing
installs are unaffected until you opt in. Use either method:
s in the Omarchy panel, or run
ai-usagebar-tui and press s. Saving a non-empty API key sets that vendor's
enabled = true for you. Clearing it removes the inline key from
config.toml.enabled = true to the vendor's config section alongside the key.The primary-vendor selector only offers vendors that are currently enabled, so a vendor you haven't opted into cannot be set as primary.
For each API-key vendor, ai-usagebar checks in this order:
api_key_env.api_key in the same config section.~/.config/ai-usagebar/config.toml at mode 600.
Redact them before committing that file to dotfiles. Environment variables
remain the default and avoid storing keys in the config.state.vscdb and cursor-agent fallback auth.json are read-only.data.sqlite3 is read-only. Refreshed credentials go to an
account-scoped kiro/oauth.json file, mode 600 on Unix.Recent Claude Code builds store OAuth credentials in the macOS login Keychain
instead of ~/.claude/.credentials.json. No setup is needed: ai-usagebar uses
macOS's security tool to read and refresh the Claude Code-credentials item.
CLAUDE_CONFIG_DIR login gets its own
Claude Code-credentials-<hash> Keychain item.The optional config file is ~/.config/ai-usagebar/config.toml. Claude,
Codex, Z.AI, and OpenRouter are enabled by default; other providers are
opt-in.
A minimal example:
[ui]
primary = "openai"
[kimi]
enabled = true
# api_key = "..." # or set KIMI_API_KEY
See the configuration reference for every provider, display option, account path, region, and API-key setting.
# Local testing — auto-detects TTY and renders human-readable output.
ai-usagebar # uses [ui] primary (defaults to anthropic)
ai-usagebar --vendor anthropic_api
ai-usagebar --vendor openai
ai-usagebar --vendor zai
ai-usagebar --vendor openrouter
ai-usagebar --vendor deepseek
ai-usagebar --vendor kimi
ai-usagebar --vendor kiro
# Force Waybar JSON (e.g. piping into jq).
ai-usagebar --json
# Everything at once: quota + time-to-reset for every configured vendor,
# with one entry per named Claude account.
ai-usagebar usage
ai-usagebar usage --json | jq '.entries[] | {id, metrics, sections}'
# Live preview while iterating on --format / --tooltip-format.
ai-usagebar --vendor openrouter --watch 5
# Interactive TUI with tabs.
ai-usagebar-tui
The JSON report has two views of each provider:
metrics contains percentage gauges only.sections preserves the complete ordered display, including balances,
grouped rows, and spacers. Rows without a percentage do not invent one.The report also includes the configured primary id. Each entry has
display_name, short_name, status, stale, and fetched_at; metric rows
may add severity and an absolute reset_at. These fields are additive, so
existing consumers remain compatible. short_name is the same three-letter
code {vendor_short} prints, so a frontend that wants a compact provider tag
takes it from the report instead of keeping its own table.
The TUI does not depend on Waybar. Run it directly in a local terminal, over SSH, or in a tmux pane:
ai-usagebar-tui # opens in your current terminal
It works in Kitty, Alacritty, Foot, Ghostty, and other terminal emulators. The controls and Settings overlay are the same everywhere; no compositor or window manager integration is required.
Omarchy 4's Quattro shell can host ai-usagebar as a native Quickshell plugin. Follow the two-step Omarchy installation above; adding the plugin alone does not install its binary dependency.
Update or remove the plugin without editing shell.json by hand:
omarchy plugin update akitaonrails.ai-usagebar
omarchy plugin remove akitaonrails.ai-usagebar
The widget reads the providers and accounts already enabled in
~/.config/ai-usagebar/config.toml; it does not keep another copy of API keys.
s opens QML settings.{vendor_short} code before that
value (cld 29%). It is off by default and applies immediately.The Omarchy plugin guide covers keyboard controls, credential handling, updates, and development checks.
The plugin depends only on the ai-usagebar executable. It runs the fixed
ai-usagebar usage --json command for reports and starts ai-usagebar-tui
only after a right-click. It installs no service, asks for no elevated
privileges, and does not overwrite user configuration.
| Integration | Supported providers | Notes |
|---|---|---|
| macOS menu bar | Claude, Codex, Z.AI, OpenRouter, DeepSeek, Kimi, Kilo, Novita, Moonshot, Grok (xAI), Anthropic API, Cursor, Google Antigravity | Thirteen providers. |
| GNOME Shell | Claude, Codex, Z.AI, OpenRouter, DeepSeek, Google Antigravity | Antigravity's two quota pools appear as grouped rows. |
| KDE Plasma 6 | Whatever usage --json reports | Provider tabs in the popup; vendor is per applet instance. |
Cursor is not available in the GNOME extension yet. On GNOME, use
ai-usagebar --vendor cursor or open the TUI.
External projects built on ai-usagebar usage --json. They live in their own
repositories and are maintained by their authors, not here.
cosmic-applet-ai-usage — panel applet for the COSMIC desktop.
AI Usage for Noctalia
— bar widget and panel for the Noctalia v5 shell, installable from its
plugin browser as felipeartur/ai-usagebar.
Use one bar item and scroll through your vendors. The TUI on-click still shows them all:
"modules-right": ["custom/aibar", ...],
"custom/aibar": {
"exec": "ai-usagebar --format '{vendor_short} {session_pct}% · {session_reset}'",
"return-type": "json",
"interval": 300,
"signal": 13,
"tooltip": true,
"on-click": "ai-usagebar-tui",
"on-scroll-up": "ai-usagebar --cycle-next",
"on-scroll-down": "ai-usagebar --cycle-prev"
}
{vendor_short} identifies the active provider with a three-letter code. For a
format shared by every cycled provider, use {session_pct},
{session_reset}, {weekly_pct}, and {weekly_reset}. Cursor maps its two
usage pools to the session and weekly slots; Kiro maps its single pool to both.
The placeholder reference lists every generic
and provider-specific field.
signal: 13 lets the scroll commands refresh the bar through SIGRTMIN+13
instead of waiting for the next interval.
The KDE plasmoid has the same gesture in its own settings and never reads or writes the state file this section relies on.
If a tray expander follows custom/aibar, the usage text may sit too close to
its icon. Add right padding in Waybar CSS:
#custom-aibar {
padding-right: 18px;
}
If you'd rather see them all at once:
"modules-right": ["custom/claude", "custom/openai", "custom/openrouter", "custom/zai", "custom/deepseek", "custom/kimi"],
"custom/claude": {
"exec": "ai-usagebar --vendor anthropic --icon ''",
"return-type": "json",
"interval": 300,
"tooltip": true,
"on-click": "ai-usagebar-tui"
},
"custom/openai": {
"exec": "ai-usagebar --vendor openai --icon ''",
"return-type": "json",
"interval": 300,
"tooltip": true
},
"custom/openrouter": {
"exec": "ai-usagebar --vendor openrouter --icon '' --format '{or_balance} · {or_used_today}'",
"return-type": "json",
"interval": 600,
"tooltip": true
},
"custom/zai": {
"exec": "ai-usagebar --vendor zai --icon ''",
"return-type": "json",
"interval": 300,
"tooltip": true
},
"custom/deepseek": {
"exec": "ai-usagebar --vendor deepseek --icon ''",
"return-type": "json",
"interval": 600,
"tooltip": true
},
"custom/kimi": {
"exec": "ai-usagebar --vendor kimi --icon ''",
"return-type": "json",
"interval": 600,
"tooltip": true
}
Why 300s? The Anthropic and OpenAI Codex endpoints are undocumented and rate-limit aggressively below ~300s. The cache TTL is 60s so multi-monitor instances coexist, but Waybar's polling interval should stay at 300s.
Named accounts appear as separate TUI tabs and report entries. The recommended setup is:
ai-usagebar account add work
ai-usagebar --vendor anthropic --account work
On macOS, the same account command can also capture and switch the active Claude Desktop or CLI login. The dedicated Claude account guide covers:
Add one [[openrouter.accounts]] entry per key, then select it with
--vendor openrouter --account <label>. Named accounts appear separately in
the TUI, native integrations, and usage reports. Each has its own cache, so
one key's fresh data cannot be shown for another. See the
OpenRouter account guide for the config and
Waybar examples.
By default Hyprland tiles the TUI. To make ai-usagebar-tui open as a centered floating window, the same way Omarchy floats its own settings TUIs (Wi-Fi/impala, audio/wiremix, Bluetooth/bluetui), add this to ~/.config/hypr/hyprland.conf or any sourced .conf, such as looknfeel.conf:
# ai-usagebar TUI — float + center + fixed size. omarchy-launch-tui sets the
# app-id from the binary basename, so the class is org.omarchy.ai-usagebar-tui.
# 875x600 matches the size Omarchy gives its own `floating-window`-tagged TUIs.
windowrule = float on, match:class ^(org\.omarchy\.ai-usagebar-tui)$
windowrule = center on, match:class ^(org\.omarchy\.ai-usagebar-tui)$
windowrule = size 875 600, match:class ^(org\.omarchy\.ai-usagebar-tui)$
Then hyprctl reload (no logout needed).
Omarchy tags a hardcoded list of TUI app-ids with
floating-windowin~/.local/share/omarchy/default/hypr/apps/system.conf, which then appliesfloat + center + size 875 600. The rules above set those values directly, so the size is deterministic regardless of which config is sourced first. If you launch the TUI differently (e.g.kitty -e ai-usagebar-tui), replace the class regex with whateverhyprctl clientsreports for your terminal.
Hyprland 0.46+ uses the unified
windowrulekeyword withmatch:…filters. The olderwindowrulev2 = …, class:…syntax still works on legacy releases but is deprecated. Use the form above on current Omarchy and Hyprland.
The CLI and TUI support every provider in the authentication table above. Native desktop coverage varies by integration. The provider endpoint reference lists each endpoint, reported metric, desktop selector, stability note, and live-test command.
Run make smoke to check live response shapes.
Use placeholders in --format and --tooltip-format:
ai-usagebar --vendor anthropic --format '{session_pct}% · {session_reset}'
ai-usagebar --vendor openrouter --format '${or_balance} remaining'
Shared claudebar placeholders and every provider-specific field are listed in the format placeholder reference.
ai-usagebar --watch 5 # iterate on --format live
ai-usagebar --vendor openrouter --format '{or_balance} · today {or_used_today}'
make test # unit + integration
source ~/.config/zsh/secrets # required for existing vendor smoke tests
make smoke # runs all ignored tests; only Kimi skips without its key
make clippy # cargo clippy -D warnings

Tab / l / → — next tabShift+Tab / h / ← — previous tabr — refresh active tabR — refresh all tabss — open Settings overlay (primary vendor + API keys)c — open local Claude context sessions (only when [context] enabled = true); v cycles its layoutq / Esc / Ctrl-C — quitThe TUI refreshes every 60 seconds. During a refresh it keeps the current values
visible with a ↻ marker. If the request fails, the last snapshot remains on
screen and is marked stale.
OpenRouter uses the same layout for balance, usage by period, and account tier:

The optional context overlay answers a different local question from the
vendor tabs: how much input context was present in recent Claude Code sessions.
Enable it by hand, restart the TUI, and press c:
[context]
enabled = true
layout = "full" # full | split | bottom (`v` cycles)
# projects_path = "~/.claude/projects" # this is the default
# context_window_tokens = 200000 # optional fallback
# Exact model ids override the fallback when 200K and 1M sessions coexist.
[context.model_context_window_tokens]
"claude-opus-4-6" = 1000000
The default full layout replaces the dashboard body. Press v to cycle
through full, split, and bottom layouts.
↑/↓ or j/k selects a session.Enter opens its detail gauge.Esc returns and r rescans.The percentage follows
Claude Code's status-line definition:
input_tokens + cache_creation_input_tokens + cache_read_input_tokens. Without
a trustworthy model window size, the overlay shows tokens instead of guessing
a percentage. After compaction, it waits for the next assistant response before
calculating a new value.
The reader handles Claude Code's undocumented local JSONL defensively:
subagents sidechains;When the feature is disabled, nothing under ~/.claude/projects is read.
Context options remain in TOML rather than the Settings modal.

Press s while the TUI is open. The overlay lets you:
← / → to cycle.Ctrl-V to reveal or hide them. The provider's configured environment
variable still wins at runtime; the inline key is the fallback. Saving a
non-empty key also sets that provider's enabled = true.Key bindings inside the overlay:
Tab / ↑↓ — move between fields← / → — cycle primary-vendor selection (only on the vendor field)Ctrl-V — toggle key visibility on the focused key fieldCtrl-S — save and closeEsc — discard and closeSave updates ~/.config/ai-usagebar/config.toml through toml_edit, preserving
comments and unrelated settings. The file is set to mode 600.
Omarchy's native QML form uses the same Rust persistence path and semantics. It never loads stored key values into the long-lived shell process: blank means unchanged, clear is explicit, and new values are sent to the binary over stdin.
After saving:
signal: 13 refresh through SIGRTMIN+13.pkill -SIGUSR2 waybar to force a full reload.~/.config/omarchy/current/theme/colors.toml.--color-low, --color-mid, --color-high, --color-critical (claudebar-compatible).See CHANGELOG.md for the release history. Each release also has its own page at https://github.com/akitaonrails/ai-usagebar/releases with the auto-generated install snippet and checksum.
The Codex and Claude OAuth endpoint references came from
claudebar and
codexbar, both by mryll. The bordered
Pango tooltip, severity colors, and pacing math also come from those projects.
The Kimi /coding/v1/usages endpoint reference came from community quota tools: CodexBar (steipete), OpenUsage, and OmniRoute.
MIT.
Rust
81.9%
Swift
7.3%
JavaScript
5.7%
QML
4.3%
Native Omarchy Quattro panel, Waybar widget, and tabbed TUI for AI plan usage across Claude, Codex/ChatGPT, Z.AI (GLM), OpenRouter, DeepSeek, Kimi, Nous Research, OpenCode Go, and other supported AI coding services.
ai-usagebar began as a Rust port of
claudebar and remains drop-in
compatible. It keeps claudebar's Pango tooltip, Omarchy theme detection, and
flock-protected OAuth refresh while adding more providers and a testable Rust
codebase.


ai-usagebar-tui opens with a compact provider overview and refreshes every
60 seconds. Its navigation can use a sidebar, navbar, or no vendor box.[ui] primary controls the
initial provider in both the widget and TUI.--pretty, --watch N, and make smoke help with local testing and API
response changes.Run either application directly from GitHub:
nix run github:akitaonrails/ai-usagebar
nix run github:akitaonrails/ai-usagebar#tui
Install both ai-usagebar and ai-usagebar-tui into your user profile:
nix profile install github:akitaonrails/ai-usagebar
For a flake-based NixOS or Home Manager configuration, add the input in your
root flake.nix:
inputs.ai-usagebar.url = "github:akitaonrails/ai-usagebar";
Pass inputs to your NixOS modules with specialArgs:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; };
modules = [ ./configuration.nix ];
}
For standalone Home Manager, use extraSpecialArgs:
let
system = "x86_64-linux";
in
home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.${system};
extraSpecialArgs = { inherit inputs; };
modules = [ ./home.nix ];
}
If your configuration already passes inputs through these arguments, you do
not need to add it again. Then consume the package in a NixOS module:
{ inputs, pkgs, ... }:
{
environment.systemPackages = [
inputs.ai-usagebar.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
The equivalent Home Manager module is:
{ inputs, pkgs, ... }:
{
home.packages = [
inputs.ai-usagebar.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
Alternatively, apply the overlay when you want the package available as
pkgs.ai-usagebar:
{ inputs, pkgs, ... }:
{
nixpkgs.overlays = [ inputs.ai-usagebar.overlays.default ];
environment.systemPackages = [ pkgs.ai-usagebar ];
}
The native plugin is a display frontend and does not bundle the
ai-usagebar executable. Install the binary first, then add and enable the
plugin:
omarchy pkg aur add ai-usagebar-bin
omarchy plugin add https://github.com/akitaonrails/ai-usagebar.git --enable
Quattro enables its own omarchy.agents status widget by default. Disable it
if you want AI Usage to be the only agent status item in the bar:
omarchy plugin disable omarchy.agents
Once enabled, left-click the AI Usage widget to open the native Quattro
usage panel. From that panel, click the gear or press s to open the native
QML settings page. Right-click intentionally opens ai-usagebar-tui in a
terminal; it is not the settings shortcut. Middle-click or use the mouse
wheel to switch providers. In QML settings, turn off Show usage value in the
top bar for an icon-only widget; the panel and tooltip keep the full details.
Turn on Show provider name in the top bar to prefix the entry with the same
three-letter code Waybar's {vendor_short} prints, so a bar cycling several
providers says which one it is showing.
The source-built ai-usagebar AUR package can replace ai-usagebar-bin in
the first command.
Two packages. Pick one:
yay -S ai-usagebar-bin # prebuilt binary from GitHub Releases (fast, ~5s install)
yay -S ai-usagebar # compiles from source (~30-60s, hermetic)
The -bin variant downloads the same x86_64 ELF that CI built and tested. The source variant compiles locally with your toolchain. Both install identical binaries to /usr/bin/. If you already have one installed, switch with yay -S the other package; pacman handles the swap through conflicts/provides.
cargo install ai-usagebar # compile from source (needs rustup)
cargo binstall ai-usagebar # download prebuilt binary (needs cargo-binstall, no rustup)
cargo binstall fetches the same x86_64 / aarch64 Linux tarball the AUR -bin package uses. Both install ai-usagebar + ai-usagebar-tui to ~/.cargo/bin/.
cargo build --release
sudo make install # → /usr/local/bin
# or
make install PREFIX=$HOME/.local # → ~/.local/bin
The Waybar widget is Wayland-only and does not apply to Windows. The
ai-usagebar-tui binary, however, runs natively, and ai-usagebar --json
/ --pretty work too (handy for feeding a custom tray/widget). Build with a
standard Rust toolchain:
cargo build --release
# binaries land in target\release\ai-usagebar.exe and ai-usagebar-tui.exe
Credentials are read from the Windows user profile rather than $HOME:
%USERPROFILE%\.claude\.credentials.json (Anthropic) and
%USERPROFILE%\.codex\auth.json (OpenAI Codex). Run the official claude /
codex CLI once on Windows to populate them, exactly as on Linux/macOS.
API-key vendors work unchanged via environment variables or config.toml.
Claude and Codex reuse OAuth credentials from their official CLIs. Other
providers use API keys, an existing app login, or a local service. API keys can
come from environment variables or config.toml.
| Vendor | Method | Action required |
|---|---|---|
| Claude | OAuth from ~/.claude/.credentials.json or the macOS login Keychain | Run claude once. Tokens refresh automatically. |
| Anthropic API | Organization Admin key | Opt in with ANTHROPIC_ADMIN_KEY or [anthropic_api] api_key. Inference and Claude Code keys do not work. |
| Codex | OAuth, read from ~/.codex/auth.json | Run codex login once. Token auto-refreshes. |
| Z.AI | API key (ZAI_API_KEY env or [zai] api_key in config) | Set either. |
| OpenRouter | API key (OPENROUTER_API_KEY env or [openrouter] api_key in config) | Set either. Named keys are supported. |
| DeepSeek | API key (DEEPSEEK_API_KEY or config) | Set either and opt in. |
| Kimi | API key (KIMI_API_KEY or config) | Set either and opt in. |
| Kilo | API key (KILO_API_KEY env or [kilo] api_key in config) | Set either. Opt-in. For a team balance, also set [kilo] organization_id; omit it for the personal balance. |
| Novita | API key (NOVITA_API_KEY env or [novita] api_key in config) | Set either. Opt-in. |
| Moonshot | API key (MOONSHOT_API_KEY or config) | Opt in. Set region cn for CNY; global uses USD. |
| Grok (xAI) | Management key | Opt in with XAI_MANAGEMENT_KEY or config. An inference key does not work. |
| SuperGrok | Official Grok Build ACP extension | Opt in, install Grok Build, and run grok login. This reports subscription usage, not the Management API balance. |
| MiniMax | Token Plan subscription key | Opt in with MINIMAX_API_KEY or config. Choose the matching global or China region; pay-as-you-go keys do not work. |
| Google Antigravity | Local Antigravity server | Opt in and keep Antigravity or an interactive agy session running. |
| Cursor | Existing Cursor IDE or cursor-agent login | Opt in and sign in once. cursor-agent is the headless fallback. |
| Kiro CLI | Existing kiro-cli login | Opt in and run kiro-cli login once. ai-usagebar refreshes the session when needed. |
| Nous Research | OAuth device flow | Enable [nous], click Log in with Nous Research in the Omarchy settings panel, or run ai-usagebar auth nous login. Credentials are kept in ai-usagebar's separate platform config directory (~/.config/ai-usagebar/credentials.json on Linux). |
| OpenCode Go | API key (OPENCODE_GO_API_KEY env or [opencode-go] api_key in config) | Enable [opencode-go], then enter the key in the Omarchy settings panel or set the environment variable. |
Nous usage percentage is calculated from the subscription-credit pool only:
(monthly subscription credits - subscription credits remaining) / monthly subscription credits.
Top-up/purchased credits are not mixed into that percentage. When the Portal
reports them, the tooltip and TUI show subscription credits, top-up credits, and
total usable credits as separate values.
Nous login is interactive because the device code is authorized in the browser.
Leave the terminal open until it reports that login completed, then refresh the
Omarchy panel. The login never reads Hermes Agent credentials. On Unix, newly
created credential directories use mode 0700, and credential and lock files
use mode 0600; an existing current-user-owned config directory also works when
it is not group- or world-writable. Windows uses the user's platform config
directory and inherited per-user access controls.
OpenCode Go uses the official usage endpoint and the percent field. Its key can
be entered through the native Settings panel; stored values are sent to the Rust
settings command over stdin and are never placed in QML command arguments. Cache
entries are tied to the endpoint and a one-way key fingerprint, so changing
accounts cannot reuse another account's fresh or stale usage.
The balance lives at /v1/billing/teams/{team}/prepaid/balance, so a team has to
be identified. With a team-scoped management key the team is read
automatically from the key. An organization-scoped key cannot provide it
because that key's scopeId is an organization id rather than a team. Set the
team explicitly in that case:
[grok]
team_id = "your-team-id"
Without it, an organization-scoped key reports an error saying exactly this rather than silently querying the wrong URL.
enabled = true is what makes a vendor fetch. Anthropic API, DeepSeek, Kimi,
Kilo, Novita, Moonshot, Grok, SuperGrok, Antigravity, Cursor, MiniMax, and Kiro CLI all default to disabled so that existing
installs are unaffected until you opt in. Use either method:
s in the Omarchy panel, or run
ai-usagebar-tui and press s. Saving a non-empty API key sets that vendor's
enabled = true for you. Clearing it removes the inline key from
config.toml.enabled = true to the vendor's config section alongside the key.The primary-vendor selector only offers vendors that are currently enabled, so a vendor you haven't opted into cannot be set as primary.
For each API-key vendor, ai-usagebar checks in this order:
api_key_env.api_key in the same config section.~/.config/ai-usagebar/config.toml at mode 600.
Redact them before committing that file to dotfiles. Environment variables
remain the default and avoid storing keys in the config.state.vscdb and cursor-agent fallback auth.json are read-only.data.sqlite3 is read-only. Refreshed credentials go to an
account-scoped kiro/oauth.json file, mode 600 on Unix.Recent Claude Code builds store OAuth credentials in the macOS login Keychain
instead of ~/.claude/.credentials.json. No setup is needed: ai-usagebar uses
macOS's security tool to read and refresh the Claude Code-credentials item.
CLAUDE_CONFIG_DIR login gets its own
Claude Code-credentials-<hash> Keychain item.The optional config file is ~/.config/ai-usagebar/config.toml. Claude,
Codex, Z.AI, and OpenRouter are enabled by default; other providers are
opt-in.
A minimal example:
[ui]
primary = "openai"
[kimi]
enabled = true
# api_key = "..." # or set KIMI_API_KEY
See the configuration reference for every provider, display option, account path, region, and API-key setting.
# Local testing — auto-detects TTY and renders human-readable output.
ai-usagebar # uses [ui] primary (defaults to anthropic)
ai-usagebar --vendor anthropic_api
ai-usagebar --vendor openai
ai-usagebar --vendor zai
ai-usagebar --vendor openrouter
ai-usagebar --vendor deepseek
ai-usagebar --vendor kimi
ai-usagebar --vendor kiro
# Force Waybar JSON (e.g. piping into jq).
ai-usagebar --json
# Everything at once: quota + time-to-reset for every configured vendor,
# with one entry per named Claude account.
ai-usagebar usage
ai-usagebar usage --json | jq '.entries[] | {id, metrics, sections}'
# Live preview while iterating on --format / --tooltip-format.
ai-usagebar --vendor openrouter --watch 5
# Interactive TUI with tabs.
ai-usagebar-tui
The JSON report has two views of each provider:
metrics contains percentage gauges only.sections preserves the complete ordered display, including balances,
grouped rows, and spacers. Rows without a percentage do not invent one.The report also includes the configured primary id. Each entry has
display_name, short_name, status, stale, and fetched_at; metric rows
may add severity and an absolute reset_at. These fields are additive, so
existing consumers remain compatible. short_name is the same three-letter
code {vendor_short} prints, so a frontend that wants a compact provider tag
takes it from the report instead of keeping its own table.
The TUI does not depend on Waybar. Run it directly in a local terminal, over SSH, or in a tmux pane:
ai-usagebar-tui # opens in your current terminal
It works in Kitty, Alacritty, Foot, Ghostty, and other terminal emulators. The controls and Settings overlay are the same everywhere; no compositor or window manager integration is required.
Omarchy 4's Quattro shell can host ai-usagebar as a native Quickshell plugin. Follow the two-step Omarchy installation above; adding the plugin alone does not install its binary dependency.
Update or remove the plugin without editing shell.json by hand:
omarchy plugin update akitaonrails.ai-usagebar
omarchy plugin remove akitaonrails.ai-usagebar
The widget reads the providers and accounts already enabled in
~/.config/ai-usagebar/config.toml; it does not keep another copy of API keys.
s opens QML settings.{vendor_short} code before that
value (cld 29%). It is off by default and applies immediately.The Omarchy plugin guide covers keyboard controls, credential handling, updates, and development checks.
The plugin depends only on the ai-usagebar executable. It runs the fixed
ai-usagebar usage --json command for reports and starts ai-usagebar-tui
only after a right-click. It installs no service, asks for no elevated
privileges, and does not overwrite user configuration.
| Integration | Supported providers | Notes |
|---|---|---|
| macOS menu bar | Claude, Codex, Z.AI, OpenRouter, DeepSeek, Kimi, Kilo, Novita, Moonshot, Grok (xAI), Anthropic API, Cursor, Google Antigravity | Thirteen providers. |
| GNOME Shell | Claude, Codex, Z.AI, OpenRouter, DeepSeek, Google Antigravity | Antigravity's two quota pools appear as grouped rows. |
| KDE Plasma 6 | Whatever usage --json reports | Provider tabs in the popup; vendor is per applet instance. |
Cursor is not available in the GNOME extension yet. On GNOME, use
ai-usagebar --vendor cursor or open the TUI.
External projects built on ai-usagebar usage --json. They live in their own
repositories and are maintained by their authors, not here.
cosmic-applet-ai-usage — panel applet for the COSMIC desktop.
AI Usage for Noctalia
— bar widget and panel for the Noctalia v5 shell, installable from its
plugin browser as felipeartur/ai-usagebar.
Use one bar item and scroll through your vendors. The TUI on-click still shows them all:
"modules-right": ["custom/aibar", ...],
"custom/aibar": {
"exec": "ai-usagebar --format '{vendor_short} {session_pct}% · {session_reset}'",
"return-type": "json",
"interval": 300,
"signal": 13,
"tooltip": true,
"on-click": "ai-usagebar-tui",
"on-scroll-up": "ai-usagebar --cycle-next",
"on-scroll-down": "ai-usagebar --cycle-prev"
}
{vendor_short} identifies the active provider with a three-letter code. For a
format shared by every cycled provider, use {session_pct},
{session_reset}, {weekly_pct}, and {weekly_reset}. Cursor maps its two
usage pools to the session and weekly slots; Kiro maps its single pool to both.
The placeholder reference lists every generic
and provider-specific field.
signal: 13 lets the scroll commands refresh the bar through SIGRTMIN+13
instead of waiting for the next interval.
The KDE plasmoid has the same gesture in its own settings and never reads or writes the state file this section relies on.
If a tray expander follows custom/aibar, the usage text may sit too close to
its icon. Add right padding in Waybar CSS:
#custom-aibar {
padding-right: 18px;
}
If you'd rather see them all at once:
"modules-right": ["custom/claude", "custom/openai", "custom/openrouter", "custom/zai", "custom/deepseek", "custom/kimi"],
"custom/claude": {
"exec": "ai-usagebar --vendor anthropic --icon ''",
"return-type": "json",
"interval": 300,
"tooltip": true,
"on-click": "ai-usagebar-tui"
},
"custom/openai": {
"exec": "ai-usagebar --vendor openai --icon ''",
"return-type": "json",
"interval": 300,
"tooltip": true
},
"custom/openrouter": {
"exec": "ai-usagebar --vendor openrouter --icon '' --format '{or_balance} · {or_used_today}'",
"return-type": "json",
"interval": 600,
"tooltip": true
},
"custom/zai": {
"exec": "ai-usagebar --vendor zai --icon ''",
"return-type": "json",
"interval": 300,
"tooltip": true
},
"custom/deepseek": {
"exec": "ai-usagebar --vendor deepseek --icon ''",
"return-type": "json",
"interval": 600,
"tooltip": true
},
"custom/kimi": {
"exec": "ai-usagebar --vendor kimi --icon ''",
"return-type": "json",
"interval": 600,
"tooltip": true
}
Why 300s? The Anthropic and OpenAI Codex endpoints are undocumented and rate-limit aggressively below ~300s. The cache TTL is 60s so multi-monitor instances coexist, but Waybar's polling interval should stay at 300s.
Named accounts appear as separate TUI tabs and report entries. The recommended setup is:
ai-usagebar account add work
ai-usagebar --vendor anthropic --account work
On macOS, the same account command can also capture and switch the active Claude Desktop or CLI login. The dedicated Claude account guide covers:
Add one [[openrouter.accounts]] entry per key, then select it with
--vendor openrouter --account <label>. Named accounts appear separately in
the TUI, native integrations, and usage reports. Each has its own cache, so
one key's fresh data cannot be shown for another. See the
OpenRouter account guide for the config and
Waybar examples.
By default Hyprland tiles the TUI. To make ai-usagebar-tui open as a centered floating window, the same way Omarchy floats its own settings TUIs (Wi-Fi/impala, audio/wiremix, Bluetooth/bluetui), add this to ~/.config/hypr/hyprland.conf or any sourced .conf, such as looknfeel.conf:
# ai-usagebar TUI — float + center + fixed size. omarchy-launch-tui sets the
# app-id from the binary basename, so the class is org.omarchy.ai-usagebar-tui.
# 875x600 matches the size Omarchy gives its own `floating-window`-tagged TUIs.
windowrule = float on, match:class ^(org\.omarchy\.ai-usagebar-tui)$
windowrule = center on, match:class ^(org\.omarchy\.ai-usagebar-tui)$
windowrule = size 875 600, match:class ^(org\.omarchy\.ai-usagebar-tui)$
Then hyprctl reload (no logout needed).
Omarchy tags a hardcoded list of TUI app-ids with
floating-windowin~/.local/share/omarchy/default/hypr/apps/system.conf, which then appliesfloat + center + size 875 600. The rules above set those values directly, so the size is deterministic regardless of which config is sourced first. If you launch the TUI differently (e.g.kitty -e ai-usagebar-tui), replace the class regex with whateverhyprctl clientsreports for your terminal.
Hyprland 0.46+ uses the unified
windowrulekeyword withmatch:…filters. The olderwindowrulev2 = …, class:…syntax still works on legacy releases but is deprecated. Use the form above on current Omarchy and Hyprland.
The CLI and TUI support every provider in the authentication table above. Native desktop coverage varies by integration. The provider endpoint reference lists each endpoint, reported metric, desktop selector, stability note, and live-test command.
Run make smoke to check live response shapes.
Use placeholders in --format and --tooltip-format:
ai-usagebar --vendor anthropic --format '{session_pct}% · {session_reset}'
ai-usagebar --vendor openrouter --format '${or_balance} remaining'
Shared claudebar placeholders and every provider-specific field are listed in the format placeholder reference.
ai-usagebar --watch 5 # iterate on --format live
ai-usagebar --vendor openrouter --format '{or_balance} · today {or_used_today}'
make test # unit + integration
source ~/.config/zsh/secrets # required for existing vendor smoke tests
make smoke # runs all ignored tests; only Kimi skips without its key
make clippy # cargo clippy -D warnings

Tab / l / → — next tabShift+Tab / h / ← — previous tabr — refresh active tabR — refresh all tabss — open Settings overlay (primary vendor + API keys)c — open local Claude context sessions (only when [context] enabled = true); v cycles its layoutq / Esc / Ctrl-C — quitThe TUI refreshes every 60 seconds. During a refresh it keeps the current values
visible with a ↻ marker. If the request fails, the last snapshot remains on
screen and is marked stale.
OpenRouter uses the same layout for balance, usage by period, and account tier:

The optional context overlay answers a different local question from the
vendor tabs: how much input context was present in recent Claude Code sessions.
Enable it by hand, restart the TUI, and press c:
[context]
enabled = true
layout = "full" # full | split | bottom (`v` cycles)
# projects_path = "~/.claude/projects" # this is the default
# context_window_tokens = 200000 # optional fallback
# Exact model ids override the fallback when 200K and 1M sessions coexist.
[context.model_context_window_tokens]
"claude-opus-4-6" = 1000000
The default full layout replaces the dashboard body. Press v to cycle
through full, split, and bottom layouts.
↑/↓ or j/k selects a session.Enter opens its detail gauge.Esc returns and r rescans.The percentage follows
Claude Code's status-line definition:
input_tokens + cache_creation_input_tokens + cache_read_input_tokens. Without
a trustworthy model window size, the overlay shows tokens instead of guessing
a percentage. After compaction, it waits for the next assistant response before
calculating a new value.
The reader handles Claude Code's undocumented local JSONL defensively:
subagents sidechains;When the feature is disabled, nothing under ~/.claude/projects is read.
Context options remain in TOML rather than the Settings modal.

Press s while the TUI is open. The overlay lets you:
← / → to cycle.Ctrl-V to reveal or hide them. The provider's configured environment
variable still wins at runtime; the inline key is the fallback. Saving a
non-empty key also sets that provider's enabled = true.Key bindings inside the overlay:
Tab / ↑↓ — move between fields← / → — cycle primary-vendor selection (only on the vendor field)Ctrl-V — toggle key visibility on the focused key fieldCtrl-S — save and closeEsc — discard and closeSave updates ~/.config/ai-usagebar/config.toml through toml_edit, preserving
comments and unrelated settings. The file is set to mode 600.
Omarchy's native QML form uses the same Rust persistence path and semantics. It never loads stored key values into the long-lived shell process: blank means unchanged, clear is explicit, and new values are sent to the binary over stdin.
After saving:
signal: 13 refresh through SIGRTMIN+13.pkill -SIGUSR2 waybar to force a full reload.~/.config/omarchy/current/theme/colors.toml.--color-low, --color-mid, --color-high, --color-critical (claudebar-compatible).See CHANGELOG.md for the release history. Each release also has its own page at https://github.com/akitaonrails/ai-usagebar/releases with the auto-generated install snippet and checksum.
The Codex and Claude OAuth endpoint references came from
claudebar and
codexbar, both by mryll. The bordered
Pango tooltip, severity colors, and pacing math also come from those projects.
The Kimi /coding/v1/usages endpoint reference came from community quota tools: CodexBar (steipete), OpenUsage, and OmniRoute.
MIT.
Rust
81.9%
Swift
7.3%
JavaScript
5.7%
QML
4.3%