Session Logger
Why. Generates rich Markdown reports alongside piβs .jsonl session files β per-turn token breakdown, tool execution stats, file modifications, sub-agent output, and error summaries.
How it works. Hooks into session lifecycle (session_start, session_shutdown), turn events (turn_start, turn_end), message events (message_end), tool events (tool_execution_start, tool_execution_end, tool_call). Tracks: token in/out per turn, thinking tokens, tool execution duration, file modifications (write/edit). On shutdown, writes .md report and .metadata.json alongside the .jsonl file. Toggle with /session-logger. Trust-gated β only generates reports on trusted projects. Latest symlinks for easy access.
Output formats
| Format | File | Description |
|---|---|---|
| JSONL | .pi/sessions/<datetime>_<uuid>.jsonl |
Event stream per session |
| Markdown | .pi/sessions/<sessionId>.md |
Human-readable session summary |
| Metadata | .pi/sessions/<sessionId>.metadata.json |
Structured session metadata |
| Latest symlinks | .pi/sessions/latest.* |
Convenience symlinks |
Reports include sub-agent output from supervisor pipeline agents (developer, auditor, researcher, test-designer) with agent header, status, tool count, token count, duration, and audit score.
Location: .pi/extensions/session-logger/
Comparison with built-in session logging
Pi saves every session as raw JSONL to ~/.pi/agent/sessions/ with tree branching, /tree//fork//clone, compaction, and the /resume picker. Thatβs the storage layer β machine-readable, structured, complete.
Session Logger is a rendering layer on top. It reads piβs JSONL, aggregates the noise into structured summaries. Not competing, complementary.
| Feature | Built-in pi | session-logger |
|---|---|---|
| Raw JSONL storage | β | β (consumes piβs) |
Tree branching / /tree |
β | β |
| Compaction summaries | β | β |
Session picker (/resume) |
β | β |
| Human-readable Markdown report | β | β Per-turn breakdown, totals |
| Per-turn token breakdown | β (raw usage in JSONL) | β Table per turn |
| Tool call stats (count, duration, errors) | β | β Aggregated |
| File modification log | β | β Every write/edit tracked |
| Error summary | β | β Table with counts |
| Sub-agent output (supervisor) | β | β Status, tokens, duration, score |
| Latest symlinks | β | β
latest.md / latest.jsonl |
| Toggle per session | β | β
/session-logger on|off |
Token efficiency for agent self-analysis
When an agent wants to analyze its own past session, format choice matters:
| Format | ~Tokens to read | Problem |
|---|---|---|
| Raw JSONL | 15-20K | Structural keys repeated every line ("type", "toolName", "args", "turnIndex") β huge overhead |
| Markdown report | 2-3K | Collapses 50 tool calls into table rows, no per-event noise |
bash script on JSONL |
~700 | Run node -e ... against JSONL, get exact answer only |
Pattern: Agent wants stats β run bash against JSONL (~700 tokens). Agent wants human overview β read .md (~2-3K). Agent reading raw JSONL directly β worst option (~15-20K).
Details
Architecture
Event-driven pipeline with report generation:
βββ index.ts # Entry: command registration (/session-logger), event wiring, gate management
βββ pipeline.ts # LoggerPipeline: event handlers, state accumulation, report writing
βββ report.ts # Markdown report builder, metadata JSON builder, latest symlink management
βββ types.ts # SessionLoggerGate, tool/event state interfaces
βββ test/ # Pipeline + report generator tests
Event Flow
flowchart TD
subgraph Events
A[session_start] --> B[Initialize session state]
C[model_select] --> D[Track model name/info]
E[thinking_level_select] --> F[Track thinking level]
G[turn_start] --> H[New turn entry]
I[message_end] --> J[Capture token usage]
K[tool_execution_start] --> L[Start tool timer]
M[tool_execution_end] --> N[Record tool result + duration]
O[tool_call] --> P[Detect file modifications]
Q[session_shutdown] --> R[Write .md + .metadata.json + symlinks]
S[session_compact] --> T[Reset accumulated state]
end
subgraph Output
R --> U[.md: human-readable summary]
R --> V[metadata.json: structured per-turn data]
R --> W[latest.md symlink]
R --> X[latest.metadata.json symlink]
end
Report Sections (Markdown)
The generated .md report includes:
# Session Report: <session_id>
## Overview
- Duration: <elapsed>
- Model: <model_name>
- Total Turns: <N>
- Total Tokens: <in>/<out>/<thinking>
- Total Tool Calls: <N>
- Errors: <N>
- Files Modified: <N>
## Turn-by-Turn Breakdown
| Turn | Tokens In | Tokens Out | Thinking | Tools | Duration |
|------|-----------|------------|----------|-------|----------|
| 1 | ... | ... | ... | ... | ... |
## Tool Calls
| Tool | Args | Duration | Status |
|------|------|----------|--------|
## File Modifications
| File | Action |
|------|--------|
## Sub-Agent Output (supervisor)
- Agent: developer β toolCount, tokenCount, duration
- Agent: auditor β toolCount, tokenCount, duration, auditScore
## Errors
- <error messages>
Key Design Decisions
- Toggle between sessions β
/session-logger on|offtakes effect on NEXT session start. Current session unaffected. State persisted in.pi/state/session-extensions.json. - Trust-gated β Reports only generated on trusted projects.
isProjectTrusted()checked onsession_shutdown. Untrusted projects skip report generation entirely. - Latest symlinks β
latest.md,latest.metadata.json,latest.jsonlsymlinks for easy access. Created on each session shutdown. Overwrite previous latest. - File modification tracking β Intercepted at
tool_calllevel forwrite/edittools. Tracked as{ file, action, timestamp }entries. - Sub-agent output β Extracts structured output from supervisor pipeline agents (developer, auditor, researcher, test-designer) including agent name, tool count, token count, duration, and audit score.
- Compact support β
session_compactevent resets accumulated state but preserves session file.
Testing
Tests cover:
- Pipeline: all event handlers, state accumulation, write
- Report generator: markdown formatting, metadata JSON, symlink creation
- Gate: toggle on/off, persistence, cross-session state
- File modification tracking: write/edit detection, multiple files
- Sub-agent output parsing: structured JSON extraction