# Session Report

> Generate a self-contained HTML report that debugs what is in a Claude Code or Codex session's context window and how every token is spent — context budget, the hidden cost of retained thinking, the dumb-zone cutoff, loaded CLAUDE.md/skills, and the full history.

- Skill: `mark-life/session-report` (Agent Skill, multi-file: 14 files)
- Install (CLI): `npx skillmds@latest add mark-life/session-report`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mark-life/session-report/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Mark-Life (https://skillmd.com/u/mark-life)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mark-life/session-report

---


# Session Report

Generates a single self-contained HTML file that reconstructs an agent session from its transcript and shows **what is in the model's context window and how every token is spent** — a forensic debugger for context bloat and the "dumb zone" (context-rot past ~40% of the window).

This is a **user-invoked** command (`/session-report`); it is not auto-invoked by the model. The session id is passed as the `$session_id` argument.

## What the report shows

- **Verdict header + gauge**: peak context vs window, health (Healthy / Degrading / Rotting), one-click jump chips to every issue.
- **Context budget at peak**: a stacked bar + table partitioning the peak context into system+tools, listings (skills/agents/tools), CLAUDE.md/memory, opened files, user prompts, tool results, assistant text, **thinking**, and an honest "unattributed (tool schemas/overhead)".
- **Context-growth timeline**: inline-SVG stacked area of real context size per turn, with the dumb-zone band, the 200K-model ghost line, compaction cliffs, peak marker, and the first dumb-zone crossing.
- **Loaded artifacts**: CLAUDE.md/AGENTS.md/memory sizes (read from disk), skill/agent/tool listings, opened files — sortable, with "trim me" callouts.
- **Biggest items** and a **full collapsible history** of every event (tool calls, results, attachments) with search/filter and the dumb-zone divider inline.

## How to run

The generator is a zero-dependency TypeScript script with **no build step**. Run it from the
skill's `scripts/` dir with the requested session id (`$session_id`). Pick whichever runtime the user has — they need only one:

```bash
# Node >= 22.18 / >= 23.6 (native TS type-stripping; most Claude Code users have Node):
node generate-report.ts "$session_id" --open
# Bun:
bun run generate-report.ts "$session_id" --open
# Older Node (no type-stripping) — no install needed, npx fetches it:
npx tsx generate-report.ts "$session_id" --open
```

Detect what's available (e.g. `command -v node bun`) and use that. A direct transcript path and options also work, e.g. `node generate-report.ts /path/to/<id>.jsonl --out report.html --window 1000000`.

If `$session_id` is empty (the user ran `/session-report` with no argument), list recent Claude Code sessions and ask which one — e.g. `ls -t ~/.claude/projects/*/*.jsonl | head` — then re-run with the chosen id.

It finds the transcript by id under `~/.claude/projects/*/`, parses it, reads the relevant CLAUDE.md/AGENTS.md/memory files from disk, and writes the HTML (then `--open`s it if asked).Print the output path to the user.

Options:
- `--out <file>` — output path (default `./ccx-<id>.html`).
- `--window <tokens>` — context-window size. **Leave the default. Claude Code always runs the 1M window, so keep 1M and do NOT pass `--window 200000` unless the user explicitly asks for a 200K view.** A peak near 200K is normal 1M usage (~20% full), not evidence of a 200K cap — never infer the window from the peak or from a healthy-looking gauge, and never regenerate to "double-check." If the user does want to compare, the report header has a live in-browser window override, so there's no need to regenerate at all. (Codex records its real window directly, so this flag is irrelevant there.)
- `--dumb-zone <frac>` — degradation threshold as a fraction of the window (default `0.40`).
- `--no-subagents` — skip parsing subagent transcripts.
- `--no-redact` — disable secret redaction. Best-effort secret redaction (API keys, tokens, private keys, credential assignments) is **ON by default**; this flag turns it off and embeds the transcript verbatim.
- `--codex` — force Codex-rollout parsing (auto-detected by default from the file/path).

## Key concepts (so you can interpret the report for the user)

- **Ground truth vs estimate**: per-turn context size is exact from `usage` metadata(`input + cache_read + cache_creation`); per-item sizes are chars/4 estimates.
- **Thinking is the usual hidden giant**: thinking text is *not* stored in the transcript, but it is retained in context. The report recovers it from real `output_tokens` minus visible text/tool_use — so a huge "thinking" band is accurate, not a guess.
- **System+tools residual**: first-turn context minus visible loads = the fixed floor (system prompt + tool schemas + global CLAUDE.md). Not in the transcript; partly attributed from disk.
- **Unattributed** = real peak minus everything attributable ≈ growing tool-definition schemas (from tool search / many MCP servers), per-turn reminders, and encoding overhead. Large value ⇒ tool bloat.

## Codex sessions

Codex rollouts (`~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl`) are also supported; Codex even records `model_context_window` directly. Pass the rollout path. See `scripts/lib/codex.ts`.

## Notes

- Output is a single HTML file — no server, no network, no external libraries. Open in any browser.
- A deterministic script reads the transcript and writes the HTML; the model never reads or echoes session content. CLAUDE.md/AGENTS.md/memory files are read for **size only** and are **not** embedded. The report is a **local, private, human-facing artifact** — it is not meant to be fed back into an LLM as context.
- Transcript content is HTML-escaped (safe to **open** in a browser — no XSS), and best-effort secret redaction runs by default, but the file may still contain sensitive data from your session — **review before sharing**. The report opens with a dismissible banner reminding you of this; use `--no-redact` to embed the raw transcript verbatim.
- Large sessions produce multi-MB files (everything is inlined and collapsed by default).

