ln-002-session-analyzer
Paths: File paths (
shared/,references/,../ln-*) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root. Ifshared/is missing, fetch files via WebFetch fromhttps://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path}.
Session Analyzer (Standalone Utility)
Type: Standalone Utility Category: 0XX Shared
Analyzes a session for errors, inefficiencies, and improvement opportunities. Produces actionable fixes for skills, tools, hooks, and communication style.
Scope: Single-session deep analysis (10 dimensions). Broader than protocol self-audit, narrower than /audit-sessions batch.
For skill self-audit: shared/references/meta_analysis_protocol.md §7. For multi-day patterns: /audit-sessions.
When to Use This Skill
- After completing a task — find what went wrong and how to improve
- Periodically — audit recent sessions for patterns
- After a skill run — analyze how well the skill instructions worked
- When debugging tool/hook issues — find root causes in session data
Input
$ARGUMENTS:
- (empty) — analyze current session (conversation context)
recent— scan latest JSONL session per agent (Claude, Codex){skill-name}— focus analysis on that skill's execution within the session
hex-line is an optional accelerator for large local session logs and repo files. If MCP is unavailable, continue with built-in Read/Grep/Glob/Bash; this skill must never block on MCP connectivity.
Dimensions
| # | Dimension | Scan for | Improvement target |
|---|---|---|---|
| D1 | Tool Errors | NOOP_EDIT, TEXT_NOT_FOUND, hash mismatch, out of range | SKILL.md steps — add paths, anchors |
| D2 | Tool Waste | Full reads without outline, repeated reads, bash fallbacks | SKILL.md — "outline first", name MCP tools |
| D3 | Process Issues | Tool loops 3+, retry storms, dead ends, wrong targets | SKILL.md phases — decompose |
| D4 | Script Extraction | Ad-hoc bash/python scripts written each run | references/scripts/ |
| D5 | Hook & Permission | Hook blocks, permission denials, built-in instead of MCP | Hook config, allowed-tools |
| D6 | Communication | Over-explaining, missing status, unnecessary confirmations | CLAUDE.md prefs, skill output notes |
| D7 | Decision Quality | Dead ends before pivot, trial-and-error, slow error detection | SKILL.md decision trees, step clarity |
| D8 | Context Pressure | Re-reading same files, re-asking resolved, thread loss | Caching notes, compact instructions |
| D9 | Subagent Quality | Empty results, timeouts, overbroad prompts | Agent prompts, timeout settings |
| D10 | Scope Drift | Deviation from goal, accidental expansion, pivot without reason | Scope guards, goal gates |
Phase 1: Collect Session Data
Determine source based on $ARGUMENTS:
Current session (empty args)
Scan conversation context directly. You have access to all tool call results, errors, and messages.
Recent sessions (recent arg)
Find latest session per agent:
echo "=== LATEST SESSIONS ==="
echo "## Claude"
CLAUDE_LATEST=$(stat -c '%Y %n' ~/.claude/projects/*/*.jsonl 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)
[ -n "$CLAUDE_LATEST" ] && echo " $CLAUDE_LATEST ($(wc -l < "$CLAUDE_LATEST") lines)" || echo " No sessions found"
echo "## Claude Active Sessions"
for f in "$HOME/.claude/sessions"/*.json; do
[ -f "$f" ] || continue
PID=$(basename "$f" .json)
kill -0 "$PID" 2>/dev/null && echo " ACTIVE: $(cat "$f")" || echo " STALE: PID=$PID"
done
echo "## Codex"
CODEX_LATEST=$(stat -c '%Y %n' ~/.codex/sessions/????/??/??/rollout-*.jsonl 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)
[ -n "$CODEX_LATEST" ] && echo " $CODEX_LATEST ($(wc -l < "$CODEX_LATEST") lines)" || echo " No sessions found"
Extract raw data from JSONL session
Run for each found session file ($F):
echo "=== TOOL CALLS ==="
grep -oE '"name"\s*:\s*"[^"]*"' "$F" 2>/dev/null | sed 's/"name"\s*:\s*"//;s/"//' | sort | uniq -c | sort -rn | head -30
echo "=== ERRORS ==="
grep -oE 'NOOP_EDIT|TEXT_NOT_FOUND|FILE_NOT_FOUND|HASH_HINT|DANGEROUS|out of range|mismatch|tool_use_error|permission denied' "$F" 2>/dev/null | sort | uniq -c | sort -rn
echo "=== TOOL LOOPS (3+ consecutive) ==="
grep -oE '"name"\s*:\s*"[^"]*"' "$F" 2>/dev/null | sed 's/"name"\s*:\s*"//;s/"//' | uniq -c | sort -rn | awk '$1 >= 3'
echo "=== BUILT-IN vs MCP ==="
grep -oE '"name"\s*:\s*"(Read|Edit|Write|Grep|mcp__hex-line__\w+)"' "$F" 2>/dev/null | sed 's/.*"name"\s*:\s*"//;s/"//' | sort | uniq -c | sort -rn
echo "=== HOOK EVENTS ==="
grep -oE 'hook_progress|blocking error|PreToolUse|PostToolUse|hex-confirmed|Obligatory use|Use mcp__hex-line' "$F" 2>/dev/null | sort | uniq -c | sort -rn
echo "=== SKILL/COMMAND INVOCATIONS ==="
grep -oE '"display":\s*"/[a-z-]+' "$F" 2>/dev/null | sed 's/"display":\s*"//' | sort | uniq -c | sort -rn
Treat keyword-based error counts as heuristic only. Confirm that reported matches come from actual tool failure/result events, not from prompts, templates, or referenced docs that contain the same strings.
Extract token statistics from Claude JSONL
Run for Claude session file ($F) to get real token usage:
echo "=== TOKEN STATS ==="
TOTAL_IN=$(grep -oE '"input_tokens":[0-9]+' "$F" | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null)
TOTAL_OUT=$(grep -oE '"output_tokens":[0-9]+' "$F" | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null)
CACHE_CREATE=$(grep -oE '"cache_creation_input_tokens":[0-9]+' "$F" | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null)
CACHE_READ=$(grep -oE '"cache_read_input_tokens":[0-9]+' "$F" | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null)
echo "in=${TOTAL_IN:-0} out=${TOTAL_OUT:-0} cache_create=${CACHE_CREATE:-0} cache_read=${CACHE_READ:-0}"
Phase 2: Analyze by Dimensions
Apply D1-D10 to collected data. Classify each finding:
| Severity | Dimensions | Meaning |
|---|---|---|
| Error | D1, D5 | Something broke — tool failed, permission denied |
| Waste | D2, D4, D8 | Unnecessary work — redundant reads, ad-hoc scripts, re-gathering |
| Pattern | D3, D6, D7, D9, D10 | Improvable behavior — loops, communication, decisions |
D1: Tool Errors
Count by type: NOOP_EDIT, TEXT_NOT_FOUND, hash mismatch, out of range, FILE_NOT_FOUND. For each, identify which step/phase caused it.
D2: Tool Waste
- Reads without preceding outline (file >100 lines)
- Same file read 3+ times
- Bash
cat/grep/head/sedwhen MCP equivalent exists
D3: Process Issues
- Tool loops: same tool on same file 3+ times without progress
- Retry storms: 3+ attempts with different parameters
- Dead ends: approach explored then abandoned
- Wrong target: looked at file X when needed Y
D4: Script Extraction
- Bash/Python scripts written during session
- If script would be needed on every run of the skill → candidate for
references/scripts/
D5: Hook & Permission
- Hook blocks (PreToolUse/PostToolUse blocking errors)
- Built-in Read/Edit/Write/Grep used when MCP enforced
hex-confirmedbypasses — were they justified?
D6: Communication
- Message length distribution (over-explaining vs terse)
- Unnecessary confirmations ("shall I proceed?")
- Missing status updates at milestones
- Redundant summaries
D7: Decision Quality
- Time to detect error and pivot (tool calls between error and correction)
- Trial-and-error sequences vs targeted approach
- Tool selection reasoning (used wrong tool first)
D8: Context Pressure
- Same file read multiple times across phases
- Information re-gathered that was already available
- Signs of thread loss (re-asking resolved questions)
D9: Subagent Quality
- Agent tool invocations with empty or low-value results
- Agent timeouts
- Overbroad prompts (agent did too much or too little)
D10: Scope Drift
- Initial goal vs actual deliverables — any deviation?
- Unplanned additions during execution
- Pivots without explicit reason
Phase 3: Map to Fixes
For each finding, determine specific target and fix:
| Target type | Example |
|---|---|
| SKILL.md step | "ln-400 Step 2: add file path src/config.ts" |
| SKILL.md phase | "ln-300 Phase 3: decompose into 3a-3c sub-steps" |
allowed-tools |
"ln-400: add mcp__hex-line__edit_file" |
| Hook config | "settings.json: add exception for npm test" |
references/scripts/ |
"ln-520: move test_harness.sh to references/scripts/" |
| CLAUDE.md | "Add preference: terse responses, no trailing summaries" |
| MCP tool | "hex-line edit_file: hash mismatch on concurrent edits" |
| Agent prompt | "ln-310 Agent A: narrow scope to security-only" |
| Scope guard | "ln-400: add Goal Articulation Gate at Phase 1" |
Phase 4: Report
Output to chat per shared/references/meta_analysis_protocol.md format.
### Session Analysis: {session identifier}
#### Improvements
| # | Dim | Finding | Target | Fix |
|---|-----|---------|--------|-----|
| 1 | D1 | 3 edit failures Phase 4 | ln-400 Step 2 | Add file path |
| 2 | D4 | test.sh written ad-hoc | ln-520 | Move to references/scripts/ |
| 3 | D6 | Over-explained 5 times | CLAUDE.md | Add "terse" pref |
| 4 | D5 | Hook blocked Read 4x | settings.json | Add MCP permission |
#### Session Errors
| Problem Type | Count | Examples |
|-------------|-------|---------|
| Retry storm | 4 | 3x edit_file on config.ts |
| Wrong target | 2 | Read utils.ts not helpers.ts |
#### Subagent Errors: {Agent Name} (per agent, if any)
| Problem Type | Count | Examples |
|-------------|-------|---------|
| {type} | {N} | {brief} |
IF no findings AND no errors: "Session analysis: clean run."
Anti-Patterns
| Do NOT | Instead |
|---|---|
| Define own output template | Reference protocol format |
| Analyze files not in session | Only analyze what was actually used |
| Generic recommendations | Each fix tied to specific file + location |
| Report OK dimensions | Only findings with issues |
Phase 5: Meta-Analysis
MANDATORY READ: Load shared/references/meta_analysis_protocol.md
Analyze this session per protocol §7. Output per protocol format.
Definition of Done
- D1-D10 dimensions checked
- JSONL scanning works (
recentmode) - Each finding has specific Target + Fix
- Output per protocol format (improvements-only)
- No template duplication
- Meta-Analysis run
Version: 1.1.0 Last Updated: 2026-04-05