aimonitor

module
v1.0.0-beta.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2026 License: MIT

README ΒΆ

aimonitor

Multi-account Claude Code session monitor and silent account switcher for macOS & Linux.

CI Latest release

aimonitor menu bar popover with 5-hour and 7-day usage bars

Features

  • πŸ” Live 5-hour and 7-day usage bars in your menu bar β€” server-side truth, polled from Anthropic's /api/oauth/usage introspection endpoint. No tokens consumed.
  • πŸ”€ Silent account switching β€” aimonitor switch <label> refreshes the OAuth access token via Anthropic's token endpoint and writes the live credential. No terminal hop, no claude /login.
  • πŸ€– Auto-swap at 80 % utilization (configurable). Picks the account with the most headroom. Running claude sessions are never interrupted β€” they pick up the new credential automatically.
  • πŸ” OS-keyring credential storage (macOS Keychain via /usr/bin/security, Linux libsecret). SQLite holds references; tokens never leave the keyring.
  • πŸ“‘ Local-first. No telemetry. No phone-home.

Install

macOS (Sonoma 14+)
brew install --cask japananh/tap/aimonitor

First launch: the .app is unsigned in v1.0.0-beta (notarization is a v1.1 deliverable). Clear the Gatekeeper quarantine once:

xattr -dr com.apple.quarantine /Applications/AIMonitor.app

Or right-click β†’ Open β†’ confirm. See docs/unsigned-app.md.

Linux (Ubuntu 22.04+)
curl -fsSL https://raw.githubusercontent.com/japananh/aimonitor/main/packaging/linux/install.sh | sh

CLI only on Linux; the GTK menu bar widget is a v2.0 deliverable.

Via go install (CLI only, any platform)
go install github.com/japananh/aimonitor/cmd/aimonitor@latest

Lands aimonitor in $GOBIN. No .app, no autostart service β€” useful if you only need the CLI for switching accounts from a terminal, or you don't want to add a Homebrew tap.

Quick start

# 1. Register your current Claude Code login as the first aimonitor account.
#    --adopt-current adopts the credential already in your keychain instead
#    of driving a fresh OAuth flow.
aimonitor add --adopt-current --label personal

# 2. Add a second account. aimonitor stashes the current credential, prints
#    instructions, polls the keychain. You drive `claude` + `/login` in
#    another terminal.
aimonitor add --label work

# 3. Switch silently β€” no terminal, no /login.
aimonitor switch work

# 4. See live 5h / 7d usage per account.
aimonitor list

# 5. Health check.
aimonitor doctor

Auto-swap is on by default at 80 % 5-hour utilization. Nothing else to configure for the common case.

Configuration

aimonitor config set auto_swap.enabled true       # default true
aimonitor config set auto_swap.threshold_pct 80   # default 80
aimonitor config set autostart true                # daemon at login
Full config keys
Key Default Description
auto_swap.enabled true Master toggle for the OAuth-limits-driven auto-swap
auto_swap.threshold_pct 80 5-hour utilization (%) at which to auto-swap
auto_swap.grace_sec 60 Seconds between the "auto-swap pending" notification and the actual swap, so you can wrap up a live claude session. 0 swaps immediately.
autostart false Start the daemon at login
autoswitch false (Legacy) tripwire-driven JSONL accumulator. Disabled in v1.0.0-beta.4 β€” the new auto_swap.* keys supersede it.

How it works

When the active account hits the configured 5-hour utilization threshold, aimonitor finds the next-lowest-utilization account and silently swaps:

                      polled every 5 min Β± 30 s jitter
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚  GET  api.anthropic.com/api/oauth/usage β”‚
                β”‚       β†’ 5h % + 7d % + reset times       β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
              5h utilization β‰₯ threshold?
                          β”‚
                          β–Ό  yes β€” pick lowest-utilization account
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   POST platform.claude.com/v1/oauth/token
   β”‚ target account   β”‚ ──────────────────────────────────────────▢
   β”‚ refresh_token    β”‚   grant_type=refresh_token
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
                                         β–Ό fresh access_token
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚ Claude Code-credentials   β”‚
                          β”‚   (macOS Keychain slot)   β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                         β”‚
                                         β–Ό
                            next `claude` invocation
                            uses the new account
                            β€” no /login required

See docs/architecture.md for the full daemon / store / widget breakdown.

Privacy & security

  • No telemetry. No phone-home. Anywhere.
  • OAuth tokens live only in the OS keyring. SQLite holds references, never secrets.
  • Token bytes are never logged, even at --debug level. Log scrubbing matches sk-ant-(oat|ort)….
  • The only outbound traffic aimonitor initiates is to two Anthropic OAuth surfaces:
    • GET https://api.anthropic.com/api/oauth/usage β€” introspection-only, ~5 KB per call. Consumes no tokens. Background interval: 5 min Β± 30 s jitter for the active account, with exponential backoff on errors (capped at 1 h). Inactive accounts are fetched only when you open the popover.
    • POST https://platform.claude.com/v1/oauth/token β€” only on account switches when the cached access token is near or past expiry. Silent (no browser).
  • The legacy aimonitor probe CLI subcommand fires a real /v1/messages request and is deprecated. The daemon no longer uses it.

See docs/security.md for the full threat model.

Roadmap

Directional, not committed.

  • v1.1: daily usage chart, cost estimation per account, notarized macOS app.
  • v1.2 (contingent on v1.1 notarization): submit to homebrew/cask so brew install aimonitor works without tapping a third-party repo.
  • v2.0: Ubuntu GTK menu bar widget, second Provider implementation (Codex or Copilot CLI).

Uninstall

aimonitor uninstall              # disable autostart; keep your data
aimonitor uninstall --purge      # also drop SQLite DB, config, aimonitor keyring entries

# macOS
brew uninstall --cask aimonitor
brew untap japananh/tap          # optional

# Linux
systemctl --user disable aimonitor.service
sudo rm /usr/local/bin/aimonitor

Your original Claude Code-credentials keyring entry is never touched by aimonitor's uninstall β€” existing claude CLI logins keep working.

Build from source

Requires Go 1.25+. Pure Go on all platforms β€” CGO_ENABLED=0 works on macOS too since v1.0.0-beta.4 (keychain access shells out to /usr/bin/security instead of linking the Security framework via cgo).

git clone https://github.com/japananh/aimonitor
cd aimonitor
make build              # Go CLI binary
make test               # unit tests
make widget             # AIMonitor.app via Swift Package Manager (macOS only)
make release-snapshot   # full goreleaser dry-run (no publish; needs goreleaser installed)

On macOS the menu bar widget needs the Swift toolchain (xcode-select --install). Full Xcode is not required; the widget builds headlessly via Swift Package Manager.

Documentation

Topic Where
Architecture (daemon, store, widget) docs/architecture.md
Threat model + scrubbing rules docs/security.md
Why the macOS .app is unsigned in v1.0.0-beta docs/unsigned-app.md
User stories shipped in v1 USER_STORIES.md

See also

Related tools in the Claude-Code-ergonomics space:

  • ncthanhngo/claude-bar β€” sibling macOS menu-bar app and the source of patterns aimonitor learned from (keychain shell-out, OAuth refresh flow, account registry).
  • ryoppippi/ccusage β€” pure-CLI usage analyzer; parses local Claude transcripts for per-day / per-session breakdowns. Read-only, no credential management.

License

MIT. See LICENSE.

Directories ΒΆ

Path Synopsis
cmd
aimonitor command
Command aimonitor is the CLI entry point.
Command aimonitor is the CLI entry point.
internal
claudeconfig
Package claudeconfig reads and writes ~/.claude.json β€” the file Claude Code uses to record which OAuth account is active (the `oauthAccount` object) alongside many unrelated settings.
Package claudeconfig reads and writes ~/.claude.json β€” the file Claude Code uses to record which OAuth account is active (the `oauthAccount` object) alongside many unrelated settings.
cli
Package cli implements the aimonitor CLI subcommands.
Package cli implements the aimonitor CLI subcommands.
config
Package config holds aimonitor's user-facing configuration: thresholds for the auto-switch tripwires, autoswitch on/off, cool-down, etc.
Package config holds aimonitor's user-facing configuration: thresholds for the auto-switch tripwires, autoswitch on/off, cool-down, etc.
daemon
Package daemon hosts aimonitor's long-running background components: the Unix-socket JSON-RPC server, the JSONL filesystem watcher, the auto-switch engine.
Package daemon hosts aimonitor's long-running background components: the Unix-socket JSON-RPC server, the JSONL filesystem watcher, the auto-switch engine.
install
Package install wires platform-specific autostart helpers.
Package install wires platform-specific autostart helpers.
provider
Package provider defines the abstraction every AI-provider integration must implement.
Package provider defines the abstraction every AI-provider integration must implement.
provider/claude
Package claude implements the Provider interface for Anthropic's Claude Code OAuth ecosystem.
Package claude implements the Provider interface for Anthropic's Claude Code OAuth ecosystem.
secret
Package secret bridges aimonitor to the OS-native secret store: macOS Keychain on darwin, libsecret (Secret Service DBus) on linux.
Package secret bridges aimonitor to the OS-native secret store: macOS Keychain on darwin, libsecret (Secret Service DBus) on linux.
store
Package store wraps the SQLite database that aimonitor uses for everything that is NOT a secret: account references, per-file JSONL resume offsets, usage samples, audit log, settings.
Package store wraps the SQLite database that aimonitor uses for everything that is NOT a secret: account references, per-file JSONL resume offsets, usage samples, audit log, settings.
updater
Package updater checks GitHub Releases for a newer aimonitor build and describes how to install it.
Package updater checks GitHub Releases for a newer aimonitor build and describes how to install it.
util/filelock
Package filelock provides a minimal Unix flock(2) wrapper for serializing access to multi-step operations like account switching.
Package filelock provides a minimal Unix flock(2) wrapper for serializing access to multi-step operations like account switching.
version
Package version holds the build-time version string for aimonitor.
Package version holds the build-time version string for aimonitor.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL