Add Fable per-model weekly usage#19
Merged
Merged
Conversation
Switch OAuthUsageService from probing rate-limit response headers (via a throwaway POST /v1/messages) to the structured GET /api/oauth/usage endpoint. The header approach only exposed session and all-models limits; the usage endpoint returns a `limits` array that also carries per-model scoped weekly limits (e.g. Fable) with display names, and no longer burns a message token on every refresh. - Models: add ScopedUsageLimit and WebUsageData.scopedLimits - ContentView: render a card per scoped weekly limit (Fable now, any future model-scoped limit automatically) - Menu bar: add an optional "F" ring alongside S/W, gated by a new "Show Fable usage" setting; fix ring width to reserve space for every separator (was clipping the trailing ring with 3+ segments) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the app’s usage reporting to include per-model weekly limits (notably Fable) by switching OAuthUsageService from parsing rate-limit headers on /v1/messages to decoding structured usage data from GET /api/oauth/usage. It also adds UI support to display these scoped limits in the main view and optionally in the menu bar.
Changes:
- Replace rate-limit-header parsing with
GET /api/oauth/usageJSON decoding, including ISO8601 reset timestamp parsing and model-scoped weekly limits extraction. - Extend the data model and main UI to render a card per scoped weekly limit.
- Add a Settings toggle and menu bar “F” ring segment for Fable usage, including updated ring width calculation.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ClaudeCodeStats/ClaudeCodeStats/Views/SettingsView.swift | Adds a new “Show Fable usage” toggle persisted via @AppStorage. |
| ClaudeCodeStats/ClaudeCodeStats/Services/OAuthUsageService.swift | Switches to GET /api/oauth/usage and decodes session/weekly/scoped limits from JSON. |
| ClaudeCodeStats/ClaudeCodeStats/Models.swift | Introduces ScopedUsageLimit and adds scopedLimits to WebUsageData. |
| ClaudeCodeStats/ClaudeCodeStats/ContentView.swift | Renders additional usage cards for each scoped weekly limit. |
| ClaudeCodeStats/ClaudeCodeStats/ClaudeCodeStatsApp.swift | Adds optional “F” ring segment and fixes menu bar ring width measurement for multiple segments. |
| CLAUDE.md | Updates architecture documentation to reflect the new usage endpoint and scoped limits. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
252
to
+256
| return WebUsageData( | ||
| sessionUsage: sessionUtilization * 100, | ||
| sessionResetsAt: sessionReset ?? Date(), | ||
| weeklyUsage: weeklyUtilization * 100, | ||
| weeklyResetsAt: weeklyReset ?? Date(), | ||
| sessionUsage: decoded.fiveHour?.utilization ?? 0, | ||
| sessionResetsAt: parseDate(decoded.fiveHour?.resetsAt) ?? Date(), | ||
| weeklyUsage: decoded.sevenDay?.utilization ?? 0, | ||
| weeklyResetsAt: parseDate(decoded.sevenDay?.resetsAt) ?? Date(), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds Fable-specific weekly usage to the app, matching the new Fable limit that claude.ai now shows on its Usage page (alongside "Current session" and "All models").
How
The old
OAuthUsageServicePOSTed a throwaway"hi"message to/v1/messagespurely to readanthropic-ratelimit-*response headers — and those headers only expose the session (5h) and all-models (7d) limits, never Fable.This switches to the structured
GET /api/oauth/usageendpoint (the same one claude.ai's Usage page uses). It returns alimitsarray that includes per-modelweekly_scopedentries carrying a display name (Fable), and as a bonus no longer consumes a message token on every refresh.Changes
OAuthUsageService— fetch +Codable-decodeGET /api/oauth/usageinstead of parsing rate-limit headers. All existing behavior preserved: token file/Keychain lookup + caching, 401/403 →tokenExpired, transient-network retry. ISO8601 reset timestamps (microsecond precision) parsed with a fractional-seconds formatter.Models— newScopedUsageLimit { name, usage, resetsAt }andWebUsageData.scopedLimits.ContentView— renders a card per scoped weekly limit, so Weekly Limit (Fable) appears now and any future model-scoped limit shows up automatically.CLAUDE.md— updated the now-stale architecture note describingOAuthUsageService.Testing
Codableparse against the live endpoint: producesCurrent Session,Weekly Limit (All Models) 59%, andWeekly Limit (Fable) 69%— matching claude.ai.🤖 Generated with Claude Code