on master help sign in

⚡ macOS menu bar app showing your Hyper (Charm) credit balance

git clone https://git.iko.soy/usage-menubar.git

Usage Menubar app icon

UsageMenubar

A macOS menu bar application that displays usage limits and credit balances for multiple LLM services: Hyper (Charm), Claude Code, and z.ai Coding Plans. Each service is independent — configure the ones you use, ignore the ones you don't.

Features

Menu bar

Each service shows an emoji-prefixed segment when configured and above 0%:

ServiceEmojiExample
Hyper balance⚡⚡42
Claude 5-hour⁕⁕62%
Claude 7-day⁕⁕8%
z.ai 5-hourZZ12%
z.ai weeklyZZ3%

Unconfigured services don't appear at all — no placeholder, no icon.

Installation

brew tap ilyakooo0/tap
brew install --cask usage-menubar

Or in one command:

brew install --cask ilyakooo0/tap/usage-menubar

Download the pre-built release

  1. Go to the Releases page
  2. Download the latest UsageMenubar-*.zip
  3. Unzip and move UsageMenubar.app to /Applications
  4. Launch the app — it will appear in your menu bar

Note: Releases are ad-hoc signed — the CI build applies codesign -s - to the app, which gives it a stable code identity but is not an Apple Developer ID signature. macOS will still warn you on first launch: right-click the app → Open, or allow it in System Settings → Privacy & Security. Removing that prompt entirely requires a paid Developer ID certificate and notarization.

Setup

Click the menu bar icon to open the popover. Each service is configured independently:

Hyper credits

  1. Enter your Hyper API key (starts with sk-...) in the Hyper API Key field
  2. Click Save
  3. Your balance appears immediately

Get your key from hyper.charm.land.

Claude Code limits (no setup)

If you use the Claude Code CLI, the popover shows how much of your Pro/Max plan you have used: the 5-hour and 7-day windows, and how long until the next reset.

There is nothing to configure. The app reads the OAuth credentials Claude Code already stores when you run claude and sign in — first from its login-Keychain item, then from ~/.claude/.credentials.json if the Keychain has nothing. If neither exists, the Claude section doesn't appear.

z.ai Coding Plan

  1. Enter your z.ai API key in the z.ai API Key field
  2. Click Save
  3. Your 5-hour and weekly quota percentages appear immediately

Get your key from z.ai/manage-apikey.

Settings

Everything is configured from the popover — click the menu bar icon.

SettingWhereNotes
Hyper API keyHyper API Key field → SaveStored in the macOS Keychain. Clearing the field and saving deletes the stored key.
z.ai API keyz.ai API Key field → SaveStored separately from the Hyper key.
Launch at loginLaunch at Login toggleRegisters the app with SMAppService.
NotificationsSystem permission promptmacOS asks on first launch (only if not already decided). Required for low-balance alerts.
Refresh nowRefresh buttonForces an immediate fetch, on top of the automatic refresh.
Refresh intervalRefresh every pickerChoose 1m, 5m, 15m, or 30m. Defaults to 5m. Stored in UserDefaults and persisted across launches.

The app also refreshes automatically when your Mac wakes from sleep.

Build from source

Prerequisites

Steps

# Clone the repository
git clone https://github.com/ilyakooo0/usage-menubar.git
cd usage-menubar

# Generate the Xcode project
xcodegen generate

# Open in Xcode
open UsageMenubar.xcodeproj

# Or build from the command line
xcodebuild \
  -scheme UsageMenubar \
  -configuration Release \
  -archivePath build/UsageMenubar.xcarchive \
  archive \
  CODE_SIGNING_ALLOWED=NO

Run tests

xcodebuild test \
  -scheme UsageMenubar \
  -configuration Debug \
  -destination "platform=macOS"

Versioning

Versions follow the format YYYY.MM.DD.HHHH where HHHH is the UTC hour and minute (24-hour).

Commit time (UTC)Version
2026-07-09 14:232026.07.09.1423
2026-01-01 00:002026.01.01.0000
2026-12-31 23:592026.12.31.2359

The version is derived automatically from the commit timestamp in the GitHub Actions release workflow.

Project structure

usage-menubar/
├── project.yml                          # xcodegen project definition
├── UsageMenubar/
│   ├── UsageMenubarApp.swift            # @main App, NSStatusBar, timer, sleep/wake
│   ├── ViewModel.swift                  # Observable state: balance, Claude usage, z.ai usage, refresh
│   ├── MenuView.swift                   # SwiftUI popover view
│   ├── CreditsChecker.swift             # Hyper API client (GET /v1/credits)
│   ├── ClaudeUsageClient.swift          # Claude OAuth client (GET /api/oauth/usage) + models
│   ├── ZaiUsageClient.swift             # z.ai API client (GET /monitor/usage/quota/limit)
│   ├── KeychainHelper.swift             # Keychain wrapper (Hyper + z.ai keys)
│   ├── VersionFormatter.swift           # YYYY.MM.DD.HHHH formatting
│   ├── Info.plist                       # LSUIElement=true (agent app)
│   ├── UsageMenubar.entitlements        # Network client; deliberately not sandboxed
│   └── Assets.xcassets/                 # App icon, accent color
├── UsageMenubarTests/
│   ├── CreditsCheckerTests.swift        # Hyper API, retry, keychain, StubURLProtocol
│   ├── ClaudeUsageClientTests.swift     # Usage decoding, read-only credential store, retry
│   ├── ZaiUsageClientTests.swift        # z.ai API, retry, decoding
│   ├── StatusBarTextTests.swift         # Menu bar title formatting
│   └── VersionFormatterTests.swift      # Version formatting tests
├── .github/workflows/
│   └── release.yml                      # Build + release on push to master
├── README.md
├── LICENSE
└── .gitignore

How it works

  1. Menu bar item: The app creates an NSStatusItem with a variable-length button. Left-click toggles the popover; right-click opens a context menu (Refresh, Quit).
  2. Popover: Clicking the menu bar item shows an NSPopover containing a SwiftUI MenuView with each configured service's data and the settings.
  3. Independent fetches: ViewModel.refresh() runs the Hyper, Claude, and z.ai requests concurrently with async let. Any can fail, stall, or be unconfigured without affecting the others.
  4. Hyper API client: CreditsChecker performs GET https://hyper.charm.land/v1/credits with Authorization: Bearer <key>, retries transient failures with exponential backoff, and decodes {"balance": <int>}.
  5. Claude usage: ClaudeUsageClient reads Claude Code's OAuth credentials (its Claude Code-credentials Keychain item via /usr/bin/security, falling back to ~/.claude/.credentials.json) and fetches GET https://api.anthropic.com/api/oauth/usage. It is strictly read-only — it never refreshes the token and never writes credentials back. Missing credentials are reported as "not configured" rather than as an error, and the popover hides the section.
  6. z.ai usage: ZaiUsageClient fetches GET https://api.z.ai/api/monitor/usage/quota/limit and GET https://api.z.ai/api/biz/subscription/list concurrently with an API key the user enters in settings. Same retry pattern as the other clients.
  7. Keychain: API keys are stored/retrieved via KeychainHelper using the macOS Security framework. Hyper and z.ai keys are stored separately.
  8. Timer: A Timer fires at the user-selected interval (1m / 5m / 15m / 30m, default 5m); the app also refreshes on wake from sleep.
  9. Notifications: When the Hyper balance crosses below 10 credits — or is already below 10 on the first successful fetch — ViewModel posts a local UNUserNotification. Permission is requested only once.
  10. Agent app: LSUIElement=true in Info.plist makes the app a background agent — no dock icon, no main window.
  11. No sandbox: Reading credentials that belong to another app means spawning /usr/bin/security and reading a file in the user's home directory, neither of which the App Sandbox permits. The app is distributed ad-hoc signed via Homebrew rather than through the App Store, where the sandbox would be mandatory.

License

MIT — see LICENSE.