Skip to content

feat: account-driven Claude — user-named accounts, opt-in per-account cost#22

Merged
Balanced02 merged 1 commit into
mainfrom
feat/claude-accounts
Jul 23, 2026
Merged

feat: account-driven Claude — user-named accounts, opt-in per-account cost#22
Balanced02 merged 1 commit into
mainfrom
feat/claude-accounts

Conversation

@Balanced02

@Balanced02 Balanced02 commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Why

With our own OAuth (v0.2.0), the token already carries account identity — so scanning shell configs for CLAUDE_CONFIG_DIR to discover Claude "profiles" is redundant, and it caused a messy account model (worktree-ish names, mis-resolution).

What

Accounts are now exactly the OAuth sign-ins. Each has a user config: a name you set, and an optional logs-folder path. Cost + plan are opt-in per account — shown only when you point that account at a logs folder (there's no cost API; cost is derived from local ~/.claude JSONL, so each account attributes cost to its own dir). Type the path (tilde-expanded); blank = live limits only.

  • ClaudeReader is account-driven; UsageConfig/ProviderSettings carry claudeAccountConfigs keyed by account UUID.
  • Removed ManualClaudeProfile / auto-discovery (ClaudeProfileDiscovery kept for the usageprobe CLI only).
  • Settings → Claude: per-account editable name + typed Cost logs path + Remove; "Add account" (SSO).

Fixes (some found live, some by review)

  • Rate-limiting: config edits re-hit the usage endpoint → 429s. Fixed with a per-account usage cache (180s) + name/path fields that commit on blur, not per keystroke.
  • Rename bug: the name field pre-filled with the email → stored email-as-name. Email is now a placeholder, blank = default, name==email self-heals; apply(draft) preserves live account edits.
  • Removed the stale pre-OAuth "Copy sign-in command" hint.
  • Adversarial review (4 confirmed, all low, all addressed): gate the ~/.claude.json plan fallback to the default dir (no cross-account plan mislabel); serve last-good usage on a transient endpoint blip so % bars don't vanish (unauthorized still surfaces); resolve account UUID at sign-in so the config key stays stable.

Tests

  • swift test green (25). Verified live: add/name accounts, typed cost path shows $ + plan, rename persists across relaunch, no rate-limit on edits.
  • Privacy: scanned the full diff — no real emails/paths/UUIDs/domains/tokens; author identity is the pseudonym; guard hook passed.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Claude accounts are now managed through browser sign-in, with customizable account names.
    • Added optional per-account cost and token details from a selected local logs folder.
    • Account settings now support editable names and cost-log locations.
  • Bug Fixes

    • Updated names and log-folder changes refresh correctly without unnecessary usage requests.
    • Settings edits are saved when fields lose focus.
    • Removed the outdated sign-in hint.

… cost

Remove Claude path auto-discovery entirely. Accounts are now exactly the OAuth
sign-ins (Add account), each with a user config: a display name and an optional
logs-folder path. Cost + plan are opt-in per account — shown only when you point it
at a logs folder (no cost API exists; cost is local JSONL × pricing), so each account
attributes cost to its own dir. Type the path (tilde-expanded); blank = live-only.

ClaudeReader is now account-driven (iterates tokens, per-account name/live%/cost);
UsageConfig/ProviderSettings carry claudeAccountConfigs keyed by account UUID; the old
ManualClaudeProfile / discovery machinery is gone (ClaudeProfileDiscovery kept for the
usageprobe CLI only).

Fixes: config edits (rename/cost) were re-hitting the usage endpoint → rate-limits —
now a per-account usage cache (180s) plus name/path fields that commit on blur, not per
keystroke. The name field pre-filled with the email and stored email-as-name — email is
now a placeholder, blank = default, and a stored name==email self-heals. apply(draft)
preserves live account configs. Removed the stale pre-OAuth 'Copy sign-in command' hint.

From adversarial review: gate the ~/.claude.json plan fallback to the default dir (no
cross-account mislabel); serve last-good usage on a transient endpoint blip so % bars
don't vanish (unauthorized still surfaces); resolve the account UUID at sign-in so the
config key stays stable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d9595b0-fb1e-4cea-8f61-9717ee866e4a

📥 Commits

Reviewing files that changed from the base of the PR and between 784a3e5 and a3db9a9.

📒 Files selected for processing (17)
  • CHANGELOG.md
  • CLAUDE.md
  • README.md
  • Sources/AIUsageBarCore/Claude/ClaudeAccountConfig.swift
  • Sources/AIUsageBarCore/Claude/ClaudeCostReader.swift
  • Sources/AIUsageBarCore/Claude/ClaudeJSONLReader.swift
  • Sources/AIUsageBarCore/Claude/ClaudeProfile.swift
  • Sources/AIUsageBarCore/Claude/ClaudeReader.swift
  • Sources/AIUsageBarCore/Claude/ClaudeTokenProvider.swift
  • Sources/AIUsageBarCore/UsageService.swift
  • Sources/AIUsageBarUI/AppModel.swift
  • Sources/AIUsageBarUI/ProviderDetailView.swift
  • Sources/AIUsageBarUI/ProviderSettings.swift
  • Sources/AIUsageBarUI/SettingsView.swift
  • Sources/usageprobe/main.swift
  • Tests/AIUsageBarCoreTests/ClaudeOAuthTests.swift
  • Tests/AIUsageBarUITests/ProviderSettingsTests.swift

📝 Walkthrough

Walkthrough

Claude usage moved from discovered profiles to explicitly signed-in accounts with persisted names and optional local cost-log directories. Usage is cached per account, settings edits commit on blur, and the CLI reports local Claude cost summaries separately.

Changes

Claude account configuration

Layer / File(s) Summary
Account configuration contracts
Sources/AIUsageBarCore/Claude/*, Sources/AIUsageBarCore/UsageService.swift, Sources/AIUsageBarUI/ProviderSettings.swift, Tests/AIUsageBarCoreTests/*, Tests/AIUsageBarUITests/*
Introduces ClaudeAccountConfig, replaces profile-based settings with keyed account configurations, updates .claude.json loading, and revises persistence and configuration tests.
Per-account usage pipeline
Sources/AIUsageBarCore/Claude/ClaudeReader.swift, ClaudeTokenProvider.swift, ClaudeJSONLReader.swift, ClaudeCostReader.swift, Sources/AIUsageBarCore/UsageService.swift
Reads usage from signed-in account tokens, optionally derives activity and cost from configured logs, caches usage per account, and invalidates cache entries on sign-out.
Account management and settings UI
Sources/AIUsageBarUI/AppModel.swift, ProviderSettings.swift, SettingsView.swift, ProviderDetailView.swift
Persists account names and log directories, reconfigures and refreshes after account edits, commits fields on blur, and removes the stale sign-in hint.
CLI reporting changes
Sources/usageprobe/main.swift
Reports local 30-day Claude cost and token totals by discovered config directory while retaining OAuth-based live usage for the app.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SettingsView
  participant AppModel
  participant UsageService
  participant ClaudeReader
  participant ClaudeTokenProvider
  participant LocalLogs
  SettingsView->>AppModel: commit account name or logs directory
  AppModel->>UsageService: reconfigure account settings
  UsageService->>ClaudeReader: refresh configured accounts
  ClaudeReader->>ClaudeTokenProvider: request cached account usage
  ClaudeTokenProvider-->>ClaudeReader: live or cached usage
  ClaudeReader->>LocalLogs: read configured activity and cost logs
  LocalLogs-->>ClaudeReader: tokens, plan, and cost data
  ClaudeReader-->>UsageService: updated account card
Loading

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/claude-accounts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Balanced02
Balanced02 merged commit 16f4b74 into main Jul 23, 2026
1 of 2 checks passed
@Balanced02
Balanced02 deleted the feat/claude-accounts branch July 23, 2026 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant