Native macOS menu-bar app for tracking Claude Code usage and Anthropic service status.
- Subscription usage from
~/.claude/claudewatch-usage.json, written by the Claude Code statusline hook. - Claude Code service health from
https://status.claude.com/api/v2/components.json. - Color-coded uptime history bar (30/60/90 days) sourced from incident data and the official status page.
- 26-week usage-history heatmap with session/streak/peak stats, approximated from local Claude Code usage observed while ClaudeWatch is running (Anthropic does not expose historical usage, so nothing before you started using ClaudeWatch is available), backed by a local event log retained indefinitely.
- Pay-as-you-go "extra usage" tracking: when enabled on your account, see monthly credits used vs. limit with a dedicated progress bar.
- Customizable progress bar colors with dynamic, status-matching, and preset options.
- Real-time relative timestamps with absolute tooltips on hover.
- macOS 14 Sonoma+, Swift 5+/SwiftUI, sandboxed, zero external dependencies.
# One-time: point xcode-select at the full Xcode install if needed.
sudo xcode-select -s /Applications/Xcode.app
sudo xcodebuild -license accept
xcodebuild -runFirstLaunch
# Build the app:
xcodebuild -project ClaudeWatch.xcodeproj -scheme ClaudeWatch -configuration Debug build
# Run unit tests:
xcodebuild -project ClaudeWatch.xcodeproj -scheme ClaudeWatch test \
-destination 'platform=macOS'Or just open ClaudeWatch.xcodeproj in Xcode and Cmd-R.
After building, the .app is under ~/Library/Developer/Xcode/DerivedData/....
Launch it; a small percentage indicator appears in the menu bar. Click it (or
press ⌘⌥C) to show the popover.
ClaudeWatch reads usage from ~/.claude/claudewatch-usage.json. This file is
written by a Claude Code statusline hook — ClaudeWatch itself never calls the
Anthropic API. Usage data is only updated while Claude Code is actively being
used in the terminal; ClaudeWatch has no way to fetch it independently.
The included statusline.sh script is a Claude Code
statusline
hook that serves two purposes:
- Feeds ClaudeWatch — each time the statusline renders, the script writes
the latest usage data to
~/.claude/claudewatch-usage.json. - Enriches your terminal — the statusline itself displays the current model, context-window token usage, reasoning effort, 5-hour and 7-day rate limit percentages, and live Claude Code service status.
The easiest way to install is with the included install script, which copies
the statusline into place, checks that jq is installed, and configures
~/.claude/settings.json for you:
./install-statusline.shRe-run ./install-statusline.sh after every git pull to copy the latest
statusline.sh into ~/.claude/ — updates to the script in this repo don't
take effect until it's reinstalled.
Or install manually:
cp statusline.sh ~/.claude/statusline.sh
chmod +x ~/.claude/statusline.shThen add (or merge) the statusLine entry in your Claude Code settings
(~/.claude/settings.json):
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}The next time you start a Claude Code session in the terminal, the statusline will appear and ClaudeWatch will begin receiving usage updates. If ClaudeWatch shows stale data, it means no terminal session has run since the last update.
{
"five_hour": {
"used_percentage": 38.0,
"resets_at": 1713100000
},
"seven_day": {
"used_percentage": 8.0,
"resets_at": 1713500000
},
"extra_usage": {
"is_enabled": true,
"used_percentage": 53.24,
"used_credits": 2662,
"monthly_limit": 5000
},
"updated_at": 1713099000
}| Field | Required | Description |
|---|---|---|
five_hour.used_percentage |
yes | 0–100, current 5-hour session usage |
five_hour.resets_at |
no | Unix epoch when the session window resets |
seven_day.used_percentage |
yes | 0–100, weekly usage across all models |
seven_day.resets_at |
no | Unix epoch when the weekly window resets |
extra_usage.is_enabled |
no | true if the account has pay-as-you-go extra credits enabled |
extra_usage.used_percentage |
no | 0–100, share of the monthly credit limit consumed |
extra_usage.used_credits |
no | USD cents consumed this month |
extra_usage.monthly_limit |
no | USD cents allowed per month |
updated_at |
no | Unix epoch when the file was last written |
The Extra usage section only renders when is_enabled is true and all three
numeric fields are present. Credits are in cents (divide by 100 for dollars).
This is the shape the bundled statusline.sh writes today.
For clients that want to surface multiple weekly buckets (e.g. per-model
limits), a "weekly" array can be provided instead of "seven_day". When
present, it takes precedence.
"weekly": [
{ "label": "All models", "used_percentage": 8.0, "resets_at": 1713500000 },
{ "label": "Sonnet only", "used_percentage": 5.0, "resets_at": 1713600000 }
]| Field | Required | Description |
|---|---|---|
weekly[].label |
yes | Display name (e.g. "All models", "Sonnet only") |
weekly[].used_percentage |
yes | 0–100, weekly usage for this bucket |
weekly[].resets_at |
no | Unix epoch when this weekly window resets |
ClaudeWatch/
App/ ClaudeWatchApp, AppDelegate, Info.plist, entitlements
Models/ Severity, QuotaState, StatusState, Preferences, UptimeHistory,
UsageHistoryEvent, UsageHistoryStats
Services/ Quota file reader, status HTTP, uptime client, usage history store,
notifications, Carbon hotkey
Coordinator/ AppCoordinator (timers, wake observer, threshold detection, history recording)
UI/ MenuBarLabel, PopoverRoot, Usage/Status/Uptime/UsageHistory/Settings sections,
HotkeyRecorder
ClaudeWatchTests/
QuotaSyncClientTests, StatusClientTests, MockURLProtocol
All preferences live in UserDefaults (see Models/Preferences.swift) and are
editable from the popover's Settings section. Changes take effect immediately.
| Setting | Default | Options |
|---|---|---|
| Show Claude Code status | Always | Always, Only when not operational, Off |
| Show 5h usage % | on | on/off |
| Usage graphic | None | None, Mini bar, Ring gauge, Logo fill, Segmented dots, Arc gauge |
| Setting | Default | Options |
|---|---|---|
| Menu bar graphic | Dynamic | Dynamic, Monochrome, Match status color, Blue, Indigo, Purple, Teal, Mint, Pink |
| Usage bars | Dynamic | Dynamic, Match status color, Blue, Indigo, Purple, Teal, Mint, Pink |
Menu bar graphic controls the color of the usage graphic in the menu bar (mini bar, ring, etc.). Usage bars controls the popover progress bars. Both are configured independently. "Dynamic" uses the system primary color (black in light mode, white in dark mode) and shifts through yellow/orange/red as usage climbs. "Monochrome" also uses the primary color but stays flat. Preset colors stay fixed. "Match status color" uses the current Claude Code service health color. The menu bar percentage text always uses dynamic coloring for readability.
Per-severity macOS notifications when Claude Code service status changes.
| Severity | Default |
|---|---|
| Recovered | on |
| Degraded / maintenance | on |
| Partial outage | on |
| Major outage | on |
| Setting | Default | Options |
|---|---|---|
| Session renewal | Off | Off, Always, When exhausted |
| Setting | Default | Options |
|---|---|---|
| Uptime history | 30 days | Off, 30 days, 60 days, 90 days |
Shows a color-coded daily uptime bar for Claude Code below the status indicator. Daily severity is computed from incident data; the 90-day uptime percentage is scraped from the official status page.
| Setting | Default | Options |
|---|---|---|
| Usage history | Chart and stats | Off, Chart only, Chart and stats |
Records every 5-hour session (start, usage bumps, end) to a JSON event
log in the app's sandboxed Application Support directory. Events are retained
indefinitely. The popover shows a 26-week (182-day) calendar heatmap keyed
by total daily usage (sum of each session's peak %), tinted to match the
Usage-bars color preference. Hovering a cell surfaces that day's
session count and total usage.
When "Chart and stats" is selected, a 3×2 stat grid (Sessions, Active days,
Avg/Max peak, Current/Longest streak) and a 7d / 30d / All segmented
picker appear above the heatmap. The duration picker only filters the
stats — the heatmap always shows the full 26-week window, and All
covers every retained event.
| Setting | Default | Options |
|---|---|---|
| Extra usage | Only when used | Off, Only when used, Always |
When your account has pay-as-you-go credits enabled, a dedicated section
below the usage limits shows the month-to-date spend ($X.XX of $Y.YY),
the percent used, and a progress bar tinted with the Usage-bars color.
"Only when used" hides the section until any credits have been consumed;
"Always" shows it whenever the account has extra usage enabled (even at
$0); "Off" hides it entirely. Extra usage data only populates when the
statusline can reach the Claude /oauth/usage API, since Claude Code's
inline rate_limits input doesn't include it.
To populate the heatmap without waiting for real sessions, run:
./seed-usage-history.sh # 365 days of synthetic history
./seed-usage-history.sh --days 90 # custom window
./seed-usage-history.sh --clear # wipe all eventsThe script writes directly to the app's sandboxed Application Support directory. Reopen the popover (or relaunch the app) to pick up changes.
| Setting | Default | Range | Step |
|---|---|---|---|
| Usage polling | 30 s | 10–300 | 10 |
| Claude status polling | 300 s | 300–900 | 60 |
| Setting | Default |
|---|---|
| Toggle popover | ⌘⌥C (rebindable) |
The bundled statusline.sh is derived from
ClaudeCodeStatusLine
by @daniel3303, used under its MIT
license. Modifications: write resolved usage data to
~/.claude/claudewatch-usage.json on every render so ClaudeWatch can
read it; removed the upstream self-update check. See the file header
and the upstream LICENSE
for the original copyright and permission notice.

