Skip to content

JSON: show how much of a breakdown's cost came from stored costUSD in auto mode #1898

Closed

Description

@erenozen

What do you want to change?

In the default auto cost mode, a modelBreakdowns entry's cost adds together two different kinds of figure: costUSD values stored in the log, and costs calculated from the price table. The JSON does not say how much of cost is which.

I'd like to add one optional per-breakdown field, storedCost: the part of cost that came from stored costUSD values. It is present only when at least one record in that breakdown used its stored cost, so --mode calculate output and every breakdown without stored costs keep their current bytes.

Reproduction on 20.0.32 with two synthetic Claude records, same day and model, one without costUSD and one with "costUSD": 0.5. Command: ccusage daily --json --by-agent --offline --timezone UTC, reading .daily[0].agents[0].modelBreakdowns[0]:

--mode cost today
auto (default) 0.503084 (0.5 stored + 0.003084 calculated)
calculate 0.006084
display 0.5

Today, in auto:

{"cacheCreationTokens":20,"cacheReadTokens":30,"cost":0.503084,"inputTokens":1500,"modelName":"claude-sonnet-4-20250514","outputTokens":100}

Proposed (not built):

{"cacheCreationTokens":20,"cacheReadTokens":30,"cost":0.503084,"inputTokens":1500,"modelName":"claude-sonnet-4-20250514","outputTokens":100,"storedCost":0.5}

Why?

I'm building a FinOps tool that reads ccusage's JSON and maps it to the FinOps Foundation's FOCUS format. The converter is here: https://github.com/erenozen/ccusage-focus. To fill a cost column honestly I need to know whether a figure is what the agent recorded or an estimate at list price. In auto mode, 0.503084 is both, and nothing in the output separates them. --mode calculate avoids the mix but drops the stored figure.

People on flat-fee subscriptions ask the same question from the other side, "is this number my bill?", in #1280.

I read the closing comment on #1737 and what was merged in #1750. This is one optional key in the same place as missingPricing, with the same rule of appearing only when it says something, and nothing changes in calculate mode. It is not a new output format; JSON stays the only one, as decided in #231. My converter lives outside ccusage.

How? (optional)

The per-record choice is made in rust/crates/ccusage-core/src/cost.rs:39-45 and lost where per-record costs are summed into a breakdown: rust/adapters/claude/src/daily.rs:639, rust/crates/ccusage-core/src/summary.rs:92, and the merges in rust/crates/ccusage-adapter-all/src/types.rs:175 and :203. Each of those lines sits right beside the existing missing_pricing handling, so the new value would follow the same path.

ModelBreakdown (rust/crates/ccusage-core/src/types.rs:98-112) would gain #[serde(skip_serializing_if = "Option::is_none")] pub stored_cost: Option<f64> beside missing_pricing. The per-record value has to travel through the loaded-entry structs the way missing_pricing_model does; those are constructed at 58 sites in 27 files, tests included, so the diff is wider than the one field. --no-cost strips cost keys by name in rust/crates/ccusage-core/src/output.rs:564-569, so storedCost would join that list. Docs: one sentence after the missingPricing bullet in docs/guide/json-output.md, and the "Mixed data" line in docs/guide/cost-modes.md would point to it.

If you agree with the shape, I'd like to implement it with fixture-backed tests next to the changed modules.

Activity

  1. pullfrog commented on Oct 15, 2026

    @pullfrog
    Contributor
  2. added
    enhancementNew feature or request
    priority:lowMinor polish, documentation, or a low-impact edge case.
    triage:maintainableFits the repository's maintainable scope and needs review.
    on Oct 15, 2026
  3. added
    triage:excludedExcluded from the current maintenance scope.
    and removed
    triage:maintainableFits the repository's maintainable scope and needs review.
    on Oct 15, 2026
  4. github-actions commented on Oct 15, 2026

    @github-actions
    Contributor

    Pullfrog triage: priority:low
    Kind: feature request
    Maintenance fit: excluded
    Confidence: high

    Requests a new optional storedCost field in JSON model breakdowns to separate stored costUSD from calculated cost in auto mode for an external FinOps converter. This is new output surface, not a defect in existing behavior, with no maintainer endorsement, so excluded with low priority.

    Decision: closed by the contribution gate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority:lowMinor polish, documentation, or a low-impact edge case.triage:excludedExcluded from the current maintenance scope.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions