[FEATURE] Per-model breakdown of the session cost in $.session.usage() / session.measure and the status line JSON

Status Open
Reported on v2.1.290
Maintainer reply None cached
Activity 0 comments · opened Oct 6, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

The session cost reaches integrations as one number. On 2.1.290:

  • status line JSON: cost.total_cost_usd (with durations and lines added / removed)
  • function hooks: SessionCost is { usd } (from $.session.usage() and session.measure)

A session usually spends on more than one model: the main loop, subagents that run on another model, a fallback model, and internal calls such as titles and compaction. Neither surface says how the total splits between them.

An integration that wants "how much of this went to model X" has to rebuild it:

  1. read the main transcript and every subagent transcript,
  2. reduce the records to one per API request,
  3. price each request with its own copy of the price table.

Each step is fragile outside the engine. The price table has to follow new models, fast mode and any managed modelPricing. Subagent transcripts have known inconsistencies (#93620, #97978). In one session I compared, the transcript count came out about 9.5% below the status line's total because the subagent requests live in other files.

Function hooks don't close the gap either. turn.step resolves with the token counts and the model id of each request, but no cost, and the cache-write count is not split by TTL, so a plugin cannot price a request exactly.

The engine already has the split:

  • the SDK result message carries modelUsage, documented as per-model totals for every model call including the main loop, subagents and internal calls, next to total_cost_usd;
  • the OpenTelemetry api_request event carries model and cost_usd, and the claude_code.cost.usage metric has a model attribute.

It just isn't passed to the status line or to function hooks.

Related: #87330 asked for per-model cost in the /usage screen and at /model switch time (closed as not planned). This request is narrower: pass the breakdown the engine already keeps to the two integration surfaces. #95837 describes a usage panel that already shows a per-model breakdown.

Proposed Solution

Add the per-model totals behind the existing total:

  • function hooks: SessionCost.byModel, a map from model id to { usd } (token counts too if that is what modelUsage holds), covering the same calls as usd;
  • status line JSON: cost.by_model with the same content.

The entries sum to the existing total. Absent where the host keeps no cost ledger, so existing readers are unaffected.

Alternative Solutions

  • OpenTelemetry: point the OTLP exporter at a local collector and sum api_request by model. Exact, but it needs a listening port and takes the one exporter endpoint, which conflicts with a real collector.
  • Transcripts plus an own price table, as described above.
  • turn.step token counts plus an own price table. Same table problem, and no TTL split for cache writes.

Priority

Low - Nice to have

Feature Category

Developer tools/SDK

Use Case Example

A usage display keeps a per-day record of spend by model and shows what share went to the most expensive model. That share is the figure a user acts on: it says whether switching the main loop, or moving subagents to a smaller model, would change the bill.

Today the display computes it from transcripts with its own price table, and corrects it with OpenTelemetry where that is configured. With byModel it would add up the engine's own figures, and a new model would need no table update on the day it ships.

Additional Context

  • Claude Code 2.1.290, Windows 11. Checked in a CLI session (terminal) and in a VS Code extension session.
  • SessionCost and turn.step are as declared in the claude-code.d.ts written by 2.1.290; the status line keys are from the actual stdin of a status line command on the same build.
  • modelUsage and the telemetry attributes are as described in the Agent SDK reference and the monitoring documentation.

View original on GitHub ↗