Skip to content

zachisparanoid/watch-your-usage

Repository files navigation

Claude Usage — Wear OS

/usage from Claude Code, on your Samsung Galaxy Watch 7 (or any Wear OS 3+ device). A glance-able utilization meter for your Claude Pro/Max subscription that also predicts when you'll hit the cap and pokes you when you cross a threshold.

What you get

On the watch

  • Main app — 5-hour arc with reset countdown, 24-hour sparkline, burn-rate prediction ("→ 100% in 1h 47m"), weekly Sonnet & Opus bars, refresh button.
  • Two Tiles — Claude Usage (5-hour primary) and Claude Weekly (Sonnet + Opus).
  • Complications — RANGED_VALUE, SHORT_TEXT, and LONG_TEXT variants.
  • Ambient-mode rendering — drops to monochrome single percentage when the display dims.
  • Threshold notifications — wrist-tap when you cross your configured warn/urgent percentages, plus a reset notification when fresh quota lands.

On the phone

  • Dashboard — same 5-hour arc + sparkline + burn-rate + weekly view.
  • Sign-in flow — Chrome Custom Tab → paste OAuth code → token automatically syncs to watch via the Wearable Data Layer.
  • Clipboard auto-capture — when you return to the app, it offers to use the code you just copied.
  • Settings — tunable warn/urgent thresholds for both windows, refresh interval (15/30/60/120 min), quiet hours, reset-notification toggle.
  • Diagnostics — copy-to-clipboard troubleshooting report with token expiry, last error, history sample.

Architecture

shared/    Kotlin library: OAuth client, /api/oauth/usage client, history,
           burn-rate analysis, threshold-bucketing, settings model
mobile/    phone — OAuth + dashboard + settings + diagnostics + token push
wear/      watch — main screen, two Tiles, three Complication types, ambient
           mode, threshold notifier, periodic refresh worker

After first pairing the watch operates standalone: it makes its own API calls to api.anthropic.com, refreshes its own access tokens, persists history, and posts its own notifications. The phone is only needed again if the refresh token ever fails or you sign out.

Design docs:

Build

./gradlew assembleDebug
# Outputs:
#   mobile/build/outputs/apk/debug/mobile-debug.apk
#   wear/build/outputs/apk/debug/wear-debug.apk
./gradlew :shared:testDebugUnitTest   # 23 JVM unit tests
./gradlew :mobile:lintDebug :wear:lintDebug

Install

Phone:

adb connect <phone-ip>:<port>
adb -s <phone-ip>:<port> install -r mobile/build/outputs/apk/debug/mobile-debug.apk

Watch (Galaxy Watch 7, ADB over WiFi enabled in Developer options):

adb connect <watch-ip>:<port>
adb -s <watch-ip>:<port> install -r wear/build/outputs/apk/debug/wear-debug.apk

Both APKs share applicationId=com.skyline.claudeusage and are signed with the standard Android debug key — required for Wearable Data Layer messages to pass between them.

First-time sign-in

  1. Open Claude Usage on the phone, tap Sign in.
  2. A Chrome Custom Tab opens claude.ai's OAuth page. Log in with your Pro/Max account.
  3. Tap Authorize on the consent screen. The callback page displays a code#state string. Copy it.
  4. Return to the phone app. It auto-detects the clipboard match and offers a one-tap "Use clipboard". Tap Finish sign-in.
  5. The phone exchanges the code for tokens and ships them to the watch via the Wearable Data Layer.
  6. Open Claude Usage on the watch — it fetches your usage within a few seconds. Long-press a watchface to add the Tile or Complication.

OAuth values (Claude.ai third-party flow)

These are the values that work for third-party clients of the Claude Code OAuth flow — verified across multiple OSS reimplementations and on the authoritative reference at akashmohan.com/writings/claude-code-oauth. Captured in KtorPairingApi.kt:

CLIENT_ID            = 9d1c250a-e61b-44d9-88ed-5944d1962f5e
AUTHORIZE_URL        = https://claude.ai/oauth/authorize
TOKEN_URL            = https://console.anthropic.com/v1/oauth/token  (JSON body)
MANUAL_REDIRECT_URI  = https://console.anthropic.com/oauth/code/callback
SCOPES               = org:create_api_key user:profile user:inference

Notable quirks of this flow versus standard OAuth 2.0:

  • Authorize URL must include a code=true sentinel query param.
  • Token exchange POSTs JSON (not form-encoded), and includes a state field in the body.
  • The returned authorization code on the callback page is formatted as <code>#<state> — split on # and pass the right half as state in token exchange.
  • Only the 3-scope set above is allow-listed for third-party clients. The 5-scope set Claude Code itself uses (with user:file_upload, user:mcp_servers, user:sessions:claude_code) will get past the consent screen but fail with "Authorization failed: Invalid request format" when the server tries to issue the code.

Settings reference

Defaults are conservative for a Max subscriber:

Setting Default Range
5-hour warn 80% 50–98%
5-hour urgent 95% warn+1 – 100%
Weekly warn 80% 50–98%
Weekly urgent 95% warn+1 – 100%
Notify on reset on on/off
Quiet hours 22:00–07:00 any 0–23 / any 0–23
Refresh interval 15 min 15 / 30 / 60 / 120 min

The RefreshUsageScheduler listens for changes and reschedules the WorkManager periodic worker live; you don't have to restart the watch app after changing refresh interval.

Notifications

Two channels:

  • usage_warningsIMPORTANCE_HIGH. Fires once per upward bucket crossing per window (none → warn → urgent → full). State is per-window and reset by the server's resets_at advance.
  • usage_resetsIMPORTANCE_DEFAULT. Fires when a window's resets_at advances (i.e. fresh quota landed).

During quiet hours, threshold events are suppressed and not state-advanced — so they fire on the first refresh after quiet hours end.

Notifications respect POST_NOTIFICATIONS (API 33+); the wear app declares the permission and silently skips posting if it's not granted.

About

An app that lets you view your current claude subscription usage on either your Android phone or watch.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages