# src/commands/sessions

`normalize sessions` subcommand implementations for inspecting Claude Code and other agent session logs. Modules: `sort` (shared sort infrastructure — `SortDir`, `SortKey<F>`, `SortSpec<F>`, `DefaultDir` trait; each subcommand defines its own `SortField` enum implementing `DefaultDir + FromStr`), `list` (enumerate sessions with fuzzy matching, `SessionListReport`; `--sort` accepts `date`/`timestamp` (desc default), `duration` (desc), `name`/`session` (asc); `--reviewed`/`--unreviewed` filters to sessions in/not in `.normalize/sessions-reviewed`), `show` (display a single session's turns, `SessionShowReport`), `messages` (extract message content; default output groups consecutive messages under a per-session header showing `[id] project  date`, each message indented as `  [role] HH:MM:SS  text`; `--sort` accepts a comma-separated list of sort keys optionally prefixed with `-` (desc) or `+` (asc) — supported fields: `tokens` (numeric, default desc), `timestamp` (date, default desc), `session` (string, default asc); e.g. `--sort -tokens` for heaviest turns first, `--sort timestamp` for chronological interleaved view, `--sort +session,-tokens` for multi-key sort; when `timestamp` is a sort key the display switches to flat interleaved mode; `--role` accepts user/assistant/tool/system/all; line-mode via `--grep --context` groups by turn; `--sequence Grep,Grep,Read` filters to turns where consecutive tool calls match the given pattern (case-insensitive prefix match on tool name) with `--context-turns N` (default 1) turns of surrounding context; composable turn/message filters: `--has-tool <name>` (turns that used the given tool, case-insensitive prefix), `--errors-only` (turns with ToolResult is_error=true), `--exclude-interrupted` (skip messages containing `[Request interrupted by user]`), `--turn-range N-M` (positional turn window per session), `--min-chars N` / `--max-chars N` (message length bounds); `SortField` + `SortSpec<SortField>` in `messages.rs` (re-exports `SortDir`/`SortKey`/`SortSpec` from `sort.rs`); `MessagesReport`), `mark` (mark/unmark sessions as reviewed; stores one session ID per line in `.normalize/sessions-reviewed`; `MarkReport`), `stats` (token/turn statistics; `--sort` accepts `calls` (desc default), `errors` (desc), `name` (asc) — sorts the per-tool rows in the output; `--by-repo` produces a `RepoStatsReport` grouping all sessions by repo name — per-repo session count, turns, tokens_in/out, error rate, parallelization rate, cost, sorted by total tokens desc; `extract_repo_name` resolves Claude Code's dash-separated directory names back to real project names via `resolve_claude_dir_name` — a cached greedy path-walking algorithm that handles projects with dashes in their name), `ngrams` (n-gram frequency analysis of message text; `--n N` (default 2 = bigrams), `--top K` (default 20), `--role assistant|user|all`; text normalization: lowercase, strip punctuation, collapse whitespace; shows top-K n-grams with ASCII bar chart; `NgramsReport` with total unique n-grams and message count), `patterns` (Markov chain transition matrix analysis of tool call sequences across sessions — computes population-level and per-session transition matrices, outlier detection via Frobenius norm divergence; `--sort` accepts `divergence` (desc default), `tool_count` (desc), `turn_count` (desc), `path` (asc) — sorts the outlier rows; `PatternsReport`), `parallelization` (find sequential same-type tool calls within a turn that could be parallelized; `--threshold N` (default 2) minimum group size; groups identified by same tool name, distinct targets, all in the same turn; `ParallelizationReport`), `heatmap` (per-file read/write counts across sessions; classifies files as `hot` (>5 writes), `read_only` (reads with no writes — potential test gap), `normal`; sorted by `write_count` desc; `--top N` (default 20); `HeatmapReport`), `cost` (per-turn token cost breakdown using model-specific pricing; shows input/output/cache-read/cache-write tokens and estimated USD cost per turn; summary includes total cost, cost-without-cache, cache savings, and cache efficiency %; `CostReport`), `plans` (extract plan-mode content, `PlansListReport`), `subagents` (list and summarize subagent sessions for a parent session, `SubagentsReport`), `analyze` (delegate to normalize-session-analysis), `serve` (optional web UI, gated on `sessions-web` feature). Session path resolution supports literal, prefix, fuzzy matching via `nucleo-matcher`, and subagent ID lookup. `mod.rs` uses `gix` (pure-Rust) to discover git root for project directory resolution (no `git` binary required). The `--mode` flag (interactive/subagent/all) on `list`, `stats`, `messages`, `analyze`, `patterns`, `parallelization`, `heatmap`, `cost` controls which session types are included. `SessionMode` enum handles comma-delimited mode values. `TruncationInfo` (defined in `mod.rs`) carries metadata when `--limit` truncates results — reports include it in both text output (human-readable notice) and JSON output (structured `truncated` field).
