Generate a session postmortem/retrospective analyzing what went well, what went wrong, and improvement opportunities
Analyzes session transcripts to generate postmortem reports with improvement recommendations.
/plugin marketplace add melodic-software/claude-code-plugins/plugin install claude-code-observability@melodic-software[session-id] [--current] [--days N]Analyze a session transcript to generate a postmortem/retrospective report with improvement recommendations.
| Argument | Description |
|---|---|
session-id | Specific session ID to analyze |
--current | Analyze current session (default) |
--days N | Analyze sessions from last N days |
| (no args) | Analyze most recent completed session |
Session files are JSONL with records like:
{"type":"user","message":{"role":"user","content":"Fix the login bug"}}
{"type":"assistant","message":{"role":"assistant","content":"I'll help..."}}
{"type":"summary","summary":"Session summary text..."}
| Category | What We Look For |
|---|---|
| Success Patterns | Clean tool calls, efficient paths, good outcomes |
| Failure Patterns | Errors, retries, failed attempts, corrections |
| Context Usage | Files read, context bloat, compaction events |
| Tool Efficiency | Tool call counts, retry rates, edit failures |
| Time Distribution | Where time was spent (if timestamps available) |
import json
from pathlib import Path
from datetime import datetime, timezone
claude_dir = Path.home() / ".claude"
projects_dir = claude_dir / "projects"
# Find current project's session directory
# Project paths are encoded: D:-repos-project -> D--repos-project
current_project = Path.cwd()
project_encoded = str(current_project).replace(":", "").replace("/", "-").replace("\\", "-")
session_dir = projects_dir / project_encoded
if not session_dir.exists():
print(f"No sessions found for current project")
exit(1)
# Find sessions (exclude agent-* files)
sessions = [f for f in session_dir.glob("*.jsonl") if not f.name.startswith("agent-")]
sessions.sort(key=lambda f: f.stat().st_mtime, reverse=True)
def parse_session(session_path):
"""Parse session JSONL into structured data."""
messages = []
summaries = []
tool_calls = []
with open(session_path) as f:
for line in f:
record = json.loads(line)
record_type = record.get("type")
if record_type == "user":
messages.append({"role": "user", "content": record["message"]["content"]})
elif record_type == "assistant":
content = record["message"].get("content", "")
messages.append({"role": "assistant", "content": content})
# Extract tool calls from assistant messages
# (simplified - actual format may vary)
elif record_type == "summary":
summaries.append(record["summary"])
return {
"messages": messages,
"summaries": summaries,
"message_count": len(messages),
"user_turns": sum(1 for m in messages if m["role"] == "user"),
"assistant_turns": sum(1 for m in messages if m["role"] == "assistant")
}
def analyze_session(parsed):
"""Identify success and failure patterns."""
analysis = {
"successes": [],
"failures": [],
"improvements": []
}
# Look for patterns in messages
for i, msg in enumerate(parsed["messages"]):
content = msg.get("content", "")
# Failure indicators
if any(phrase in content.lower() for phrase in [
"error", "failed", "let me try again", "sorry",
"that didn't work", "retry", "fix that"
]):
analysis["failures"].append({
"turn": i,
"type": "retry_pattern",
"snippet": content[:100]
})
# Success indicators
if any(phrase in content.lower() for phrase in [
"successfully", "completed", "done", "finished",
"works", "passed"
]):
analysis["successes"].append({
"turn": i,
"type": "completion",
"snippet": content[:100]
})
return analysis
def generate_recommendations(analysis, parsed):
"""Generate improvement recommendations."""
recommendations = {
"claude_md": [],
"hooks": [],
"commands": [],
"prompting": []
}
# High retry rate -> CLAUDE.md guidance
failure_count = len(analysis["failures"])
if failure_count > 3:
recommendations["claude_md"].append(
"Consider adding guidance to CLAUDE.md about common failure patterns"
)
# Edit tool failures on Windows -> hook opportunity
edit_failures = [f for f in analysis["failures"] if "edit" in f.get("snippet", "").lower()]
if edit_failures:
recommendations["hooks"].append(
"Consider PreToolUse hook for Edit -> suggest sed fallback on Windows"
)
# Large file reads -> subagent delegation
# (would need to track file sizes)
recommendations["prompting"].append(
"For file exploration tasks, prefer subagents to preserve main context"
)
return recommendations
# Session Retrospective
**Session ID:** abc123-def456
**Date:** 2025-12-30
**Duration:** ~45 minutes
**Turns:** 23 user, 23 assistant
## Summary
This session focused on implementing user configuration management tooling.
## What Went Well
### Efficient Patterns (5 instances)
- Successfully created 6 commands with minimal iterations
- Efficient use of parallel subagents for exploration
- Good recovery from initial Edit tool failure
### Tool Usage Highlights
- Read tool: 15 calls (no failures)
- Write tool: 8 calls (all successful)
- Task tool: 3 calls (parallel execution)
## What Could Improve
### Failure Patterns (3 instances)
- 2 Edit tool retries on Windows config files
- 1 path resolution issue (forward vs backslash)
- Context grew large before compaction (could have used /clear earlier)
### Inefficiencies
- Read 12 files to find 3 relevant ones (could use grep first)
- Repeated MCP queries for same topic (could cache results)
## Improvement Recommendations
### CLAUDE.md Additions
```markdown
- Use sed instead of Edit tool on Windows for .editorconfig files
- Prefer subagents for file exploration tasks to preserve context
- Use grep before Read to narrow file search
| Hook Type | Trigger | Action |
|---|---|---|
| PreToolUse | Edit on Windows + config file | Suggest sed fallback |
| PostToolUse | MCP query | Consider caching frequent queries |
/cleanup-sessions could auto-suggest based on storage patterns| Metric | Value |
|---|---|
| Total turns | 46 |
| Tool calls | 38 |
| Retries | 3 (7.9%) |
| Compaction events | 1 |
| Subagents spawned | 3 |
| Action | Count | Examples |
|---|---|---|
| Read | 15 | known-structure.yaml, user-config-status.md |
| Written | 8 | user-config-backup.md, user-config-restore.md |
| Edited | 2 | SKILL.md (retry), index.yaml |
Sessions with similar patterns:
xyz789 (2025-12-29) - Also had Edit retriesuvw456 (2025-12-28) - Similar file exploration task/user-config:transcript-search - Search across sessions/user-config:prompt-extract - Extract successful prompts/user-config:session-stats - Aggregate statisticsThis command uses the user-config-management skill for: