How CodexBar Scans for Codex and Claude Cost Usage: A Technical Deep Dive

CodexBar aggregates cost and token usage data through a layered pipeline orchestrated by CostUsageFetcher, which validates providers, refreshes model pricing, executes heavy-weight log scans, and merges Pi session data to generate a unified CostUsageTokenSnapshot.

CodexBar is an open-source macOS menu bar application that monitors AI coding assistant costs in real time. The engine powering its cost tracking is CostUsageFetcher, a Swift class located in Sources/CodexBarCore/CostUsageFetcher.swift that systematically scans local log files, session caches, and Pi cost data to calculate spending for Codex, Claude, and other providers.

The Scanning Pipeline

Provider Validation and Time Window Configuration

The process begins in CostUsageFetcher.loadTokenSnapshot, which validates that the requested provider is one of .codex, .claude, .vertexai, or .bedrock. It calculates a since-until date range representing a 30-day rolling window by default (configurable via historyDays). This method is defined at lines 22-31 of CostUsageFetcher.swift.

Scanner Options and Cache Configuration

Before scanning, the method constructs a CostUsageScanner.Options instance. For Codex scans, this includes the explicit codexHomePath to locate the sessions folder; for Claude, it configures claudeLogProviderFilter appropriately. These options are initialized between lines 43-66 of CostUsageFetcher.swift.

Background Pricing Refresh

If the provider is Codex or Claude, ModelsDevPricingPipeline.refreshIfNeeded is invoked (lines 52-60) to ensure the latest per-model pricing is available. This runs either on a detached utility task or synchronously before the scan begins, guaranteeing that cost calculations use current rates.

Heavy-Weight Scan Execution

The CostUsageScanExecutor.run method bridges Swift concurrency cancellation into the synchronous scanner. Inside this closure, defined in CostUsageScanExecutor.swift, three main actions occur:

  • Load raw daily logs: CostUsageScanner.loadDailyReportCancellable reads the provider's log files or JSONL data for the calculated window.
  • Load Codex project caches: When the provider is Codex, CostUsageCacheIO.load reads pre-computed scan caches and feeds them to CostUsageScanner.buildCodexProjectBreakdownsFromCache.
  • Load Pi session cost data: For Codex and Claude, PiSessionCostScanner.loadDailyReportCancellable fetches session-level cost information (tokens and USD). The Pi report is merged with the raw daily report via CostUsageDailyReport.merged.

This execution block spans lines 84-95 in CostUsageFetcher.swift.

Project Breakdown Aggregation

After the raw scan completes, Codex-specific project breakdowns are merged by mergedProjectBreakdowns in CostUsageFetcher.swift. This yields a unified list of CostUsageProjectBreakdown objects sorted by cost, token count, and name.

Snapshot Generation

The tokenSnapshot method synthesizes a CostUsageTokenSnapshot containing:

  • Session-level tokens and cost for the current day (the entry whose local day contains now)
  • 30-day totals derived from the daily report summary, or summed from entries if absent
  • Per-project breakdowns

Caching Layer

To avoid redundant disk scans, loadCachedCodexTokenSnapshot (lines 36-49) attempts to read a persisted CachedCodexTokenSnapshotResult from disk via CostUsageCacheIO. If a valid cache exists and covers the requested window, the snapshot returns instantly without file system traversal.

Bedrock Special Handling

When the provider is .bedrock, the scanner delegates to BedrockCredentialResolver and BedrockUsageFetcher.fetchDailyReport, bypassing the generic log-parsing flow used for Codex and Claude.

Key Implementation Files

Code Examples

Fetching Usage from Swift

import CodexBarCore

let fetcher = CostUsageFetcher()
do {
    // Request Codex usage for the past 30 days with auto-refresh pricing
    let codexSnapshot = try await fetcher.loadTokenSnapshot(
        provider: .codex,
        now: Date(),
        historyDays: 30,
        forceRefresh: false,
        allowVertexClaudeFallback: false)

    print("Session cost: $\(codexSnapshot.sessionCostUSD ?? 0)")
    print("30-day total: $\(codexSnapshot.last30DaysCostUSD ?? 0)")
    if let project = codexSnapshot.projects?.first {
        print("Top project '\(project.name)' spent $\(project.totalCostUSD ?? 0)")
    }
} catch {
    print("Failed to fetch usage: \(error)")
}

CLI Invocation

$ codexbar cost --provider codex

# Output:

#   Session: $0.12   (1,234 tokens)

#   30-day total: $9.45

#   Projects:

#     • my-project   $4.20  (2,500 tokens)

Leveraging the Cache

let cached = await fetcher.loadCachedCodexTokenSnapshot(
    now: Date(),
    codexHomePath: "/Users/me/.codex",
    historyDays: 30)

if let snapshot = cached {
    // Use cached version - no disk scan performed
    print("Cached 30-day cost: $\(snapshot.last30DaysCostUSD ?? 0)")
}

Summary

  • CodexBar uses CostUsageFetcher to orchestrate cost scanning for Codex, Claude, and other providers through a unified pipeline.
  • The scanner validates providers, refreshes pricing data via ModelsDevPricingPipeline, and executes heavy-weight log parsing via CostUsageScanExecutor.
  • Session-level cost data from Pi tools is merged with daily reports using CostUsageDailyReport.merged to produce accurate CostUsageTokenSnapshot objects.
  • A caching layer via CostUsageCacheIO prevents redundant scans of large session archives, with loadCachedCodexTokenSnapshot providing instant access to recent data.
  • The implementation supports both programmatic Swift APIs and CLI interfaces through CLICostCommand.swift.

Frequently Asked Questions

How does CodexBar handle different AI providers in the same codebase?

The CostUsageFetcher.loadTokenSnapshot method accepts a provider enum (.codex, .claude, .vertexai, or .bedrock) and configures scanner options accordingly. For Bedrock, it delegates to BedrockCredentialResolver and BedrockUsageFetcher.fetchDailyReport, bypassing the generic log-parsing flow used for Codex and Claude.

What is the default time window for cost scanning?

By default, CodexBar calculates a 30-day rolling window through the loadTokenSnapshot method, creating since and until date ranges based on the historyDays parameter (defaulting to 30). This window determines which log files and session data are scanned.

How does CodexBar ensure cost calculations use current pricing?

Before scanning, the pipeline invokes ModelsDevPricingPipeline.refreshIfNeeded for Codex and Claude providers. This updates the per-model pricing cache from OpenAI's dev-pricing endpoint, ensuring that token counts are converted to accurate USD amounts.

Can the scan process be interrupted or cancelled?

Yes. The CostUsageScanExecutor.run method provides a cancellation bridge that allows Swift concurrency to signal cancellation to the underlying synchronous scanner. This prevents long-running file system operations from blocking app termination or UI updates in the menu bar interface.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →