2 <img src="UsageMenubar/Assets.xcassets/AppIcon.appiconset/icon-1024.png" width="128" height="128" alt="Usage Menubar app icon">
7A macOS menu bar application that displays usage limits and credit balances for multiple LLM services: [Hyper (Charm)](https://hyper.charm.land), [Claude Code](https://claude.com/claude-code), and [z.ai](https://z.ai) Coding Plans. Each service is independent — configure the ones you use, ignore the ones you don't.
11- ⚡ **Hyper credits** — balance from `hyper.charm.land`, with sparkline trend, click-to-copy, and low-balance notifications
12- ⁕ **Claude Code limits** — Pro/Max 5-hour and 7-day usage windows, with countdown to next reset. No setup: if you've signed in with the Claude Code CLI, it just appears
13- Z **z.ai Coding Plan** — 5-hour and weekly token quota percentages, with reset countdowns. Enter your API key in settings
14- 🔄 **Auto-refresh** — configurable interval (1m / 5m / 15m / 30m), plus refresh on wake from sleep
15- 🖱️ **Right-click menu** — quick access to Refresh and Quit
16- 🔒 **Keychain storage** — API keys stored securely in macOS Keychain
17- 🚀 **Launch at login** — optional, using `SMAppService`
18- 🫥 **Agent app** — no dock icon, no main window; lives entirely in the menu bar
22Each service shows an emoji-prefixed segment when configured and above 0%:
24| Service | Emoji | Example |
25|---------|-------|---------|
26| Hyper balance | ⚡ | `⚡42` |
27| Claude 5-hour | ⁕ | `⁕62%` |
28| Claude 7-day | ⁕ | `⁕8%` |
29| z.ai 5-hour | Z | `Z12%` |
30| z.ai weekly | Z | `Z3%` |
32Unconfigured services don't appear at all — no placeholder, no icon.
36### Homebrew (recommended)
40brew install --cask usage-menubar
46brew install --cask ilyakooo0/tap/usage-menubar
49### Download the pre-built release
511. Go to the [Releases page](https://github.com/ilyakooo0/usage-menubar/releases)
522. Download the latest `UsageMenubar-*.zip`
533. Unzip and move `UsageMenubar.app` to `/Applications`
544. Launch the app — it will appear in your menu bar
56> **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.
60Click the menu bar icon to open the popover. Each service is configured independently:
641. Enter your Hyper API key (starts with `sk-...`) in the **Hyper API Key** field
663. Your balance appears immediately
68Get your key from [hyper.charm.land](https://hyper.charm.land).
70### Claude Code limits (no setup)
72If you use the [Claude Code CLI](https://claude.com/claude-code), 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.
74There 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.
76- **macOS will ask once.** Those credentials belong to Claude Code, not to this app, so the first read prompts you to allow access to the `Claude Code-credentials` Keychain item. Choose **Always Allow** and you won't be asked again.
77- **The credentials are strictly read-only.** The app reads the access token Claude Code stored and spends it as-is. It never refreshes it, and never writes those credentials back — that is the CLI's job alone. If the token has expired, the Claude section says so and asks you to run `claude`.
811. Enter your z.ai API key in the **z.ai API Key** field
833. Your 5-hour and weekly quota percentages appear immediately
85Get your key from [z.ai/manage-apikey](https://z.ai/manage-apikey/coding-plan/personal/my-plan).
89Everything is configured from the popover — click the menu bar icon.
91| Setting | Where | Notes |
92| ------------------- | ------------------------------ | ------------------------------------------------------------------------------------ |
93| **Hyper API key** | **Hyper API Key** field → **Save** | Stored in the macOS Keychain. Clearing the field and saving deletes the stored key. |
94| **z.ai API key** | **z.ai API Key** field → **Save** | Stored separately from the Hyper key. |
95| **Launch at login** | **Launch at Login** toggle | Registers the app with `SMAppService`. |
96| **Notifications** | System permission prompt | macOS asks on first launch (only if not already decided). Required for low-balance alerts. |
97| **Refresh now** | **Refresh** button | Forces an immediate fetch, on top of the automatic refresh. |
98| **Refresh interval**| **Refresh every** picker | Choose 1m, 5m, 15m, or 30m. Defaults to 5m. Stored in `UserDefaults` and persisted across launches. |
100The app also refreshes automatically when your Mac wakes from sleep.
106- macOS 14.0+ (Sonoma)
108- [xcodegen](https://github.com/yonaskolb/XcodeGen) (`brew install xcodegen`)
113# Clone the repository
114git clone https://github.com/ilyakooo0/usage-menubar.git
117# Generate the Xcode project
121open UsageMenubar.xcodeproj
123# Or build from the command line
125 -scheme UsageMenubar \
126 -configuration Release \
127 -archivePath build/UsageMenubar.xcarchive \
129 CODE_SIGNING_ALLOWED=NO
136 -scheme UsageMenubar \
137 -configuration Debug \
138 -destination "platform=macOS"
143Versions follow the format `YYYY.MM.DD.HHHH` where `HHHH` is the UTC hour and minute (24-hour).
145| Commit time (UTC) | Version |
146| ------------------------ | ----------------- |
147| 2026-07-09 14:23 | `2026.07.09.1423` |
148| 2026-01-01 00:00 | `2026.01.01.0000` |
149| 2026-12-31 23:59 | `2026.12.31.2359` |
151The version is derived automatically from the commit timestamp in the GitHub Actions release workflow.
157├── project.yml # xcodegen project definition
159│ ├── UsageMenubarApp.swift # @main App, NSStatusBar, timer, sleep/wake
160│ ├── ViewModel.swift # Observable state: balance, Claude usage, z.ai usage, refresh
161│ ├── MenuView.swift # SwiftUI popover view
162│ ├── CreditsChecker.swift # Hyper API client (GET /v1/credits)
163│ ├── ClaudeUsageClient.swift # Claude OAuth client (GET /api/oauth/usage) + models
164│ ├── ZaiUsageClient.swift # z.ai API client (GET /monitor/usage/quota/limit)
165│ ├── KeychainHelper.swift # Keychain wrapper (Hyper + z.ai keys)
166│ ├── VersionFormatter.swift # YYYY.MM.DD.HHHH formatting
167│ ├── Info.plist # LSUIElement=true (agent app)
168│ ├── UsageMenubar.entitlements # Network client; deliberately not sandboxed
169│ └── Assets.xcassets/ # App icon, accent color
170├── UsageMenubarTests/
171│ ├── CreditsCheckerTests.swift # Hyper API, retry, keychain, StubURLProtocol
172│ ├── ClaudeUsageClientTests.swift # Usage decoding, read-only credential store, retry
173│ ├── ZaiUsageClientTests.swift # z.ai API, retry, decoding
174│ ├── StatusBarTextTests.swift # Menu bar title formatting
175│ └── VersionFormatterTests.swift # Version formatting tests
176├── .github/workflows/
177│ └── release.yml # Build + release on push to master
1851. **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).
1862. **Popover**: Clicking the menu bar item shows an `NSPopover` containing a SwiftUI `MenuView` with each configured service's data and the settings.
1873. **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.
1884. **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>}`.
1895. **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.
1906. **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.
1917. **Keychain**: API keys are stored/retrieved via `KeychainHelper` using the macOS Security framework. Hyper and z.ai keys are stored separately.
1928. **Timer**: A `Timer` fires at the user-selected interval (1m / 5m / 15m / 30m, default 5m); the app also refreshes on wake from sleep.
1939. **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.
19410. **Agent app**: `LSUIElement=true` in `Info.plist` makes the app a background agent — no dock icon, no main window.
19511. **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.
199MIT — see [LICENSE](LICENSE).
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list