Use this command to install AI Usage Dashboard with WinGet:
winget install --id=neyham.AIUsageDashboard -e
AI Usage Dashboard is a local-first Windows desktop dashboard and screensaver
for viewing Claude Code, Codex, and Grok Build usage windows alongside a
DeepSeek API balance. Display Settings provide a write-only DeepSeek API key
field and an optional Low Power Mode that disables animation and reduces
renderer update work. Credentials and provider requests stay in the native
Rust backend; the renderer receives sanitized usage summaries only. The
project has no developer-operated server, analytics, or telemetry.
curl -fsSL https://github.com/neyham/ai-usage-dashboard/releases/latest/download/install-macos.sh | sh
Linux — Debian/Ubuntu .deb, otherwise AppImage
curl -fsSL https://github.com/neyham/ai-usage-dashboard/releases/latest/download/install-linux.sh | sh
The macOS and Linux scripts verify downloaded assets against the published
SHA-256 file. Published installers are currently unsigned, so Windows SmartScreen
or macOS Gatekeeper may require manual confirmation.
Available usage windows, reset times, extra usage, cooldown, and cache state
Codex
Usage windows, reset times, plan, banked resets, and earliest expiry
Grok Build
Server-reported credit period, reset time, plan, and optional monthly allowance
DeepSeek
API balance and insufficient-balance state
Each provider refreshes independently; one outage does not erase the others.
Last-known-good data stays visible and is marked when it may be stale.
Choose any zero-to-four provider layout.
Use a normal window or borderless fullscreen on every platform.
Enable Low Power Mode to stop animation and heavy compositing, update the
clock once per minute, and use a 15-minute automatic-refresh minimum.
Windows additionally supports WSL credential discovery, scheduled idle launch,
and screensaver mode.
Compatibility and limitations
Version 0.6.0 is the current multi-platform release: Windows (WinGet + NSIS),
Linux (.deb / AppImage), and macOS (.dmg). Screensaver and scheduled-idle
helpers remain Windows-only. Published installers are not code-signed.
This project reads credential formats and usage endpoints used by provider CLI
tools. Some of those interfaces are undocumented and can change without notice;
incompatible responses fail closed to sanitized last-known-good data. This
project is not affiliated with, endorsed by, or supported by Anthropic, OpenAI,
xAI, or DeepSeek.
Local by design
The Rust backend owns credentials and live network requests. The React renderer
only receives sanitized percentages, reset times, plan labels, balances,
timestamps, and status text.
There is no project account, project-operated server, analytics, or telemetry.
Stored tokens, API keys, credential files, and raw provider responses are
never returned to the renderer.
A DeepSeek key entered in Settings is stored in the per-user config.json,
never in the usage cache, and is not shown again by the UI. macOS and Linux
config files use mode 0600.
Sanitized cached summaries can still contain private account information and
should be treated as sensitive.
Malformed configuration and invalid mock modes fail closed.
"Local-first" does not mean live mode is offline: enabled providers are queried
directly from the Rust backend. See the full security model before
reporting a vulnerability or suspected credential exposure.
Additional installation notes
Pin a version with VERSION=0.6.0 before the install script, for example
VERSION=0.6.0 sh install-linux.sh.
Windows (WinGet and direct installer)
The package is live in WinGet as neyham.AIUsageDashboard. After a new GitHub
release, community-source indexes can lag briefly while the version manifest is
reviewed and propagated:
winget source update
winget show --id neyham.AIUsageDashboard --exact --source winget
After installation, open AI Usage Dashboard (Judge Demo) from the Start
menu for an offline walkthrough with synthetic data.
Linux and macOS
The one-line scripts pull .deb / AppImage or .dmg assets from GitHub
Releases and verify checksums. Direct downloads remain available on the
latest release
page.
Run without credentials
The isolated offline demo reuses the production parsers and bundled fixtures:
launch with --judge-demo (Start menu shortcut: AI Usage Dashboard (Judge
Demo)); the UI shows SYNTHETIC DEMO · OFFLINE;
it does not load normal config.json, credentials, cache, or provider
endpoints;
refresh actions regenerate fixture data without constructing a live request;
provider selections persist separately in the platform config directory
(judge-demo.json) and cannot alter live settings;
settings can exercise every zero-to-four panel layout.
It demonstrates the UI and parser-to-renderer boundary without touching live
accounts. It does not validate authentication, endpoint availability, or live
quota accuracy.
Command-line fallbacks:
# Windows (current-user install)
& "$env:LOCALAPPDATA\AI Usage Dashboard\ai-usage-dashboard.exe" --judge-demo
# Linux / macOS (from a local build)
./src-tauri/target/release/ai-usage-dashboard --judge-demo
Windows:x86_64-pc-windows-msvc toolchain and Visual Studio Build Tools with
Desktop development with C++. Build from PowerShell for Windows integration
(Task Scheduler and screensaver integration). A WSL build produces a Linux
binary instead.
macOS: Xcode Command Line Tools (xcode-select --install).
Build and run
git clone https://github.com/neyham/ai-usage-dashboard.git
cd ai-usage-dashboard
npm ci
npm run app:dev
Build the native app and platform installers:
npm run app:build
Outputs land under src-tauri/target/release/ and
src-tauri/target/release/bundle/ (NSIS on Windows, .deb/AppImage on Linux,
.dmg/.app on macOS).
Do not use a standalone cargo build debug executable as a deployment smoke
test. Debug builds load the Vite devUrl (http://localhost:1420) and require
npm run app:dev to stay running. Use npm run app:build and the release binary
or bundle when validating embedded production assets.
Provider setup
Use the settings button in the bottom toolbar to choose the window mode and
which providers appear on the home screen. Disabled providers are excluded from
automatic and manual refresh cycles, including credential reads and network
requests. Only changed fields are submitted; provider and window changes are
saved together, and a temporary CLI fullscreen override is not persisted by a
provider-only save. The same dialog accepts a replacement DeepSeek API key;
leave its password field blank to keep the existing value.
Provider
Default credential source
Override
Claude
~/.claude/.credentials.json, then credentials.json; on Windows also the Ubuntu WSL home
claudeCredentialsPath (wsl:: on Windows only)
Codex
~/.codex/auth.json; on Windows also the Ubuntu WSL home
codexAuthPath (wsl: or \\wsl.localhost\... on Windows only)
DeepSeek
deepSeekApiKey saved from Display Settings, then DEEPSEEK_API_KEY
Enter or replace it in Display Settings
Grok Build
~/.grok/auth.json; on Windows also the Ubuntu WSL home
grokCredentialsPath (wsl: or UNC on Windows only)
Sign in with the official Claude Code, Codex, and Grok Build clients before
enabling their panels. Grok is disabled by default so an upgrade never starts
reading a newly introduced credential source without an explicit selection.
The direct settings field stores DeepSeek's key as plaintext in the per-user
configuration file. The app never pre-fills or returns that value to the UI;
blank means unchanged. On Mac/Linux, every app config replacement is created
with mode 0600 before it becomes visible.
If you do not want the key in config.json, set DEEPSEEK_API_KEY in the app's
environment instead.
For a Windows WSL distribution other than Ubuntu, configure an explicit path
such as:
The dashboard invokes wsl.exe without interpolating the configured path into
a shell command, caps credential input at 64 KiB, and stops the reader after
15 seconds. A \\wsl.localhost\... UNC path remains supported when preferred.
Automatic Grok CLI renewal requires the native official path or a wsl: path;
UNC paths remain read-only. An explicit path is fail closed. If it cannot be
read, the dashboard reports an authentication or data error instead of silently
selecting another account.
When a recognized Grok access token expires and the login contains a refresh
token, the dashboard runs
grok --no-auto-update models through the official CLI with no shell
interpolation, no captured output, and a 20-second timeout. The official CLI
silently renews its own session, after which the dashboard rereads
auth.json. The dashboard never extracts the refresh-token value into app
state, sends it, logs it, passes it to the child process, or writes the
credential file itself. A billing 401 can trigger the same flow once, covering
clock skew or a token rejected before its local expiry. Attempts are serialized
across dashboard processes and held per credential source for 15 minutes before
another background attempt. An unavailable CLI is shown as
GROK SESSION EXPIRED instead of incorrectly claiming that the credential file
is missing; a 403 is reported separately as GROK ACCESS UNAVAILABLE.
CodexBar's Grok adapter informed the credential boundary, official-CLI renewal,
and provider selection. Grok Build 0.2.111 currently returns Method not found
for its x.ai/billing ACP probe, so this dashboard uses the live-verified
read-only JSON billing responses that include an explicit period type and Grok
Build product usage. These are not public APIs; incompatible responses fail
closed to sanitized last-known-good data.
Claude token renewal
Native Windows Claude credential files are read-only to the dashboard. Direct
OAuth renewal is intentionally disabled for those files because the dashboard
cannot participate in every lock used by Claude Code. If the native token has
expired, refresh it with Claude Code or opt into the bounded CLI fallback in
configuration.
For explicit wsl:: credentials, direct renewal uses
Claude Code-compatible lock directories, reloads the file while holding the
locks, merges only rotated OAuth fields, and writes atomically.
The optional Claude Code fallback is off by default because its recovery command
may consume a small amount of usage. When enabled, it is limited to selected
authentication failures, clamped to a maximum timeout and budget, and throttled
across dashboard processes to one attempt per 30 minutes.
Configuration
Run the following to create or open the configuration file:
# Linux / macOS
./src-tauri/target/release/ai-usage-dashboard --config
# Windows
.\src-tauri\target\release\ai-usage-dashboard.exe --config
Settings changed in the application apply immediately. Restart the application
after editing the JSON file directly. Timing and CLI recovery values are
clamped to safe bounds:
Setting
Allowed range
refreshIntervalMinutes
5 to 1,440 minutes
claudeCodeRefreshTimeoutSeconds
5 to 120 seconds
claudeCodeRefreshMaxBudgetUsd
USD 0.001 to USD 0.10
lowPowerMode can also be changed from Display Settings. It disables
continuous motion and heavyweight full-screen overlays, removes decorative
glows, updates the clock once per minute, and applies a 15-minute minimum to
automatic provider refreshes. Manual refresh remains available. Hidden or
minimized windows pause motion and clock updates automatically in either mode.
deepSeekApiKey is plaintext in config.json. Treat that per-user file as a
secret and do not sync or commit it. The settings UI never displays the saved
value again.
Refresh and cache behavior
Enabled providers refresh immediately at launch, then repeat every five
minutes by default. Normal mode can be configured from 5 minutes to 24 hours.
Disabled providers are not displayed, do not read credentials, and do not
receive background or manual refresh requests. Their last-known cache remains
available if they are enabled again later.
Screensaver mode enforces a 15-minute minimum interval to avoid unnecessary
idle-time traffic.
Low-power mode enforces the same 15-minute minimum while it is enabled. The
change is applied immediately without triggering an extra provider request.
Press F5 or use the refresh button for an on-demand refresh in normal or
fullscreen mode.
Provider usage and balance requests receive one retry after transport
failures, HTTP 408, or HTTP 5xx responses. Claude OAuth renewal is not
automatically replayed after an ambiguous transport failure because refresh
tokens can rotate.
Claude HTTP 429 responses honor Retry-After plus a 30-second buffer. If no
usable value is returned, the cooldown defaults to 30 minutes.
Codex, DeepSeek, and Grok HTTP 429 responses use the same bounded cooldown and
persist it in state.json, preventing manual refreshes from bypassing the
provider's Retry-After deadline.
A successful response is cached per provider. Cached data older than six
hours is marked as possibly stale.
Understanding status warnings
SYSTEM NOMINAL means every enabled provider returned fresh, healthy data.
WARNING - SERVICE DEGRADED means at least one enabled provider is cached,
unavailable, rate limited, unauthenticated, or reporting a non-nominal balance.
SERVICE FAILURE means every enabled check failed or only fallback data was
available. With no providers selected, the dashboard remains in standby.
Panel status text distinguishes setup and auth from generic failures when
possible: DeepSeek uses KEY MISSING / AUTH EXPIRED / AUTH FORBIDDEN
instead of a blanket API ERROR when the key is absent or rejected; Codex and
Claude use LOGIN REQUIRED / AUTH EXPIRED (and related auth statuses), while
a malformed or unreadable Codex credential file is CREDENTIAL ERROR; Grok
keeps GROK SESSION EXPIRED for expired sessions. API ERROR still means a
transport, HTTP, or response-parse failure after credentials were available.
If every enabled panel fails:
Confirm that Claude Code, Codex, and any enabled Grok Build provider are
signed in and that a DeepSeek key is available through one of the documented
sources.
Open config.json and check for invalid JSON or an incorrect explicit path.
Restart after editing the JSON directly, then trigger one manual refresh.
Check the providers' official status pages. A provider outage should not be
repaired by deleting credentials.
Use mock mode to separate a local UI problem from a credential or provider
problem.
Deleting %LOCALAPPDATA%\AiUsageDashboard\state.json only clears cached display
data; it does not repair authentication.
Launch modes
Default chrome follows windowMode in config.json (normal or fullscreen).
Change it from Display Settings in the app (gear icon), or by editing the
config file and restarting. CLI flags still override the saved preference for
that process.
Argument
Behavior
none
Uses saved windowMode (normal by default)
--fullscreen
Borderless fullscreen; Esc exits
--judge-demo
Offline synthetic demo; no normal config, credential, cache, or provider access
/s or -s
Fullscreen, always on top, and exits on real input after a short arming delay
--config or /c
Opens config.json and exits
/p
Windows screensaver preview; intentionally exits without rendering
Task Scheduler is the recommended idle-launch method:
The script prefers an installed executable under %LOCALAPPDATA%, then falls
back to the release build. Use -ExePath when the executable lives elsewhere.
The .scr integration is experimental because WebView2 is not embedded in the
small Windows Settings preview pane:
The installer backs up the current user's screensaver registry values and only
restores them if AI Usage Dashboard is still the selected screensaver when it is
removed.
Tests
Install the Playwright browser once, then run the renderer and Rust suites:
npx playwright install chromium
npm test
npm run test:rust
cargo clippy --locked --all-targets --manifest-path src-tauri/Cargo.toml -- -D warnings
The UI suite exercises healthy, rate-limited, partial-failure, and
insufficient-balance states across seven viewports, including Surface 200%
landscape, portrait, and half-Snap layouts. It also checks overflow, touch
targets, refresh state, keyboard behavior, screensaver input exit, offline demo
disclosure, zero/one/two/three/four-panel selection layouts, transactional
settings failures, CLI fullscreen isolation, modal focus behavior, and auth-chip
mapping.
Set mockMode to normal, claude429, or failures to exercise the embedded
provider fixtures without network access. An unknown value displays INVALID MOCK MODE and remains offline. --judge-demo is the safer offline entrypoint
because it ignores normal configuration and cache files entirely.
Repository layout
src/ React and TypeScript renderer
scripts/viewport-check.mjs Playwright viewport and interaction suite
mocks/ Embedded provider response fixtures
src-tauri/src/ Rust backend, cache, fetchers, and launch modes
src-tauri/nsis-hooks.nsh Offline demo Start menu shortcut
docs/releases/ Per-release notes
install-idle-task.ps1 Scheduled idle-mode install and removal
install-screensaver.ps1 Experimental .scr install and safe restoration
License
AI Usage Dashboard is licensed under the MIT License. Embedded font
software keeps its separate OFL-1.1 terms; see
THIRD_PARTY_NOTICES.md.