Audit Session-Metrics
Reads a session-metrics JSON export and produces a prioritised, plain-English
audit of token-usage waste. It runs on the session's current model (it no
longer pins one — a hard model pin capped the usable context at that model's
window and broke invocation on long sessions). The work is mostly
summarisation over a small disk-read export, so for a ~10× cheaper run
/model haiku before invoking (short/early sessions only — Haiku's 200k
window can't hold a long conversation).
Supports three JSON scopes auto-detected from digest.scope:
- session — single session (
session_*.json) — per-turn analysis
- project — all sessions for one project (
project_*.json) — per-session analysis
- instance — all projects (
instance/*/index.json) — per-project analysis
Dispatch — how to route this invocation
First positional argument received: $ARGUMENTS[0]
Second positional argument received: $ARGUMENTS[1]
Read $ARGUMENTS[0] and match by literal equality:
$ARGUMENTS[0] |
Route |
Then read (session scope) |
Then read (project/instance scope) |
quick |
Quick audit |
references/quick-audit.md |
see Scope routing below |
detailed |
Detailed audit |
references/detailed-audit.md |
see Scope routing below |
| (empty / other) |
Print usage and stop |
this file's "Usage" block below |
— |
$ARGUMENTS[1] must be the path to a JSON export written by session-metrics.
Accepted patterns:
exports/session-metrics/session_<id8>_<ts>.json — session scope
exports/session-metrics/project_<ts>.json — project scope
exports/session-metrics/instance/<datedir>/index.json — instance scope
If $ARGUMENTS[1] is missing, empty, or the file does not exist, print:
Usage: /audit-session-metrics {quick|detailed} <path-to-session-metrics.json>
Accepted JSON types:
session: exports/session-metrics/session_*.json
project: exports/session-metrics/project_*.json
instance: exports/session-metrics/instance/*/index.json
…and stop without further work.
Steps
Run the extract helper once with the input path:
python3 scripts/audit-extract.py $ARGUMENTS[1] --mode $ARGUMENTS[0]
The helper emits a single JSON digest to stdout. Read digest.scope
from the output — it will be "session", "project", or "instance".
Do not read the raw .jsonl, and do not re-derive numbers the
digest already carries.
Scope routing — read the matching reference file:
digest.scope |
$ARGUMENTS[0] |
Reference file |
session |
quick |
references/quick-audit.md |
session |
detailed |
references/detailed-audit.md |
project |
quick |
references/project-quick-audit.md |
project |
detailed |
references/project-detailed-audit.md |
instance |
quick or detailed |
references/instance-quick-audit.md |
Follow the playbook step-by-step. Do not improvise additional phases.
For detailed mode on session scope only, the playbook also asks
you to read the user's config files (~/.claude/CLAUDE.md,
./CLAUDE.md, ~/.claude/settings.json, ./.claude/settings.json,
./.claudeignore). Each is capped at ≤500 lines — if a file is
bigger, that itself is a finding.
Output contract — three artefacts. All playbooks specify the
same three-artefact contract:
- JSON sidecar at
<project>/exports/session-metrics/audit_<id8>_<ts>_<mode>.json — structured findings (versioned schema, enum'd metrics).
- Markdown copy at
<project>/exports/session-metrics/audit_<id8>_<ts>_<mode>.md — same content rendered for humans.
- Inline chat output — the markdown content printed in your reply.
<id8> and <ts> come from digest.session_id_short and
digest.ts_str (the helper parses the input filename and
normalises all three filename patterns).
Write order. Populate the JSON object first using the digest
values, write the JSON sidecar, render the markdown using the
template in the playbook, write the markdown copy, then print the
markdown inline (without the H1 heading — the chat client already
shows context above the audit). Finish with two stderr-style lines
on their own:
[audit] saved → <json-path>
[audit] saved → <md-path>
IMPORTANT: Use the Write tool directly for steps 3 and 5.
Do NOT generate a Python script (e.g. writing to /tmp/audit_synthesis.py
and executing it) — this adds unnecessary failure modes (syntax errors,
f-string escaping) and is never required. Build the JSON in the AI's own
context; call Write. Render the markdown in context; call Write again.
Tone
- Direct and specific. Cite the exact ratio, dollar figure, or turn
index. No motivational language, no LLM-theory padding.
- Prioritise by impact. Sort findings so the costliest fix is first.
- Quote sparingly. Snippets capped at 5 lines each.
- Honour the playbook. If quick-audit.md asks for 5 rows, produce 5
rows — don't invent a 6th to look thorough.
Why this is a separate skill
The audit is a distinct, user-initiated analysis step over a finished
export, not part of generating one. It reads only the on-disk JSON — never
the conversation — so it stands alone as its own turn, which is why
session-metrics suggests /audit-session-metrics rather than invoking it
programmatically. Running it as a fresh slash command keeps the turn focused
and lets the user decide when to spend on it. The work is summarisation-heavy
and the input is tiny, so the cost path is /model haiku before invoking
(short/early sessions only — Haiku's 200k window can't hold a long
conversation) — ~10× cheaper than a frontier model, with identical output
(every dollar figure is pre-computed by audit-extract.py, not guessed by
the model).
Reference files
Session scope
references/quick-audit.md — Distilled
ratios + cache health + top expensive turns. Read when scope=session,
mode=quick.
references/detailed-audit.md — Quick
audit findings plus config + re-read scans. Read when scope=session,
mode=detailed.
Project scope
references/project-quick-audit.md —
Per-session cost outliers, cache health, breaks, weekly trend. Read when
scope=project, mode=quick.
references/project-detailed-audit.md —
Project quick findings plus per-session turn-level drilldown on the most
expensive sessions. Read when scope=project, mode=detailed.
Instance scope
references/instance-quick-audit.md —
Per-project cost breakdown, cache health, weekly cost trend. Used for both
quick and detailed modes (no per-turn data available at instance scope).
1---2name: audit-session-metrics3description: Audit a session-metrics JSON export for token-usage waste and produce a plain-English findings report. Trigger when the user runs /audit-session-metrics, when session-metrics suggests an audit after an HTML export, or when the user asks to audit / review / find waste in a saved session-metrics JSON. Two modes: "quick" (ratios + cache health + top expensive turns/sessions) and "detailed" (adds CLAUDE.md / settings / re-read scan). Supports session, project, and instance JSON scopes. Args: $ARGUMENTS[0] = quick|detailed, $ARGUMENTS[1] = path to a session-metrics JSON export.4---5
6# Audit Session-Metrics
7
8Reads a session-metrics JSON export and produces a prioritised, plain-English
9audit of token-usage waste. It runs on the session's current model (it no
10longer pins one — a hard model pin capped the usable context at that model's
11window and broke invocation on long sessions). The work is mostly
12summarisation over a small disk-read export, so for a ~10× cheaper run
13`/model haiku` before invoking (short/early sessions only — Haiku's 200k
14window can't hold a long conversation).
15
16Supports three JSON scopes auto-detected from `digest.scope`:
17- **session** — single session (`session_*.json`) — per-turn analysis
18- **project** — all sessions for one project (`project_*.json`) — per-session analysis
19- **instance** — all projects (`instance/*/index.json`) — per-project analysis
20
21## Dispatch — how to route this invocation
22
23**First positional argument received:** `$ARGUMENTS[0]`
24**Second positional argument received:** `$ARGUMENTS[1]`
25
26Read `$ARGUMENTS[0]` and match by **literal equality**:
27
28| `$ARGUMENTS[0]` | Route | Then read (session scope) | Then read (project/instance scope) |
29|-----------------|--------------------------|---------------------------|------------------------------------|
30| `quick` | Quick audit | [`references/quick-audit.md`](references/quick-audit.md) | see Scope routing below |
31| `detailed` | Detailed audit | [`references/detailed-audit.md`](references/detailed-audit.md) | see Scope routing below |
32| *(empty / other)* | Print usage and stop | this file's "Usage" block below | — |
33
34`$ARGUMENTS[1]` must be the path to a JSON export written by session-metrics.
35Accepted patterns:
36- `exports/session-metrics/session_<id8>_<ts>.json` — session scope
37- `exports/session-metrics/project_<ts>.json` — project scope
38- `exports/session-metrics/instance/<datedir>/index.json` — instance scope
39
40If `$ARGUMENTS[1]` is missing, empty, or the file does not exist, print:
41
42> Usage: /audit-session-metrics {quick|detailed} <path-to-session-metrics.json>
43>
44> Accepted JSON types:
45> session: exports/session-metrics/session_*.json
46> project: exports/session-metrics/project_*.json
47> instance: exports/session-metrics/instance/*/index.json
48
49…and stop without further work.
50
51## Steps
52
531. Run the extract helper once with the input path:
54
55 ```
56 python3 scripts/audit-extract.py $ARGUMENTS[1] --mode $ARGUMENTS[0]
57 ```
58
59 The helper emits a single JSON digest to stdout. Read `digest.scope`
60 from the output — it will be `"session"`, `"project"`, or `"instance"`.
61 **Do not** read the raw `.jsonl`, and **do not** re-derive numbers the
62 digest already carries.
63
642. **Scope routing — read the matching reference file:**
65
66 | `digest.scope` | `$ARGUMENTS[0]` | Reference file |
67 |----------------|-----------------|----------------|
68 | `session` | `quick` | [`references/quick-audit.md`](references/quick-audit.md) |
69 | `session` | `detailed` | [`references/detailed-audit.md`](references/detailed-audit.md) |
70 | `project` | `quick` | [`references/project-quick-audit.md`](references/project-quick-audit.md) |
71 | `project` | `detailed` | [`references/project-detailed-audit.md`](references/project-detailed-audit.md) |
72 | `instance` | `quick` or `detailed` | [`references/instance-quick-audit.md`](references/instance-quick-audit.md) |
73
74 Follow the playbook step-by-step. Do not improvise additional phases.
75
763. For `detailed` mode **on session scope only**, the playbook also asks
77 you to read the user's config files (`~/.claude/CLAUDE.md`,
78 `./CLAUDE.md`, `~/.claude/settings.json`, `./.claude/settings.json`,
79 `./.claudeignore`). Each is capped at ≤500 lines — if a file is
80 bigger, that itself is a finding.
81
824. **Output contract — three artefacts.** All playbooks specify the
83 same three-artefact contract:
84 - **JSON sidecar** at `<project>/exports/session-metrics/audit_<id8>_<ts>_<mode>.json` — structured findings (versioned schema, enum'd metrics).
85 - **Markdown copy** at `<project>/exports/session-metrics/audit_<id8>_<ts>_<mode>.md` — same content rendered for humans.
86 - **Inline chat output** — the markdown content printed in your reply.
87
88 `<id8>` and `<ts>` come from `digest.session_id_short` and
89 `digest.ts_str` (the helper parses the input filename and
90 normalises all three filename patterns).
91
925. **Write order.** Populate the JSON object first using the digest
93 values, write the JSON sidecar, render the markdown using the
94 template in the playbook, write the markdown copy, then print the
95 markdown inline (without the H1 heading — the chat client already
96 shows context above the audit). Finish with two stderr-style lines
97 on their own:
98 `[audit] saved → <json-path>`
99 `[audit] saved → <md-path>`
100
101 **IMPORTANT:** Use the **Write tool** directly for steps 3 and 5.
102 Do NOT generate a Python script (e.g. writing to `/tmp/audit_synthesis.py`
103 and executing it) — this adds unnecessary failure modes (syntax errors,
104 f-string escaping) and is never required. Build the JSON in the AI's own
105 context; call Write. Render the markdown in context; call Write again.
106
107## Tone
108
109- **Direct and specific.** Cite the exact ratio, dollar figure, or turn
110 index. No motivational language, no LLM-theory padding.
111- **Prioritise by impact.** Sort findings so the costliest fix is first.
112- **Quote sparingly.** Snippets capped at 5 lines each.
113- **Honour the playbook.** If quick-audit.md asks for 5 rows, produce 5
114 rows — don't invent a 6th to look thorough.
115
116## Why this is a separate skill
117
118The audit is a distinct, user-initiated analysis step over a finished
119export, not part of generating one. It reads only the on-disk JSON — never
120the conversation — so it stands alone as its own turn, which is why
121session-metrics *suggests* `/audit-session-metrics` rather than invoking it
122programmatically. Running it as a fresh slash command keeps the turn focused
123and lets the user decide when to spend on it. The work is summarisation-heavy
124and the input is tiny, so the cost path is `/model haiku` before invoking
125(short/early sessions only — Haiku's 200k window can't hold a long
126conversation) — ~10× cheaper than a frontier model, with identical output
127(every dollar figure is pre-computed by `audit-extract.py`, not guessed by
128the model).
129
130## Reference files
131
132### Session scope
133- [`references/quick-audit.md`](references/quick-audit.md) — Distilled
134 ratios + cache health + top expensive turns. Read when scope=session,
135 mode=quick.
136- [`references/detailed-audit.md`](references/detailed-audit.md) — Quick
137 audit findings plus config + re-read scans. Read when scope=session,
138 mode=detailed.
139
140### Project scope
141- [`references/project-quick-audit.md`](references/project-quick-audit.md) —
142 Per-session cost outliers, cache health, breaks, weekly trend. Read when
143 scope=project, mode=quick.
144- [`references/project-detailed-audit.md`](references/project-detailed-audit.md) —
145 Project quick findings plus per-session turn-level drilldown on the most
146 expensive sessions. Read when scope=project, mode=detailed.
147
148### Instance scope
149- [`references/instance-quick-audit.md`](references/instance-quick-audit.md) —
150 Per-project cost breakdown, cache health, weekly cost trend. Used for both
151 quick and detailed modes (no per-turn data available at instance scope).