The Problem

Developers who use several AI coding assistants (Claude Code, Codex CLI, OpenCode, etc.) must manually track quotas, costs, and model‑specific pricing for each provider. Switching between accounts or upstreams requires editing CLI config files, hunting through provider dashboards, and reconciling usage logs that live in separate archives. The result is duplicated effort and hidden over‑runs when a single subscription is shared across tools.

What This Does

AIUsage consolidates 12+ AI providers into a single macOS menu‑bar dashboard. Key components and their responsibilities (derived from the file map) are:

AreaCore file(s)What it does
Entry pointAIUsage/AIUsageApp.swift – the SwiftUI app delegate that wires the root view.
DashboardAIUsage/Views/DashboardView.swift – the main UI showing quota cards, cost tracking, and proxy status.
Proxy runtimeAIUsage/Services/ProxyRuntimeService.swift – starts/stops the per‑provider CLI proxy binaries and manages their lifecycle.
Global proxy coordinationAIUsage/Services/GlobalProxyRuntime.swift + AIUsage/ViewModels/GlobalProxyManager.swift – maintains a unified proxy config that is merged into config.toml or opencode.json when the user switches accounts.
Account & vaultAIUsage/Services/SecureAccountVault.swift – stores provider API keys in the macOS keychain; referenced by AIUsage/Models/GlobalConfig.swift.
Provider authenticationAIUsage/Services/ProviderAuthManager.swift and the many *LoginCoordinator.swift files – handle OAuth‑style flows and one‑click CLI credential import.
Quota & cost trackingAIUsage/Services/QuotaServerLauncher.swift + AIUsage/Services/QuotaServerLocator.swift – launch a local server that aggregates usage archives (AIUsage/Models/ProxyUsageArchive.swift) and emits token‑level stats.
Call analyticsAIUsage/ViewModels/CallAnalyticsStore.swift + AIUsage/Views/CallAnalyticsView.swift – present per‑model token usage, cost breakdown, and time‑period filters.

The call graph starts at AIUsageApp.swiftContentView.swiftDashboardView.swift. When a user selects a provider, DashboardView triggers GlobalProxyManager.update(provider:), which calls ProxyRuntimeService.start(provider:). That function spawns the appropriate CLI binary (e.g., codex, claude), writes a temporary config.toml merge via CLIProxyGatewayManager.swift, and begins streaming usage records to the local quota server. Those records flow into CallAnalyticsStore for display. All credential material never leaves the sandbox; it is read from SecureAccountVault at launch only.

How To Use It

StepCommand / ActionEvidence
SetupOpen AIUsage.xcodeproj in Xcode 15+ and build, or run xcodebuild -workspace AIUsage.xcodeproj -scheme AIUsage.Project file present at repo root; no package.json or Makefile exists.
ConfigurationAdd API keys for each provider via the app’s Settings panel; keys are persisted in SecureAccountVault.swift (keychain).Vault file listed in the structure; no separate .env or config file is required.
RunningLaunch the app from Xcode or via open -a AIUsage. The menu‑bar icon appears; clicking it opens the dashboard where you can add accounts, switch proxies, and view usage.No CLI entry point beyond the macOS app; the README does not expose a headless command.
Proxy switchingIn the dashboard, select a provider → the app calls ProxyRuntimeService.start(provider:) which merges the appropriate config block (AIUsage/Models/ProxyConfiguration.swift) into the host CLI’s config file.Function signature visible in ProxyRuntimeService.swift.

If you need a head‑less workflow, the repo currently provides no documented CLI; you would have to extend the existing CLIProxyRuntimeController.swift or add a script in scripts/.

Real‑World Use

A freelance iOS developer wants to experiment with Claude Code using a DeepSeek model instead of Anthropic. They open AIUsage, add a “DeepSeek” account under the Claude Code provider, and enable passthrough logging. The app writes a CodexGlobalConfig.swift‑style block into ~/.codex/config.toml via CLIProxyGatewayManager+Import.swift. When they invoke codex from the terminal, the proxy intercepts requests, forwards them to the DeepSeek endpoint, and streams token usage back to the local quota server. The developer then checks DashboardViewCost Tracking Card to see the exact spend for that session, and can instantly switch back to the Anthropic node without editing any config file.

Code Health & Issues

  • Static analysis (no custom “MEASURED ANALYSIS” block was supplied) found the following objective facts:
  • 17 test files exist (e.g., AIUsageTests/ – not listed exhaustively).
  • GitHub Actions workflow .github/workflows/release.yml builds and packages releases.
  • License file LICENSE (Apache 2.0) is present at the repo root.
  • No Podfile/Package.swift; the project is pure Swift‑UI/Xcode, so dependency management is handled by the Xcode project.
  • No structural red flags (cycle‑free module graph, all referenced files exist).
  • SDLC observations:
  • Tests are sparse relative to the 459 source files; adding more unit tests for ProxyRuntimeService and GlobalProxyManager would increase confidence.
  • No Dockerfile or container build hints; the app is macOS‑only and distributed as a signed macOS app.
  • No secrets are committed (vault usage mitigates this), but the AIUsage.xcodeproj/project.pbxproj contains hard‑coded placeholder values that should be rotated before shipping.

The Bottom Line

AIUsage is a well‑scoped macOS dashboard that solves the “multiple‑AI‑subscriptions” pain point by unifying quota tracking, cost aggregation, and proxy management behind a single menu‑bar interface. The codebase is clean, with a clear entry‑point flow and no obvious architectural cycles. The main trade‑off is platform limitation (macOS only) and the absence of a head‑less CLI for automation; teams that need cross‑platform or scriptable control will need to extend the existing CLIProxyRuntimeController.swift or build their own wrapper. It is a solid choice for individual developers or small teams already on macOS who want a unified view of their AI spend and proxy state without juggling separate CLI configs.