Skip to content

v1.14.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 21:12
· 57 commits to main since this release

What's changed

Added

  • Local provider detection. detect::has_local_credentials is a cheap,
    local-only probe per vendor (credential files, sqlite stores, saved API keys,
    env vars, Antigravity's local ports; never the network) that parses the
    credential the way the fetch would, so an empty or unreadable file does not
    count. detect::run_once writes enabled = true into config.toml for the
    vendors that have one and are still off — so Cursor, Kiro, Grok, Copilot and
    friends show up without editing the config by hand. Detection only ever
    enables, and never overrules an explicit enabled = false — that is the
    user's answer, it lives in the config file, and not even --all rewrites it.
    detect.json in the cache dir remembers which vendors were already checked so
    repeat runs probe nothing; because it is a cache file and may be deleted, it
    is a shortcut, not the thing protecting a decision.
    config::enable_vendors_in and VendorId::config_section are the shared
    toml_edit write path the TUI Settings overlay now reuses, with a guard test
    that every section name parses to its own vendor's enabled switch.

  • ai-usagebar detect [--all] [--json] runs that local provider detection
    from the command line, for the user or for any frontend that reads
    usage --json and wants a first run to show the tools that are actually
    installed. --all re-checks vendors already seen; --json prints
    {"enabled": [...], "known": [...], "probed": n} with vendor slugs and no
    paths or secrets.

  • usage --json metrics carry window_secs, the exact length of the reset
    window, for the vendors that state it (Anthropic, Codex, Z.AI, Antigravity,
    MiniMax, Kimi, SuperGrok weekly, and Cursor when the API sends both
    billingCycleStart and billingCycleEnd); absent otherwise — an unstated
    window omits the field rather than guessing — so a frontend that reads the
    report can pace a metric without a per-vendor window table of its own.

  • Custom providers. [[custom]] tables in config.toml declare a
    provider from a JSON endpoint and a static token: url, api_key_env /
    api_key, optional auth header/scheme and extra headers, a literal or
    pointed plan, and [[custom.metrics]] / [[custom.texts]] mapped with
    RFC 6901 JSON Pointers (used + limit or percent, resets_at as RFC
    3339 or epoch seconds/milliseconds, window_secs). Each gets a TUI tab and
    a usage --json entry (custom:<id>) with the same cache, severity and
    reset metadata as a built-in vendor, so every frontend that reads
    usage --json shows it. The cache stores the projected snapshot, not the
    response body. Validation rejects duplicate ids and short names, non-https
    URLs (unless allow_http), bad pointers and header names; the token's env
    var is scrubbed from child processes. Not covered: OAuth, the Waybar
    --vendor list, the TUI Settings overlay, [ui] primary and the vendors
    catalog.

  • Antigravity with the app closed. When no Antigravity product answers
    locally, the vendor reads the Google OAuth session Antigravity saved in the
    OS keyring (Windows Credential Manager gemini:antigravity, macOS
    Keychain, secret-tool on Linux), refreshes it through Google when it
    expired (cached in antigravity/oauth.json, never written back to the
    keyring) and asks the Cloud Code API for the same quota summary the local
    RPC serves, plus the plan from loadCodeAssist. The TUI panel and every
    frontend that reads usage --json carry a "Source · Google API (app
    closed)" row on that path; the "no local server found" error only remains
    when there is no saved session either, and a server that is up but signed
    out is still reported as such. Renewing the session needs [antigravity] oauth_client_id / oauth_client_secret (Antigravity's public
    installed-app client, not shipped in source); without them the fallback
    lasts while the saved access token does.

  • Windows system-tray popover. ai-usagebar-tray shows a NotifyIcon whose
    left-click opens an OpenUsage-style dashboard fed in-process by
    usage --json: a 320 px panel that sizes itself to its content, provider
    sections with the provider mark, name and plan over a grouped card, capsule
    meters in blue / yellow / red with a 52% left ⟷ Resets in 4d 17h line
    under each bar (click either side to flip Used/Left or countdown/exact time
    everywhere), spend rows, and a pace note ("~12% spare", "Limit in 1h 53m")
    with a tick on the meter for every metric whose window_secs is known.
    Right-click the icon for Refresh, Detect Providers, Open TUI, Start with
    Windows, and Quit; right-click a row to hide it, move it between Always
    Visible and On Demand, refresh just that provider or open its Customize
    screen. Customize orders and hides providers and rows; Settings has Launch
    at Login, Refresh Every (1, 5 or 10 minutes), a Global Shortcut
    recorded in place that toggles the popover from any window, Theme, Density,
    Time Format, Show Usage As, Reset Times and Always Show Pacing. Before its
    first report the tray runs local provider detection and turns on the
    vendors that already have a credential on this PC; the first report seeds
    the layout the way OpenUsage does (providers whose only error is a missing
    key start hidden behind a welcome card). Errors show a short title and a
    next step instead of an HTTP status line, and a rate-limited vendor says
    when it retries. config.toml gains a [tray] section (shortcut,
    refresh_minutes), written by the popover's Settings. The UI is a Vite +
    React + shadcn app in windows/popover/ with a Node contract test on its
    view-model; the host is Windows-only, so Linux and macOS builds never pull
    WebView2 or GTK. The release workflow gains a Windows job that publishes
    ai-usagebar-windows-x86_64.zip (tray, CLI and TUI) with a .sha256.
    The NotifyIcon is a bar-chart-in-circle mark shipped as anti-aliased
    rasters at 16/20/24/32/40/48 px and picked by SM_CXSMICON, so the shell
    never resamples it; node windows/icon/rasterize.js regenerates them from
    windows/tray-icon.svg. The SuperGrok (grok agent stdio) and Copilot
    (gh auth token) children run with CREATE_NO_WINDOW, so a refresh from a
    GUI process no longer flashes a console that takes the foreground.

  • Windows tray: in-app updates. Settings → Updates (Automatic /
    Notify me / Off; [tray] updates, default notify) checks GitHub Releases
    of the repository in Cargo.toml (CARGO_PKG_REPOSITORY) once an hour.
    Notify shows a dashboard banner with an Install button (✕ snoozes that
    version; a blue dot by the footer version remembers it) and Check Now
    in Settings says when the last check ran; Automatic installs unattended.
    Installing downloads the bare *-windows-x86_64.exe assets, verifies each
    against its .sha256 sidecar (integrity, not authenticity), swaps the
    binaries beside the running exe leaving ai-usagebar-tray.exe.old for the
    next start to remove, and relaunches — the relaunched process waits for
    the old one to release the single-instance mutex. Debug builds check but
    refuse to install. The Windows release job now also publishes the bare
    exes and their sidecars next to the zip; the first release cut after this
    change is the first one the tray can install.

Fixed

  • Rate-limit backoff. A vendor that answers HTTP 429 arms a five-minute
    backoff in its cache dir (.retry_after). While it is armed
    Cache::fresh_payload — the one pre-network step every vendor takes —
    serves the last good snapshot if there is one and otherwise reports
    rate limited; next attempt in 4m without touching the network, so the
    60-second poll no longer prolongs the block. A successful fetch clears it.
    Nous Research has its own fetch path without the shared cache and is not
    covered. Frontends that read usage --json see the same message in the
    vendor's error field.

  • Claude error cards in usage --json and the TUI keep the OAuth plan label
    when the usage endpoint fails, so a 401/429 still shows Max/Pro instead of a
    plan-less error. Quotas are not invented; only the label from
    ~/.claude/.credentials.json is kept.

Install

Arch (AUR)

yay -S ai-usagebar-bin      # prebuilt binary from this release
yay -S ai-usagebar          # compiles from source

Manual

curl -fsSL https://github.com/akitaonrails/ai-usagebar/releases/download/v1.14.0/ai-usagebar-linux-x86_64.tar.gz | tar xz -C ~/.local/bin ai-usagebar ai-usagebar-tui

Windows

Unzip ai-usagebar-windows-x86_64.zip anywhere and run ai-usagebar-tray.exe (the zip also carries ai-usagebar.exe and ai-usagebar-tui.exe). The bare *-windows-x86_64.exe assets are what the tray's self-updater downloads; they are not needed by hand.

Checksums (SHA256)

c05be18c54583789c8a010b49061d4e248af4c8754d0a72462ad0e4f65352dcf  ai-usagebar-linux-aarch64.tar.gz
770b2285d0a3cbd4a5cb519254493d2263656ca0629ee806296ae92cf5ed6c08  ai-usagebar-linux-x86_64.tar.gz
11082cb53a2d42f605c84db6e41b6b95b01ef81eac708ba41dfbc1ce9c83f378  ai-usagebar-tray-windows-x86_64.exe
6e7cc927c30384f3b147e11289ef0eaf7728d9a0068189065d5bba77285f9f88  ai-usagebar-tui-windows-x86_64.exe
e099f712d6829ba2293b8c7a9c72c59f772af6a4d739bef4426726a26fc83292  ai-usagebar-windows-x86_64.exe
c7b00fd6a1c545fedeac31e230bc0886c71ad4f9fa3354e3f2c60f2efa4854b4  ai-usagebar-windows-x86_64.zip

Full diff: v1.13.0...v1.14.0