AI Meter is a native macOS menu-bar app for OpenAI/Codex and Anthropic/Claude. It shows trustworthy live plan limits when the terminal clients expose them, measures local coding activity, and keeps optional personal budgets distinct from provider-reported quota.
- Live percent-used meters for Codex, and for Claude with an optional status-line helper.
- Local token totals for OpenAI/Codex and Anthropic/Claude when compatible records are available.
- Automatic refresh every 1, 5, or 15 minutes, with battery-aware behavior.
- Optional token budgets and reset windows for providers without live limits.
- Optional local cost estimates from user-configured model pricing.
- Signed in-app updates via Sparkle, with optional automatic checking.
- No API keys, account credentials, or manual exports required.
- Local-first: AI Meter does not upload your usage records or include telemetry.
- macOS 14 Sonoma or later.
- Apple Silicon or Intel Mac.
- A supported AI client installed or previously used on this Mac.
AI Meter is a menu-bar-only app. It does not appear in the Dock after launch.
Building requires full Xcode with the Swift 6.2 toolchain. Command Line Tools alone can build the app on some systems, but do not reliably include XCTest.
git clone https://github.com/anthonylimo90/ai-meter.git
cd ai-meter
./scripts/preflight.sh
./scripts/package_app.sh
open "dist/AI Meter.app"The packaged app is written to dist/AI Meter.app. Move it to /Applications
if you want to keep it installed.
Current GitHub release installers are not Apple Developer ID signed or notarized. The app bundle is ad hoc signed, and Sparkle updates are separately protected by an EdDSA signature. macOS may therefore show an unidentified developer or verification warning during the first installation.
When a .pkg build is available:
- Download it from GitHub Releases.
- Compare its SHA-256 digest with the release's
SHA256SUMSfile. - Control-click the package, choose Open, and confirm the prompt if Gatekeeper blocks the normal double-click flow.
- Complete the installer, then launch AI Meter from
/Applications.
- Launch AI Meter and select its menu-bar item.
- Choose the refresh button to scan your local usage records.
- Open Settings > Providers to review Data Health, browse for an extra record file/folder, or configure an optional fallback budget.
- Open Settings > General to change the refresh interval or simplify the menu-bar display.
Notifications are opt-in. AI Meter can alert once every six hours per provider when 75% or more of a current limit is used, and once per hour when a provider's local source is stale or cannot be read. Source-health alerts take priority over quota alerts so an old value is never presented as current. If macOS denies permission, AI Meter turns the setting back off and explains where to enable it.
AI Meter labels quota, remaining usage, provider health, and recovery controls for VoiceOver. Status also appears as text and symbols, so color is never the only signal.
AI Meter discovers standard client folders automatically. A provider can still show Unavailable when its folder is missing, its records do not contain token metadata, or it does not publish a trustworthy plan limit.
| Provider | Local source | What AI Meter can show |
|---|---|---|
| OpenAI / Codex | ~/.codex/sessions |
Local tokens plus provider-reported 5-hour and weekly Codex plan windows when present |
| Anthropic / Claude | ~/.claude/projects (+ optional status-line helper) |
Local token totals, plus live 5-hour and weekly plan limits when Show live Claude plan usage is enabled |
AI Meter intentionally supports only these two ecosystems. You can add a custom JSON, JSONL, or log folder for either provider in Provider settings.
AI Meter keeps two different measurements separate:
- Plan usage is a percentage and reset time reported by the provider's own client. AI Meter reads this for Codex from its local session records, and for Claude through the optional status-line helper (see Claude live usage).
- Local token usage is counted from compatible records stored on your Mac. It is useful for tracking activity, but it is not necessarily the same as a provider's billing or subscription quota.
The popover leads with plan usage and its reset time. Local token activity and estimated cost appear underneath as secondary context, with their local measurement window stated explicitly.
When live plan usage is unavailable, you can configure a personal token budget,
window, and reset time. These are your own reference values, not provider data.
Leaving the fallback budget at 0 keeps the percentage unconfigured.
AI Meter is local-first and does not request provider account credentials or inspect browser sessions. A future account connection will be offered only when an official, read-only integration can return the exact plan or billing data it labels. Until then, the app clearly identifies whether a figure came from a provider-reported local plan window, local records, or your own budget.
Live plan usage is a by-product of the command-line clients, not the desktop
apps. Codex records its rate_limits in the session files it writes to
~/.codex/sessions, and Claude Code passes its limits to the status-line helper
— both only when run from the terminal. The Claude and ChatGPT/Codex desktop
apps keep their usage figures in memory and browser storage, and never write a
plan limit to disk in a readable form, so AI Meter cannot surface live limits
from desktop sessions alone. Token totals are less affected: Claude's desktop
sessions still log into ~/.claude/projects, so their token counts are picked
up even though their limits are not. To see live plan limits, run the terminal
client at least once; the figures then persist until the window resets.
Claude Code does not record its plan limits in its session logs the way Codex does, but it does pass them to a configured status line. AI Meter uses that sanctioned, local channel.
Turn on Settings > Providers > Claude > Show live 5-hour and weekly limits and AI Meter:
- Installs a small helper script and points Claude Code's
statusLineat it (your existing status line, if any, is preserved and still runs). - The helper writes only Claude's
rate_limits(5-hour and weeklyused_percentageand reset times) to a file under~/.config/ai-meter/. - AI Meter reads that file and shows your live Claude plan usage.
This uses no account credentials and makes no network requests — Claude Code itself hands AI Meter the data through its documented status line. The values update while Claude Code is running; when it is idle, AI Meter shows the last known reading until its window resets. Turning the setting off removes the helper and restores your previous status line.
AI Meter can estimate local token cost when you enable Estimate token cost in provider settings and enter USD-per-million-token rates for a model. These estimates are calculated locally from compatible usage records. They are not provider billing statements.
Actual bills can differ because local records may omit model names or token splits, providers may apply subscription terms, caching discounts, credits, taxes, usage buckets, or other account-level adjustments, and official pricing can change. Keep the configured rates aligned with the provider's current pricing page if you use cost estimates for planning.
AI Meter reads only the local folders listed in Settings > Providers and any extra folder you add. It does not ask for or read provider account credentials, launch other applications, or make network requests to read usage — every reading comes from records already on your Mac.
For updates, AI Meter uses Sparkle. When you check for updates — or, if you opt in, on Sparkle's periodic schedule — it fetches a small update feed (an "appcast") served from this project's GitHub Pages site. The request sends no usage data, account data, or identifiers, only the standard IP address and user agent. Automatic checking is off by default.
AI Meter updates itself in place:
- Open Settings > About and select Check for Updates (or enable Check for updates automatically).
- If a newer version exists, Sparkle shows the release and an Install button.
- AI Meter verifies the update's cryptographic (EdDSA) signature, replaces itself, and relaunches.
Every update is signed with a private key held only in CI; the app embeds the
matching public key and refuses any update that fails verification. See
docs/auto-update-plan.md for the design.
macOS says the installer could not be verified
This warning is expected for the current unsigned, unnotarized GitHub package.
Verify that it came from the linked GitHub release, compare its SHA-256 digest
with SHA256SUMS, then Control-click the package and choose Open. Do not
bypass the warning for a package obtained from another source.
AI Meter launched but no window appeared
This is expected. Select AI Meter on the right side of the menu bar.
A provider says "No local data folder is available"
Run that provider's local client at least once, then refresh AI Meter. You can also add the correct folder under Settings > Providers > Extra source.
Records were found, but usage is unavailable
The files may not contain timestamped token metadata that AI Meter recognizes. This is common for clients that do not expose token-level usage locally.
Claude shows tokens but no plan percentage
By default Claude shows local token totals only. To see live 5-hour and weekly limits, enable Settings > Providers > Claude > Show live 5-hour and weekly limits (see Claude live usage). The percentage appears after Claude Code runs and refreshes its status line at least once.
Refreshes are less frequent than configured
macOS Low Power Mode limits background refreshes to every 15 minutes. Opening the menu or choosing Refresh Now can update sooner.
Verify the selected Xcode toolchain, then run the test suite and build:
./scripts/preflight.sh
swift test
./scripts/package_app.shBuild an installer package:
./scripts/package_installer.shOutputs:
dist/AI Meter.appdist/AI Meter-<version>.pkg
Generate deterministic screenshots without reading local provider data:
swift run AIMeterSnapshot implementation.png
swift run AIMeterSnapshot settings.png --settings
swift run AIMeterSnapshot providers.png --providers
swift run AIMeterSnapshot provider-recovery.png --providers --provider-recovery
swift run AIMeterSnapshot about.png --about
swift run AIMeterSnapshot menubar.png --menubar
swift run AIMeterSnapshot first-run.png --first-run
swift run AIMeterSnapshot scanning.png --scanning
swift run AIMeterSnapshot setup-needed.png --setup-needed
swift run AIMeterSnapshot partial.png --partial
swift run AIMeterSnapshot low.png --low
swift run AIMeterSnapshot error.png --errorThe state flags cover first run, active discovery, setup and provider recovery,
partial provider availability, a low-quota warning, and a provider read error.
Quota percentages in these fixtures and in the app are always labeled as usage
(% used); local token totals separately name their measurement window (for
example, 24h local window).
Release artifacts are universal (arm64 and x86_64). When Developer ID and
notarization credentials are available, create signed, hardened, notarized, and
stapled artifacts with:
APP_SIGN_IDENTITY="Developer ID Application: Example (TEAMID)" \
INSTALLER_SIGN_IDENTITY="Developer ID Installer: Example (TEAMID)" \
NOTARY_PROFILE="ai-meter-release" \
./scripts/package_release.shVersion and build metadata live in Config/version.env. The tag-triggered
GitHub workflow uses the strict signed path when all Apple credentials are
configured. Until then, it explicitly falls back to an ad hoc-signed app and an
unsigned, unnotarized installer. Sparkle's EdDSA key remains mandatory in both
modes, so automatic updates reject modified archives. See
docs/releasing.md for the release procedure and trust
model; automation is defined in .github/workflows/release.yml.
Quit AI Meter, then remove /Applications/AI Meter.app, or run:
./scripts/uninstall_app.sh