- name
- cost-report
- description
- Report actual token spend and dollar cost of dispatched work — per agent and total — and flag cost regressions. Use when the user asks "how much did that cost", "token spend", "cost of this run", "cost report", or wants to check for a cost regression after /code-review or an orchestration run.
- argument-hint
- [--transcript <path>] [--tolerance <n>]
- user-invocable
- true
- allowed-tools
- Bash(python3 *, jq *, tail *, cat *, ls *, test *)
# Cost Report (#102)
Role: worker. Reports runtime cost/token spend captured by the cost meter.
Token usage is not available to hooks, so the `Stop`/`SubagentStop` hook
(`hooks/cost_meter.py`) records a per-session summary to
`metrics/cost-metering.jsonl` by parsing the session transcript, converting
tokens to dollars via `knowledge/model-pricing.json`. This skill reports that
data.
## Steps
1. **Per-session breakdown.** If the user passes `--transcript <path>` (or you
know the current transcript path), run an exact per-agent report:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/cost_meter.py" report --transcript <path>
```
Otherwise show the most recently recorded session from the metrics log
(prefer the migrated `.claude/metrics/` location, falling back to the
legacy bare `metrics/` path for a project mid-transition):
```bash
log=".claude/metrics/cost-metering.jsonl"; [ -f "$log" ] || log="metrics/cost-metering.jsonl"
tail -n 1 "$log" | python3 -m json.tool
```
2. **Regression check.** Compare the latest session's total cost against the
rolling mean of prior sessions (default tolerance +50%):
```bash
log=".claude/metrics/cost-metering.jsonl"; [ -f "$log" ] || log="metrics/cost-metering.jsonl"
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/cost_meter.py" regression \
--log "$log" --tolerance 0.5
```
3. Report the per-model, per-thread (main/subagent), and per-agent-type tokens
+ cost, the session total, and whether a cost regression was detected. Do
not invent numbers — print exactly what the meter emits. If
`.claude/metrics/cost-metering.jsonl` (or the legacy `metrics/cost-metering.jsonl`)
is absent, tell the user the meter hasn't recorded a session yet (the hook
records on turn end).
For a windowed cost-regression baseline (mean of only the N most recent prior
sessions instead of all-time), pass `--window N`:
```bash
log=".claude/metrics/cost-metering.jsonl"; [ -f "$log" ] || log="metrics/cost-metering.jsonl"
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/cost_meter.py" regression \
--log "$log" --tolerance 0.5 --window 10
```
## Attribution dimensions (#102, #170, #1094)
`report` breaks spend down by **model**, by **thread** (main-loop vs
subagent), and by **agent type** (#1094), plus the session **total**.
The agent-type dimension answers "which agent type drives spend" (e.g.
`security-review` vs `test-review` vs `general-purpose`): main-loop turns land
in `main`; sidechain turns are attributed via the native `attributionAgent`
field the harness stamps on subagent records, falling back to the Task/Agent
dispatch join (`tool_use` `input.subagent_type` paired with
`toolUseResult.agentId`). Sidechain spend carrying neither signal lands in an
honest `unattributed` bucket — the meter never guesses. The meter also folds in
the sibling per-subagent transcript files
(`<dir>/<session-id>/subagents/agent-*.jsonl`) that newer harness versions
write instead of inline sidechain turns, so subagent spend stays visible.
Attribution is limited to what the Claude Code harness actually records on
transcript turns. Per-command, per-phase, and per-fix-loop-iteration buckets
were **removed** (#170): they relied on `attributionSkill` / `orchestrationPhase`
/ `fixLoopIteration` fields the harness never writes (verified 0/312 in a real
transcript), and a plugin has no write-path into the transcript — so those
dimensions were always empty. The main/subagent split uses the native
`isSidechain` flag, which the harness does provide; the agent-type dimension
likewise reads only harness-recorded fields (verified against a real
transcript, #1094).
## Review value (#348)
`/build` records, per inline review checkpoint, whether review actually changed
anything (`metrics/review-value.jsonl`, schema in `performance-metrics`). When
that file exists, surface a compact "review value" summary so the user can see
whether the pipeline's review overhead paid off on this work — the count of
checkpoints that **found+fixed** a defect vs. those that **passed no-op**, with
the fix-loop iterations spent:
```bash
log=".claude/metrics/review-value.jsonl"; [ -f "$log" ] || log="metrics/review-value.jsonl"
[ -f "$log" ] && jq -s '
{checkpoints: length,
no_op: (map(select(.outcome=="no-op")) | length),
fixed: (map(select(.outcome=="fixed")) | length),
escalated:(map(select(.outcome=="escalated")) | length),
issues_found: (map(.issues_found) | add // 0),
issues_fixed: (map(.issues_fixed) | add // 0),
fix_iterations: (map(.fix_iterations) | add // 0)}' \
"$log"
```
A run that is mostly `no_op` is evidence the review ceremony is over-provisioned
for that class of work — feed it back into the `/plan` plan-tier and `/build`
per-step complexity routing. Counts only; no code or file content is stored.
## Context pollution — per-phase resident vs one-time spend (#1520)
A one-time token bill and context that lingers and "charges rent" on every
subsequent turn are economically different costs (Martin Fowler, "The
Orchestrator's Tax"). The session totals above cannot tell them apart. The
`phase_marker.py` PostToolUse hook records a marker at every `/handoff` (a
phase boundary) capturing, for the **main-loop** context, the resident
occupancy and the cumulative output spend at that boundary. `phase-report`
turns the marker sequence into a per-phase ratio:
```bash
log=".claude/metrics/phase-markers.jsonl"; [ -f "$log" ] || log="metrics/phase-markers.jsonl"
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/cost_meter.py" phase-report --log "$log"
```
Report the per-phase `resident_tokens`, `spent_tokens` (output generated during
the phase), and `resident_to_spent_ratio`. A **high** ratio flags a phase whose
context stayed resident (pollution — a candidate for earlier mid-phase
compaction or narrower subagent scoping) rather than being one-time cost; a low
ratio means most of the phase's spend was transient. If the log is absent, tell
the user no phase boundary has been recorded yet (the hook records on each
`/handoff`).
**Honesty caveat — this is a session-scoped proxy, not exact per-phase
accounting.** `resident` is sampled at the `/handoff` marker because that is the
closest phase boundary the harness exposes; the harness records no explicit
phase marker of its own (the same reason per-command/per-phase *cost*
attribution was removed in #170 — see Attribution dimensions above). The metric
lives in its own `phase-markers.jsonl` log and is never folded into the
`cost-metering.jsonl` incremental state.
## Privacy boundary
The meter persists **only** token counts, dollar amounts, model identifiers,
the main/subagent thread flag, agent-type identifiers, and — for phase markers —
a phase label and the resident/spent token counts. It never records prompt
text, code, file paths, or tool payloads. `metrics/cost-metering.jsonl` and
`metrics/phase-markers.jsonl` are metrics-only artifacts by construction.
1. **Account pace (optional, #142).** When the user asks "am I on track for my
budget", "how much have I burned this week", or "which model should I use for
the rest of the period", report account-level pace: cumulative spend over a
rolling window, the implied daily rate, and the projected spend for a billing
period — flagging when pace would exhaust a stated budget:
```bash
log=".claude/metrics/cost-metering.jsonl"; [ -f "$log" ] || log="metrics/cost-metering.jsonl"
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/cost_meter.py" pace \
--log "$log" --budget 100 --period-days 30 --window-days 7
```
Without `--budget` it reports pace only (no flag). When it flags an
over-budget pace it suggests dropping a model tier (Opus→Sonnet) for the rest
of the window.
## Notes
- Disable the meter with `DEV_TEAM_COST_METER=off`.
- Pricing lives in `knowledge/model-pricing.json` — update it when rates change
(it is the named instrument for every cost number this skill prints).
View on GitHub