feat: add multi-currency support with live exchange rates by IrumiDesu7 · Pull Request #15 · ccusage/ccusage · GitHub
Skip to content

feat: add multi-currency support with live exchange rates#15

Closed
IrumiDesu7 wants to merge 2 commits into
ccusage:mainfrom
IrumiDesu7:main
Closed

feat: add multi-currency support with live exchange rates#15
IrumiDesu7 wants to merge 2 commits into
ccusage:mainfrom
IrumiDesu7:main

Conversation

@IrumiDesu7

Copy link
Copy Markdown

Summary

This PR adds comprehensive multi-currency support to ccusage, allowing users to view Claude usage costs in their preferred currency with live exchange rates.

Key Features

  • 🌍 20 Supported Currencies: USD, EUR, GBP, JPY, CAD, AUD, CHF, CNY, INR, IDR, SGD, HKD, KRW, MXN, BRL, ZAR, SEK, NOK, DKK, PLN
  • 📡 Live Exchange Rates: Fetches current rates from exchangerate-api.com
  • ⚡ Smart Caching: 2-hour local cache in ~/.claude/exchange-rates.json for performance
  • 🛡️ Graceful Fallbacks: Falls back to USD if API fails or currency unavailable
  • 💱 Proper Formatting: Currency-specific symbols and decimal handling (e.g., IDR shows "Rp", JPY shows no decimals)
  • 🔧 CLI Integration: New --currency/-c flag works with all existing commands

Usage Examples

# Daily report in Indonesian Rupiah
ccusage daily --currency IDR

# Session report in Euros with JSON output
ccusage session --currency EUR --json

# British Pounds with date filtering
ccusage daily --currency GBP --since 20250101

Technical Implementation

Core Components:

  • CurrencyService: Handles exchange rate fetching, caching, and conversion
  • ExchangeRate interface: Type-safe currency data structure
  • convertCostToCurrency(): Utility function for USD→target conversion
  • Enhanced CLI args with currency validation

Architecture Decisions:

  • Internal calculations remain in USD (maintains LiteLLM compatibility)
  • Currency conversion only at display time (preserves data integrity)
  • Local file-based caching for offline resilience
  • Free API with no rate limits or registration required

Error Handling:

  • Network failures → fallback to stale cache → fallback to USD
  • Missing currencies → fallback to USD with warning
  • Invalid cache files → start with empty cache

Files Added/Modified

New Files:

  • src/currency.ts - Core currency service implementation
  • src/currency.test.ts - Comprehensive test coverage

Modified Files:

  • src/types.ts - Currency types and validation schemas
  • src/shared-args.ts - CLI argument definition
  • src/calculate-cost.ts - Currency conversion utilities
  • src/commands/daily.ts - Multi-currency table/JSON output
  • src/commands/session.ts - Multi-currency table/JSON output

Testing

Comprehensive test coverage for CurrencyService including:

  • Exchange rate fetching with API mocking
  • Caching behavior and TTL validation
  • Error handling and fallback scenarios
  • Currency formatting and symbol handling

Manual testing verified:

  • CLI flag recognition and validation
  • Live API integration with caching
  • Proper formatting in both table and JSON outputs
  • Graceful handling of network failures

Example Output

Table Format (IDR):

┌─────────────────┬──────────────┬──────────────┬──────────────┐
│ Date            │ Total Tokens │ Cost (IDR)   │ Last Activity│
├─────────────────┼──────────────┼──────────────┼──────────────┤
│ 2025-06-06      │   82,159,177 │ Rp1097751.35 │ 2025-06-06   │
└─────────────────┴──────────────┴──────────────┴──────────────┘

JSON Format (EUR):

{
  "daily": [
    {
      "date": "2025-06-06",
      "totalCost": 59.01,
      "currency": "EUR"
    }
  ],
  "totals": {
    "totalCost": 76.77,
    "currency": "EUR"
  }
}

Backward Compatibility

Fully backward compatible - defaults to USD if no currency specified
No breaking changes to existing CLI interface or JSON structure
Maintains data integrity - all internal calculations still in USD

Test Plan

  • Verify CLI flag appears in help output
  • Test currency conversion with live API
  • Validate caching behavior and TTL expiration
  • Confirm fallback handling for network errors
  • Test all 20 supported currencies
  • Verify table and JSON output formatting
  • Check backward compatibility with no --currency flag
  • Validate proper currency symbols and decimal handling

Implementation Notes

This feature enables international users to better understand their Claude Code usage costs in familiar currencies. The implementation prioritizes reliability with multiple fallback layers and maintains full backward compatibility.

The exchange rate API (exchangerate-api.com) is free, reliable, and doesn't require registration, making it ideal for this use case. Local caching ensures good performance and offline functionality.

- Add support for 20 currencies (IDR, EUR, GBP, JPY, etc.)
- Implement CurrencyService with exchange rate API integration
- Add local caching with 2-hour TTL for exchange rates
- Update CLI with --currency/-c flag for all commands
- Convert costs from USD to target currency at display time
- Add proper currency formatting and symbols
- Include comprehensive test coverage
- Graceful fallback to USD on API failures

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @IrumiDesu7, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello! Gemini here, providing a summary of this pull request. This PR introduces comprehensive multi-currency support to the ccusage CLI tool. The primary goal is to allow users to view their Claude usage costs in their preferred currency rather than being limited to USD. This is achieved by fetching live exchange rates from an external API, caching them locally for performance and offline access, and implementing robust fallback mechanisms in case of API or cache issues. The changes integrate this new functionality into the existing daily and session commands, adding a new --currency flag and ensuring proper currency formatting in both table and JSON outputs. The implementation keeps internal calculations in USD for consistency and performs conversion only at the display layer.

Highlights

  • Multi-Currency Support: Adds a new --currency (or -c) CLI flag to specify the desired output currency. Supports 20 different currencies.
  • Live Exchange Rates: Integrates with the exchangerate-api.com service to fetch current exchange rates relative to USD.
  • Local Caching: Implements a local cache for exchange rates in ~/.claude/exchange-rates.json with a 2-hour TTL to improve performance and provide offline capability.
  • Robust Fallbacks: Includes logic to gracefully handle API failures by falling back to stale cached rates, and ultimately falling back to USD if no valid rate can be obtained.
  • Currency Formatting: Adds currency-specific formatting, including symbols and decimal place handling (e.g., no decimals for JPY/KRW).
  • CLI Integration: Modifies the daily and session commands to accept the new --currency flag and display costs in the selected currency in both table and JSON output formats.
  • New Currency Service: Introduces a dedicated CurrencyService class to encapsulate the logic for fetching, caching, converting, and formatting currency.

Changelog

Click here to see the changelog
  • src/calculate-cost.ts
    • Imports Currency type and currencyService instance.
    • Adds convertCostToCurrency async function to convert a USD amount to a target currency using the currencyService.
    • Adds createTotalsObjectWithCurrency async function to create a totals object including the converted cost and the target currency.
  • src/commands/daily.ts
    • Imports currency-related functions (createTotalsObjectWithCurrency, convertCostToCurrency) and types (Currency, CurrencyService).
    • Modifies the JSON output logic to use createTotalsObjectWithCurrency for the totals and iterate through daily data to convert each item's cost using convertCostToCurrency, adding the currency field to each daily entry.
    • Updates the table header to dynamically display the cost column label based on the selected currency (e.g., 'Cost (EUR)').
    • Modifies the loop adding daily data rows to the table to convert the cost using convertCostToCurrency and format it using CurrencyService.formatAmount.
    • Modifies the logic for adding the total row to the table to convert the total cost using convertCostToCurrency and format it using CurrencyService.formatAmount.
  • src/commands/session.ts
    • Imports currency-related functions (createTotalsObjectWithCurrency, convertCostToCurrency) and types (Currency, CurrencyService).
    • Modifies the JSON output logic to use createTotalsObjectWithCurrency for the totals and iterate through session data to convert each item's cost using convertCostToCurrency, adding the currency field to each session entry.
    • Updates the table header to dynamically display the cost column label based on the selected currency (e.g., 'Cost (JPY)').
    • Modifies the loop adding session data rows to the table to convert the cost using convertCostToCurrency and format it using CurrencyService.formatAmount.
    • Modifies the logic for adding the total row to the table to convert the total cost using convertCostToCurrency and format it using CurrencyService.formatAmount.
  • src/currency.test.ts
    • New file containing comprehensive unit tests for the CurrencyService class.
    • Tests cover fetching exchange rates (including USD=1, successful fetch, currency not found fallback, API error fallback), converting amounts from USD, getting currency symbols, and formatting amounts according to currency conventions.
  • src/currency.ts
    • New file defining the CurrencyService class.
    • Implements methods for fetching exchange rates from exchangerate-api.com, handling API responses, and managing a local cache (~/.claude/exchange-rates.json) with a 2-hour TTL.
    • Includes logic for loading and saving the cache using Node.js file system promises.
    • Provides the convertFromUSD method to perform the actual currency conversion.
    • Includes static methods getCurrencySymbol and formatAmount for currency-specific display formatting.
    • Implements fallback logic for API errors, missing currencies, and invalid cache files.
    • Exports a singleton instance of CurrencyService.
  • src/shared-args.ts
    • Imports SupportedCurrencies and Currency types.
    • Adds a new command-line argument --currency (short -c) to the sharedArgs object.
    • Configures the --currency argument as an enum with choices from SupportedCurrencies and a default value of 'USD'.
  • src/types.ts
    • Defines the SupportedCurrencies array containing the list of 20 supported currency codes.
    • Defines the Currency type as a union of the strings in SupportedCurrencies.
    • Defines the ExchangeRate interface for the structure of cached exchange rate data (currency code, rate, timestamp).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a well-executed pull request that adds significant value by introducing multi-currency support. The implementation is thoughtful, with robust caching, good fallback mechanisms, and comprehensive test coverage for the new CurrencyService.

The code is generally clear and follows good practices. The PR description is excellent and provides great context.

I have one main point of feedback regarding currency formatting consistency, detailed below. Addressing this will ensure the feature behaves as consistently as documented and tested.

Summary of Findings

  • Currency Formatting Consistency (IDR): The test case for IDR formatting in src/currency.test.ts expects thousand separators, while the implementation and PR description examples for IDR do not use them. This should be aligned for consistency.
  • Explicit Return Types (Low Severity - Not Commented): In src/calculate-cost.ts, the new function createTotalsObjectWithCurrency could benefit from an explicit return type (e.g., Promise<TotalsWithCurrency>) for improved type safety and code clarity. This was not commented on due to review settings.
  • Minor Code Style (Low Severity - Not Commented): There are a few minor style issues such as extra blank lines (e.g., src/calculate-cost.ts:58, src/currency.ts:37) and missing newlines at the end of files (src/currency.test.ts, src/currency.ts). These were not commented on due to review settings.

Merge Readiness

This pull request introduces a valuable multi-currency feature and is largely in good shape. However, there is a medium-severity issue regarding currency formatting consistency for IDR that should be addressed to ensure the tests accurately reflect the intended behavior and documentation.

Once this point is clarified and potentially adjusted, the PR should be ready for merging. As a reviewer, I am not authorized to approve pull requests, so please ensure further review and approval from authorized team members before merging.

Comment thread src/currency.test.ts Outdated
@ryoppippi

Copy link
Copy Markdown
Member

@ryoppippi ryoppippi closed this Jun 7, 2025
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 9, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 10, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 11, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jay-tau added a commit to jay-tau/ccusage that referenced this pull request Jun 11, 2026
…ead ref

External review ccusage#15 (nit a) flagged three remaining multi-paragraph
comment blocks as obvious targets for the comment-trim pattern this
branch has been applying (b529041, 0cbfeac). Nit d flagged the
test-internal `ccusage#1209-r1q` review-thread reference as meaningless
post-squash.

Trims (load-bearing rationale retained; narrative prose dropped):
* adapter/all/loader.rs `summary_rows` filter rationale: 16->8 lines.
  Kept the relaxed-predicate invariant + exact-zero safety claim;
  dropped the `session.shutdown` example narrative and the
  `unwrap_or(0.0)/total_cost = 0.0` source trace.
* adapter/all/types.rs `AllRow.credits` doc: 19->9 lines. Kept the
  byte-parity claim (Option::is_some per-row, SUM > 0.0 totals) and
  the `None` vs `Some(0.0)` distinction; dropped the metadata
  side-channel essay.
* adapter/copilot/loader.rs mode-dispatch table narrative: 25->17
  lines. Kept the load-bearing table verbatim, the field-presence
  rationale, the README pointer, the `Some(0.0)` semantics, and the
  synthetic-row bypass pointer; dropped the duplicated "Auto/Display
  bill those as a genuine $0" rephrasing and the
  `parse_session_state_file` provenance prose.

Scrubbed:
* adapter/all/loader.rs `summary_rows_relaxed_filter_applies_uniformly_across_non_copilot_agents`
  test comment dropped the `External review ccusage#1209-r1q` /
  `r1q-r1 follow-up` references. The behavior they document is
  identical; only the transient review-thread provenance is gone.

Validation:
* `cargo fmt --check` clean.
* `cargo clippy --workspace --all-targets -- -D warnings` clean.
* `cargo test --workspace`: 364 tests pass, 0 failed (unchanged).

Diff: 3 files changed, +23 / -50 lines (-27 net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

2 participants