token-doctor — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited token-doctor (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Platforms: Claude Code / Cowork and Codex.scripts/inventory.pydetects the host (via theplatformstampinstall.shwrites, orAI_FIRST_PLATFORM) and routes: Claude Code (~/.claude/projects) + Cowork transcripts, or Codex rollouts (~/.codex/sessions). Codex token usage comes from Codex's own per-responsetoken_countevents; cost uses OpenAI list rates inpricing.py(gpt-5.4 family; unknown models show token counts with no fabricated cost). Antigravity is unsupported: its IDE store is AEAD-encrypted at rest and its CLI store has no parseable turn/token content, so the skill prints a clear "not available" message and exits.
Two-stage diagnostic. Stage 1 is fast and lands directly in the terminal so the user always walks away with their numbers. Stage 2 is opt-in, fans out subagents over hotspots, and writes a tight Markdown report.
Read this whole file before running.
Trigger phrases: "diagnose my Claude habits", "why am I spending so much", "where are my tokens going", "audit my spend", "token doctor", "what's driving my Claude bill".
Do NOT trigger for:
task-profile.session-search.The line is: token-doctor is about cost shape, not task inventory or recall.
~/.claude/projects/*/*.jsonl~/Library/Application Support/Claude/local-agent-mode-sessions/*/*/local_*/audit.jsonlIf neither path exists, stop and say so.
The goal is: the user invokes the skill, sees a clean doctor's report within 10 seconds, knows which projects are healthy and which are bleeding, and can decide whether to go deeper. You write the report directly in your message based on the JSON the scripts produce. The scripts compute, you communicate.
~/.claude/skills/token-doctor/scripts/inventory.py --since YYYY-MM-DD --out out/sessions.jsonlDefault window: last 90 days. Flags: --since, --until, --all, --include-automation, --no-cowork. Automation runs (paperclip, /loop, /schedule, ditto-routines, scheduled-tasks) excluded by default.
~/.claude/skills/token-doctor/scripts/personal_stats.py --in out/sessions.jsonl --out out/user-stats.jsonPrints a single confirmation line. The full data is in out/user-stats.json.
Read out/user-stats.json. Then write the report directly in your message as terminal-style ASCII with emojis. The user reads your message; no intermediate file.
#### Report structure (mandatory sections, in order)
🩺 ┌────────────────────────────────────────────────────────────────────┐
│ TOKEN DOCTOR · personal diagnosis │
└────────────────────────────────────────────────────────────────────┘
Patient: <user's first name or "you">
Window: <window dates from inventory>
Spend: $<total> list-price equivalent · <conv count> conversations
── Vital signs ─────────────────────────────────────────────────────────
🔴/🟡/🟢 Marathon (≥300 turns) <N> conv · $<X> · <Y>% of spend
🔴/🟡/🟢 Zombie (≥4h wall clock) <N> conv · $<X> · <Y>% of spend
🔴/🟡/🟢 Cache rebuilds <N> events · <Z>M tokens · ~$<X>
🔴/🟡/🟢 Re-read ratio <X>× (healthy ≤15×, org avg 30×)
📈 Peak context observed <X>k tokens
── Spend by conversation length ────────────────────────────────────────
1 to 5 <bar> <%> (<N> conv)
6 to 20 <bar> <%> (<N> conv)
…
1,000+ <bar> <%> (<N> conv)
── Diagnosis ───────────────────────────────────────────────────────────
<2-4 sentences synthesizing the vitals into one clear picture. Lead with
the dominant antipattern in this user's data, then the corollary cost. End
with one line about the strongest positive signal you see.>
── Project chart ───────────────────────────────────────────────────────
✅ clean · 🏃 marathon · 🔄 rebuilds · 🧟 zombie · ⚠️ multiple
<emoji> $<X> <truncated cwd> <meta line>
<emoji> $<X> <truncated cwd> <meta line>
… up to 10-12 rows from by_cwd_top
── Treatment plan ──────────────────────────────────────────────────────
💚 Keep doing:
<bullet referencing a clean project from by_cwd_top or by_cwd_clean_deeper,
OR a positive structural signal like a high short_share if no clean cwd is in top 12>
<2-3 bullets total>
🎯 Change first:
<one concrete action tied to the biggest lever, with cited project>
<2-3 bullets total, ordered by expected impact>
── Want a deeper look? ─────────────────────────────────────────────────
<one-line question asking if they want the deep dive>#### Rules when writing the report
by_cwd_top[i].emoji in the JSON. Do not re-classify.█ characters proportional to the share. Use a fixed width like 36 chars.by_cwd_top entries with emoji == "✅" for cleanby_cwd_clean_deeper for clean projects below the top 12short_share if neither is available — frame as "X% of your spend is in short focused sessions, so the habit is there, you just don't use it everywhere"… if they're long. Drop the /Users/<name>/ prefix when it makes the line cleaner.#### Traffic-light thresholds
| Metric | 🟢 | 🟡 | 🔴 |
|---|---|---|---|
| Marathon share | < 20% | 20-50% | ≥ 50% |
| Zombie share | < 20% | 20-50% | ≥ 50% |
| Cache rebuild $ | < $50 | $50-$200 | ≥ $200 |
| Re-read ratio | ≤ 15× | 15-35× | ≥ 35× |
#### Asking about the deep dive
End with one short line, not a paragraph. Example:
Want me to pull apart your top sessions one by one — what specifically drove each marathon, plus a couple of your most efficient runs to learn from? Takes about a minute, runs ~15 Haiku subagents in parallel.
If they say no, stop. The report is the deliverable.
~/.claude/skills/token-doctor/scripts/pick_hotspots.py --in out/sessions.jsonl --out out/hotspots.jsonSelects ~14 sessions:
Briefly tell the user the list before fan-out so they can drop sensitive sids. Keep it to one line per session: $X · N turns · short title.
~/.claude/skills/token-doctor/scripts/build_payloads.py --sessions out/sessions.jsonl --hotspots out/hotspots.json --outdir out/payloadsWrites one redacted payload per hotspot. Payloads include token shape, tool-call counts, timeline samples, and a 120-char title. They do NOT include user prompt bodies or model output text.
For each payload in out/payloads/, dispatch one subagent. Send all calls in one message with multiple tool blocks so they run in parallel.
Agent(
description="Diagnose one session",
subagent_type="general-purpose",
model="haiku",
run_in_background=true,
prompt="""
Diagnose the session at out/payloads/<sid>.json.
Read first, in order:
1. ~/.claude/skills/token-doctor/references/antipattern-taxonomy.md
2. ~/.claude/skills/token-doctor/references/diagnosis-rubric.md
3. out/payloads/<sid>.json
Apply the rubric. Emit strictly the JSON schema (see rubric §Output) to out/analyses/<sid>.json. Hard length limits: what_happened max 2 sentences (~25 words), trigger_moment.what max 14 words, would_have_helped max 18 words. Lead with structural facts (turn count, context size, key signal). No restating the schema.
Tone: second-person, neutral, no "waste" / "burning".
"""
)Wait for all to complete.
Read every out/analyses/*.json. Then:
# Token Doctor — your diagnosis
**Signature.** <one sentence: dominant antipattern + dominant strength>
**Bottom-line lever.** <one sentence: the single habit change with the biggest expected impact>
## What you're doing well
- **<positive pattern>** in `<cwd>`. <one sentence with one cited sid>
- **<positive pattern>** in `<cwd>`. <one sentence with one cited sid>
(2-3 bullets. At least one is mandatory; do not skip this section.)
## What's driving your bill
- **<antipattern>** in `<cwd>`. <one sentence. Cite the worst sid and one specific turn or signal>
- ...
(3-5 bullets ordered by estimated savings)
## Per-session diagnoses
| Cost | Turns | Verdict | What happened |
|---:|---:|---|---|
| $XXX | NNN | <label> | <1-2 line what_happened from the analysis> |
| ...
(Only the analyzed sessions. Use the `what_happened` field verbatim from each analysis JSON.)Also write out/recommendations.json with structured form for re-use:
{
"signature": {
"primary_antipattern": "marathon | drip-feed | zombie | bloat | grind | drift | fanout | none",
"primary_strength": "focused | front-loaded | time-bounded | lean | directed | none",
"one_line": "<one sentence about how this user's spend is shaped>"
},
"bottom_line_lever": "<one sentence>",
"positives": [{"pattern": "...", "cwd": "...", "evidence_sid": "...", "note": "..."}],
"antipatterns": [{"pattern": "...", "cwd": "...", "evidence_sids": ["..."], "note": "...", "expected_impact": "small|medium|large"}],
"session_table": [{"sid": "...", "cost": 0, "turns": 0, "verdict": "...", "what_happened": "..."}]
}Keep the prose terse. The user already has the terminal numbers; the report's job is to point at specific projects and habits, not to recite stats.
out/ contain session ids and short titles. They do not contain conversation content.rm -rf out/ to wipe everything.personal_stats.py script uses them). Keep them out of the Markdown report — there it should look like an engineering doc.--include-automation if they want those analyzed; otherwise note the interactive count.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.