ccc-usage ยท diff

git:20260722.9d3ab82 to git:20260728.38c269b

12 added, 11 removed. Audit A to A.

---
name: ccc-usage
description: "Usage & Cost deck: what your agent work costs, and what delegating to cheaper models saved you. A self-contained artifact โ€” burn, savings, cost by app."
allowed-tools:
- Read
- Bash
- Write
- AskUserQuestion
argument-hint: "[open | status]"
---
# $ccc-usage โ€” Usage & Cost
The money deck. CC Commander already logs your model routing to `~/.claude/commander/` โ€” `savings.json` (what delegating to cheaper models saved vs an all-Opus baseline) and `mission-control/metrics.jsonl` (cost per app per day). This turns those into one page: cumulative savings, saved/day + cost/day trends, and a cost-by-app split.
> ๐Ÿ”’ Privacy: the numbers are read locally. Publishing the artifact uploads it (dollar figures, per-app split, dates) to your private claude.ai artifact URL โ€” private to your account, but it leaves the machine. Always ask before publishing; never publish automatically.
> โš ๏ธ Honesty: these are **estimates** (rough per-model rates vs an all-Opus baseline, not your actual bill). Say so on the page. Never present them as billing.
## How it routes
On `$ccc-usage` with no argument, open a click-first picker:
```
AskUserQuestion:
question: "Usage & Cost โ€” how do you want it?"
options:
- ๐Ÿ›ฐ๏ธ Publish the deck โ€” a living Usage & Cost artifact you can keep beside your chat
- ๐Ÿ—ฃ๏ธ Plain-English status โ€” narrate the headline numbers here, no jargon
```
`$ccc-usage open` (or `snapshot`) โ†’ publish the deck. `$ccc-usage status` โ†’ narrate.
**Zero-state:** if `savings.json` and `metrics.jsonl` are both missing/empty, say so plainly โ€” "No cost data logged yet โ€” run some agents (`$ccc-fleet`, `$ccc-spawn`) and this deck fills in." Never render an error for an empty deck.
### ๐Ÿ›ฐ๏ธ Publish the deck
- **LIVING PATTERN:** always render to the SAME file path (`scratchpad/ccc-usage-live.html`), then republish that same path with the Artifact tool โ€” same path means same URL, so it updates one living page instead of a trail of copies.
+ **LIVING PATTERN:** always render to the SAME file path (`scratchpad/ccc-usage-live.html`), then republish that same path with the Artifact tool โ€” same path means same URL, so it updates one living page instead of a trail of copies. **Do not change this path** โ€” it is the identity of every bookmark anyone already has for this deck.
- Build the self-contained HTML with the plugin's own library (no server needed):
+ Since v7.4.0 this page is the **Usage tab of the Commander Console**, published on its own โ€” one builder renders every deck and the console, so the numbers can't disagree:
```bash
mkdir -p scratchpad
- node --input-type=module -e "
- import { readUsageModel, buildUsageHtml } from '${CLAUDE_PLUGIN_ROOT}/lib/usage-snapshot.js';
- import { writeFile } from 'node:fs/promises';
- const now = Date.now();
- const html = buildUsageHtml(await readUsageModel({ now }), { now });
- await writeFile('scratchpad/ccc-usage-live.html', html);
- console.log('wrote scratchpad/ccc-usage-live.html');
- "
+ if [ -f "${CLAUDE_PLUGIN_ROOT}/scripts/build-console.mjs" ]; then
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/build-console.mjs" \
+ --surface artifact --tab usage --out scratchpad/ccc-usage-live.html
+ else
+ node commander/cowork-plugin/scripts/build-console.mjs \
+ --surface artifact --tab usage --out scratchpad/ccc-usage-live.html
+ fi
```
+ The page is unchanged apart from one added line pointing at `$ccc-console` (the inline all-in-one view).
+
**First publish this session** โ†’ ask before publishing ($ figures leave the machine for your private artifact URL). **Every later run of `$ccc-usage`** โ†’ invoking the skill again IS the refresh consent: republish the same file path to the same URL without re-asking. Publish `scratchpad/ccc-usage-live.html` with the Artifact tool (favicon ๐Ÿ’ฐ). End with the artifact title + the headline: "$X saved across N dispatches." To refresh later: run `$ccc-usage` again โ€” same URL updates in place; viewers reload.
### ๐Ÿ—ฃ๏ธ Plain-English status
Run `readUsageModel({})` and read `model.totalSavedUsd` / `model.totalDispatches` / `model.costByApp`, then narrate caveman-simple: "You saved about $X by letting cheaper models do N jobs. Most of your spend is <app>." No jargon, no tables.
## The deck also links the others
- The published artifact carries the shared **Commander decks** strip at the top โ€” one click (copy) away from the Cockpit, Mission Control, and Safety decks. Users always know the other decks exist.
+ The published artifact carries the shared **Commander decks** strip at the top โ€” one click (copy) away from the Cockpit, Mission Control, and Safety decks. Users always know the other decks exist. It also carries one line pointing at `$ccc-console`, the inline console that shows all of these tabs at once (and has a prompt bar, which a published page cannot).
> **On Codex:** some panels may be empty on Codex today โ€” Safety's failure hotspots, Mission Control's agent roster, and Usage's savings hero are fed from Claude-only hooks right now. A follow-up workstream wires the matching Codex telemetry.
---
> โš™๏ธ **Fable contract:** plan before build ยท verifier โ‰  worker ยท prove before alarm ยท loops need gates ยท leave durable state โ€” `rules/fable-method.md`
> (On Codex, present these options as a numbered list and ask the user to reply with a number โ€” AskUserQuestion is Claude-only.)