aium
AI usage monitor: a Python CLI core that polls your AI providers and a GNOME Shell extension that displays the results. Think of it as a system monitor, but for AI providers.
Features
- Panel indicator — robot icon with monthly spend and balance (stacked two-line label).
- Popover — per-provider: balance, monthly spend, rate-limit quota windows, sparklines (spend or quota trend), plan, and a peak/off-peak dot for providers with dynamic pricing (DeepSeek).
- Clickable providers — open the provider's usage/dashboard page.
- Provider abstraction — add a provider with one file + one registry entry.
- Secrets — API keys in the system keyring; OAuth providers reuse the CLI's own credential files (Codex, Claude Code, Antigravity).
- History — SQLite time-series of balances, quota and usage.
- systemd timer — polls every 60 minutes, no resident daemon.
Screenshots
Installation
Quick install (CLI + timer + extension)
curl -fsSL https://raw.githubusercontent.com/jonykalavera/aium/main/install.sh | bash
Pin a specific release with AIUM_VERSION:
curl -fsSL https://raw.githubusercontent.com/jonykalavera/aium/main/install.sh | AIUM_VERSION=v0.1.1 bash
The script installs the aium CLI from PyPI (aium-cli), the systemd user
timer (polls every 60 min) and the GNOME Shell extension. Requires curl,
unzip, and one of uv / pipx / pip. Restart GNOME Shell (logout/login)
to load the extension.
CLI only
pipx install aium-cli # or: uv tool install aium-cli
aium init
The CLI reads its config from ~/.config/aium/ (YAML) and keeps history in
~/.local/share/aium/ (SQLite).
Extension only
Grab aium@jonykalavera.zip from the releases page, extract it
to ~/.local/share/gnome-shell/extensions/aium@jonykalavera/, compile the
schema (glib-compile-schemas schemas) and enable it with
gnome-extensions enable aium@jonykalavera.
From source (development)
./local-install.sh # installs the CLI (uv tool), the systemd timer and the extension from this repo
Quick start
aium providers add deepseek
aium keys set deepseek # prompts for the API key (keyring)
aium poll
aium status
Providers
| Kind | Auth | What it reports | Balance means |
|---|---|---|---|
deepseek |
API key | balance, peak/off-peak tariff | prepaid credit (balance) |
kimi |
API key | balance | prepaid credit (balance) |
openrouter |
API key | balance + monthly usage | prepaid credit (credits) |
openai |
OAuth (Codex) | rate-limit quota windows | none |
anthropic |
OAuth (Claude Code) | spend vs monthly limit + quota windows | monthly budget remaining (budget) |
google |
OAuth (Antigravity) | plan/tier + quota (paid tiers) | none |
zai |
API key | quota windows + plan | none |
manual |
— | fixed subscription cost + renewal | — |
Balance semantics. "Balance" means different things per provider:
- Prepaid credit (
balance/credits) — real money on the account. OpenRouter reports it ascreditsbecause BYOK/free usage is billed elsewhere and does not decrement it. - Budget (
budget) — Anthropic's remaining monthly spending limit, not money you hold. - None — the provider exposes no balance (quota/plan only).
The aggregated Prepaid balance total sums only prepaid-credit balances; budget and quota-only providers are shown per-row but excluded from the total.
OAuth providers reuse the CLI's own credential files (~/.codex/auth.json,
~/.claude/.credentials.json, ~/.gemini/oauth_creds.json) — no API key
needed. Their usage endpoints are private/undocumented and may break.
Commands
aium providers add|list|show|update|remove
aium providers update deepseek --peak-window 00:30-16:30 # UTC high-tariff window
aium keys set|list|delete
aium poll # fetch every provider, persist history, refresh cache
aium status # show the last cached status
aium history <id> # balance history for a provider
peak_window marks the UTC peak (high-tariff) hours as 'HH:MM-HH:MM'
(wrapping across midnight allowed); the provider row shows a peak/off-peak
indicator. DeepSeek defaults to 00:30-16:30.
Architecture
src/aium/ # Python core (config, secrets, history, polling, providers)
extension/ # GNOME Shell outlet (GJS) — reads ~/.cache/aium/status.json
lib/ # pure logic (unit-tested), no gi:// imports
tests/ # GJS unit tests (gjs -m extension/tests/run.js)
systemd/ # aium-poll timer/service (user units)
tests/ # pytest (core)
The extension is a passive outlet: no provider CRUD, no secrets. It renders
~/.cache/aium/status.json, whose schema (models.py::StatusFile) is the
contract between the core and the extension.
Development
uv sync --all-groups --locked # install dev deps
make uv.check # ruff lint + ty typecheck + format check
make uv.test # pytest --cov aium --blockage (network blocked)
make ext-test # GJS unit tests for the extension logic
Tools: ruff (lint/format), ty (type checker), pytest (coverage + network
blockage). Recipes use bare commands; prefix with uv. to run inside the uv
environment. To iterate on the extension on Wayland (no hot reload), use
./scripts/dev-nested.sh (requires mutter-devkit).
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aium_cli-0.1.2.tar.gz.
File metadata
- Download URL: aium_cli-0.1.2.tar.gz
- Upload date:
- Size: 104.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33275ac5d85083a639b190bf2f254d60daf4205bce7fd0b743ab3dc6ed3f8b67
|
|
| MD5 |
4d6cd130a43f93f367a7a098e0b6814a
|
|
| BLAKE2b-256 |
9e4a77863764ec879c711bb34b0d919b6befb553341144a8a512d0a6e0f439cb
|
Provenance
The following attestation bundles were made for aium_cli-0.1.2.tar.gz:
Publisher:
release.yml on jonykalavera/aium
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aium_cli-0.1.2.tar.gz -
Subject digest:
33275ac5d85083a639b190bf2f254d60daf4205bce7fd0b743ab3dc6ed3f8b67 - Sigstore transparency entry: 2564268975
- Sigstore integration time:
-
Permalink:
jonykalavera/aium@8d81d3bc4439f0ea2e9393fa9b8dcf854f4fc74f -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/jonykalavera
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8d81d3bc4439f0ea2e9393fa9b8dcf854f4fc74f -
Trigger Event:
push
-
Statement type:
File details
Details for the file aium_cli-0.1.2-py3-none-any.whl.
File metadata
- Download URL: aium_cli-0.1.2-py3-none-any.whl
- Upload date:
- Size: 31.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7510f53b872b0d556808a08f0ce1def75f683057a46f66f39803816e1c356afa
|
|
| MD5 |
8b3fb85438d86b9e97f9e5fb04e7efb1
|
|
| BLAKE2b-256 |
034eab920eb2da1f005d03582f3226c8cf9b2718d50fb7b64041dc23ff0e35f9
|
Provenance
The following attestation bundles were made for aium_cli-0.1.2-py3-none-any.whl:
Publisher:
release.yml on jonykalavera/aium
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aium_cli-0.1.2-py3-none-any.whl -
Subject digest:
7510f53b872b0d556808a08f0ce1def75f683057a46f66f39803816e1c356afa - Sigstore transparency entry: 2564269229
- Sigstore integration time:
-
Permalink:
jonykalavera/aium@8d81d3bc4439f0ea2e9393fa9b8dcf854f4fc74f -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/jonykalavera
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8d81d3bc4439f0ea2e9393fa9b8dcf854f4fc74f -
Trigger Event:
push
-
Statement type: