Installs into .claude/skills of the current project.
Are you the author of Session Insights?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/ilyagorsky-session-insights)
---
name: session-insights
description: Extract insights from past .jsonl sessions — problems, decisions, friction points. Analyzes sessions you can't see in current context.
user-invocable: true
argument-hint: "[ticket|session-id|workstream]"
---
# /session-insights — Extract insights from past sessions
Parse `.jsonl` session transcripts and extract structured insights: problems, decisions, patterns, friction points. Works on sessions outside the current context.
## Step 1: Find sessions
Resolve memory directory, then find sessions by argument:
```bash
# Transcripts are stored per launch cwd (a monorepo subdir gets its own dir), memory per git root
SESSIONS_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/projects/$(pwd | sed 's/[^a-zA-Z0-9]/-/g')/"
```
- **Ticket/keyword** — grep across all `.jsonl` files
- **Session ID** — specific file by UUID
- **Workstream** — use `node "${CLAUDE_PLUGIN_ROOT}/scripts/memory.js" workstream <name>` for context, match by dates/keywords
- **No argument** — most recent session
```bash
grep -l "<query>" "$SESSIONS_DIR"*.jsonl 2>/dev/null | head -10
```
Also check session index if available:
```bash
cat "$(node "${CLAUDE_PLUGIN_ROOT}/scripts/memory.js" dir)/sessions.jsonl" 2>/dev/null
```
## Step 2: Extract user messages
For each session found:
```python
import json, sys
with open(sys.argv[1]) as f:
for i, line in enumerate(f):
try:
obj = json.loads(line.strip())
if obj.get('type') != 'user':
continue
c = obj.get('message', {}).get('content', obj.get('content', ''))
if isinstance(c, list):
for item in c:
if isinstance(item, dict) and item.get('type') == 'text':
text = item.get('text', '').strip()
if text and not text.startswith('<') and len(text) > 5:
print(text[:300])
elif isinstance(c, str):
text = c.strip()
if text and not text.startswith('<') and len(text) > 5:
print(text[:300])
except:
pass
```
## Step 3: Analyze
Extract structured insights from the user messages:
1. **Problems** — what didn't work, was redone, caused friction
2. **Decisions** — what was chosen and why (architectural, process)
3. **Insights** — non-obvious conclusions, patterns, reassessments
4. **Friction points** — where the agent repeatedly failed, what required many iterations
Format:
```
## Session insights: <date range or session id>
### Problems
- <description> → <resolution or status>
### Decisions
- <what> — <why>
### Insights
- <insight> — <evidence from session>
### Friction
- <what> (×N iterations) — <root cause>
```
## Step 4: Save
**MUST present all options as a numbered menu and wait for user response before writing anything:**
```
What to do with these insights?
1. Save insights to memory (feedback/ or decisions/)
2. Add friction points to backlog
3. Mark as DOC: for /docs-reflect
4. Skip — display only
Choose (1-4, or comma-separated):
```
Then execute only what the user chose.
## Rules
- Filter system messages, ide_opened_file, tool calls — only USER text
- Large sessions (>50KB user text) — split into chunks
- Don't dump raw output — format into readable blocks
- If multiple sessions found for a query — combine chronologically
- If session index (`sessions.jsonl`) exists — use it for faster lookup