feat: local Claude 5H/7D usage when disconnected + branded DMG installer#18
Conversation
Show last 5H/7D token counts and equivalent cost on the Claude tab from local ~/.claude logs (ccusage-style), so the tab is useful before you Connect. Connecting still adds the live limit %. The release .dmg now opens to a branded, retina drag-to-Applications window (rendered by a new dmgbggen tool as a multi-rep TIFF). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe PR adds local Claude 5H/7D token and cost metrics, displays them when live usage is unavailable, and documents the behavior. It also adds a Swift-based branded DMG background generator and integrates it into the macOS release workflow. ChangesClaude local usage
Branded DMG packaging
Repository housekeeping
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ClaudeLogs
participant ClaudeCostReader
participant CostSummary
participant ProviderDetailView
ClaudeLogs->>ClaudeCostReader: read local session entries
ClaudeCostReader->>ClaudeCostReader: aggregate 5H and 7D totals
ClaudeCostReader->>CostSummary: populate rolling usage fields
CostSummary->>ProviderDetailView: provide local tokens and USD
ProviderDetailView-->>ProviderDetailView: render LocalUsageRows
sequenceDiagram
participant ReleaseWorkflow
participant dmgbggen
participant create_dmg
ReleaseWorkflow->>dmgbggen: generate dmg-background.tiff
dmgbggen-->>ReleaseWorkflow: write retina TIFF
ReleaseWorkflow->>create_dmg: package app with background TIFF
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/AIUsageBarUI/ProviderDetailView.swift`:
- Around line 234-263: Update LocalUsageRows.usageRow so the USD value uses the
provided accent color for its foreground style instead of
Theme.modelColor("Opus"), ensuring local-usage totals match the caller-supplied
account accent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 896b273b-a6ae-4f68-8318-e9a2b8e14970
📒 Files selected for processing (10)
.github/workflows/release.yml.gitignoreCHANGELOG.mdPackage.swiftREADME.mdSources/AIUsageBarCore/Claude/ClaudeCostReader.swiftSources/AIUsageBarCore/Models.swiftSources/AIUsageBarUI/ProviderDetailView.swiftSources/dmgbggen/main.swiftTests/AIUsageBarCoreTests/CoreTests.swift
| /// ccusage-style local usage windows (5H / 7D) derived from the logs — token | ||
| /// volume + equivalent cost, no live quota %. Shown when a Claude account isn't | ||
| /// connected, so it stays useful without any Keychain access. | ||
| struct LocalUsageRows: View { | ||
| let cost: CostSummary | ||
| let accent: Color | ||
|
|
||
| var body: some View { | ||
| VStack(alignment: .leading, spacing: 8) { | ||
| usageRow("5H", tokens: cost.last5hTokens, usd: cost.last5hUSD) | ||
| usageRow("7D", tokens: cost.last7dTokens, usd: cost.last7dUSD) | ||
| Text("Local activity from your logs — Connect for the live limit %.") | ||
| .font(.caption2).foregroundStyle(.tertiary) | ||
| } | ||
| } | ||
|
|
||
| private func usageRow(_ label: String, tokens: Int, usd: Double) -> some View { | ||
| HStack(spacing: 10) { | ||
| Text(label).font(.system(size: 12, weight: .semibold)) | ||
| .frame(width: 32, alignment: .leading) | ||
| Text("\(Theme.compactTokens(tokens) ?? "0") tok") | ||
| .font(.system(size: 12).monospacedDigit()).foregroundStyle(.secondary) | ||
| Spacer(minLength: 6) | ||
| Text(Theme.usd(usd)) | ||
| .font(.system(size: 12, weight: .medium).monospacedDigit()) | ||
| .foregroundStyle(Theme.modelColor("Opus")) | ||
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use the provided accent color instead of hardcoding "Opus".
The LocalUsageRows struct receives the account's accent color from the caller, but the property goes unused because the USD value's foreground style is hardcoded to Theme.modelColor("Opus"). This forces the local-usage totals to render in purple instead of matching the account's accent color.
🎨 Proposed fix
- .foregroundStyle(Theme.modelColor("Opus"))
+ .foregroundStyle(accent)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// ccusage-style local usage windows (5H / 7D) derived from the logs — token | |
| /// volume + equivalent cost, no live quota %. Shown when a Claude account isn't | |
| /// connected, so it stays useful without any Keychain access. | |
| struct LocalUsageRows: View { | |
| let cost: CostSummary | |
| let accent: Color | |
| var body: some View { | |
| VStack(alignment: .leading, spacing: 8) { | |
| usageRow("5H", tokens: cost.last5hTokens, usd: cost.last5hUSD) | |
| usageRow("7D", tokens: cost.last7dTokens, usd: cost.last7dUSD) | |
| Text("Local activity from your logs — Connect for the live limit %.") | |
| .font(.caption2).foregroundStyle(.tertiary) | |
| } | |
| } | |
| private func usageRow(_ label: String, tokens: Int, usd: Double) -> some View { | |
| HStack(spacing: 10) { | |
| Text(label).font(.system(size: 12, weight: .semibold)) | |
| .frame(width: 32, alignment: .leading) | |
| Text("\(Theme.compactTokens(tokens) ?? "0") tok") | |
| .font(.system(size: 12).monospacedDigit()).foregroundStyle(.secondary) | |
| Spacer(minLength: 6) | |
| Text(Theme.usd(usd)) | |
| .font(.system(size: 12, weight: .medium).monospacedDigit()) | |
| .foregroundStyle(Theme.modelColor("Opus")) | |
| } | |
| } | |
| } | |
| /// ccusage-style local usage windows (5H / 7D) derived from the logs — token | |
| /// volume + equivalent cost, no live quota %. Shown when a Claude account isn't | |
| /// connected, so it stays useful without any Keychain access. | |
| struct LocalUsageRows: View { | |
| let cost: CostSummary | |
| let accent: Color | |
| var body: some View { | |
| VStack(alignment: .leading, spacing: 8) { | |
| usageRow("5H", tokens: cost.last5hTokens, usd: cost.last5hUSD) | |
| usageRow("7D", tokens: cost.last7dTokens, usd: cost.last7dUSD) | |
| Text("Local activity from your logs — Connect for the live limit %.") | |
| .font(.caption2).foregroundStyle(.tertiary) | |
| } | |
| } | |
| private func usageRow(_ label: String, tokens: Int, usd: Double) -> some View { | |
| HStack(spacing: 10) { | |
| Text(label).font(.system(size: 12, weight: .semibold)) | |
| .frame(width: 32, alignment: .leading) | |
| Text("\(Theme.compactTokens(tokens) ?? "0") tok") | |
| .font(.system(size: 12).monospacedDigit()).foregroundStyle(.secondary) | |
| Spacer(minLength: 6) | |
| Text(Theme.usd(usd)) | |
| .font(.system(size: 12, weight: .medium).monospacedDigit()) | |
| .foregroundStyle(accent) | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Sources/AIUsageBarUI/ProviderDetailView.swift` around lines 234 - 263, Update
LocalUsageRows.usageRow so the USD value uses the provided accent color for its
foreground style instead of Theme.modelColor("Opus"), ensuring local-usage
totals match the caller-supplied account accent.
What
Two things for v0.1.6:
Local Claude usage without connecting
The Claude tab now shows your last 5H / 7D token counts and equivalent cost, derived entirely from local
~/.claudelogs (ccusage-style), so the tab is useful before you ever click Connect. Connecting still adds the live limit % from Claude's usage endpoint.CostSummarygainslast5hTokens/USD,last7dTokens/USD(accumulated inClaudeCostReader, cache signature bumped to v5)ProviderDetailViewshowsLocalUsageRowsin the disconnected state when there's local activityBranded DMG installer
The release
.dmgnow opens to a branded window — app icon, purple drag-to-Applications arrow, name + tagline — rendered at retina resolution.dmgbggentool renders a multi-representation TIFF (540×380 @1x + 1080×760 @2x in one file); create-dmg has no @2x support but Finder resolves the right rep per displayrelease.ymlrenders the background and passes it to create-dmg, with the plain-symlink fallback intactTest
swift testgreen (added 5H/7D assertions to the cost-reader test)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Bug Fixes