Browse Source

feat(skills): Add introspect skill for session log analysis

Extract insights from Claude Code session logs:
- Tool usage statistics across sessions
- Thinking block extraction (reasoning traces)
- Error pattern analysis
- Conversation flow reconstruction
- Subagent analysis

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
0xDarkMatter 2 months ago
parent
commit
d372f6b1af
1 changed files with 324 additions and 0 deletions
  1. 324 0
      skills/introspect/SKILL.md

+ 324 - 0
skills/introspect/SKILL.md

@@ -0,0 +1,324 @@
+---
+name: introspect
+description: "Analyze Claude Code session logs - extract thinking blocks, tool usage stats, error patterns, debug trajectories. Triggers on: introspect, session logs, trajectory, analyze sessions, what went wrong, tool usage, thinking blocks, session history, my reasoning, past sessions, what did I do."
+allowed-tools: "Bash Read Grep Glob"
+---
+
+# Introspect
+
+Extract actionable intelligence from Claude Code session logs. Analyze tool usage, reasoning patterns, errors, and conversation flow to improve workflows and debug issues.
+
+## Log File Structure
+
+```
+~/.claude/
+├── history.jsonl                              # Global: all user inputs across projects
+├── projects/
+│   └── {project-path}/                        # e.g., X--Dev-claude-mods/
+│       ├── sessions-index.json                # Session metadata index
+│       ├── {session-uuid}.jsonl               # Full session transcript
+│       └── agent-{short-id}.jsonl             # Subagent transcripts
+```
+
+### Project Path Encoding
+
+Project paths use double-dash encoding: `X:\Dev\claude-mods` → `X--Dev-claude-mods`
+
+```bash
+# Find project directory for current path
+project_dir=$(pwd | sed 's/[:\\\/]/-/g' | sed 's/--*/-/g')
+ls ~/.claude/projects/ | grep -i "${project_dir##*-}"
+```
+
+## Entry Types in Session Files
+
+| Type | Contains | Key Fields |
+|------|----------|------------|
+| `user` | User messages | `message.content`, `uuid`, `timestamp` |
+| `assistant` | Claude responses | `message.content[]`, `cwd`, `gitBranch` |
+| `thinking` | Reasoning blocks | `thinking`, `signature` (in content array) |
+| `tool_use` | Tool invocations | `name`, `input`, `id` (in content array) |
+| `tool_result` | Tool outputs | `tool_use_id`, `content` |
+| `summary` | Conversation summaries | `summary`, `leafUuid` |
+| `file-history-snapshot` | File state checkpoints | File contents at point in time |
+| `system` | System context | Initial context, rules |
+
+## Core Analysis Patterns
+
+### List Sessions for Current Project
+
+```bash
+# Get sessions index
+cat ~/.claude/projects/X--Dev-claude-mods/sessions-index.json | jq '.'
+
+# List session files with sizes and dates
+ls -lah ~/.claude/projects/X--Dev-claude-mods/*.jsonl | grep -v agent
+```
+
+### Session Overview
+
+```bash
+SESSION="417ce03a-6fc7-4906-b767-6428338f34c3"
+PROJECT="X--Dev-claude-mods"
+
+# Entry type distribution
+jq -r '.type' ~/.claude/projects/$PROJECT/$SESSION.jsonl | sort | uniq -c
+
+# Session duration (first to last timestamp)
+jq -s '[.[].timestamp // .[].message.timestamp | select(.)] | [min, max] | map(. / 1000 | strftime("%Y-%m-%d %H:%M"))' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl
+
+# Conversation summaries (quick overview)
+jq -r 'select(.type == "summary") | .summary' ~/.claude/projects/$PROJECT/$SESSION.jsonl
+```
+
+### Tool Usage Statistics
+
+```bash
+PROJECT="X--Dev-claude-mods"
+
+# Tool frequency across all sessions
+cat ~/.claude/projects/$PROJECT/*.jsonl | \
+  jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' | \
+  sort | uniq -c | sort -rn
+
+# Tool frequency for specific session
+jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl | sort | uniq -c | sort -rn
+
+# Tools with their inputs (sampled)
+jq -c 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | {tool: .name, input: .input}' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl | head -20
+```
+
+### Extract Thinking Blocks
+
+```bash
+SESSION="417ce03a-6fc7-4906-b767-6428338f34c3"
+PROJECT="X--Dev-claude-mods"
+
+# All thinking blocks (reasoning trace)
+jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "thinking") | .thinking' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl
+
+# Thinking blocks with context (which turn)
+jq -r 'select(.type == "assistant") |
+  .message.content as $content |
+  ($content | map(select(.type == "thinking")) | .[0].thinking) as $thinking |
+  ($content | map(select(.type == "text")) | .[0].text | .[0:100]) as $response |
+  select($thinking) | "---\nThinking: \($thinking[0:500])...\nResponse: \($response)..."' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl
+```
+
+### Error Analysis
+
+```bash
+PROJECT="X--Dev-claude-mods"
+
+# Find tool errors across sessions
+cat ~/.claude/projects/$PROJECT/*.jsonl | \
+  jq -r 'select(.type == "user") | .message.content[]? | select(.type == "tool_result") |
+    select(.content | test("error|Error|ERROR|failed|Failed|FAILED"; "i")) |
+    {tool_id: .tool_use_id, error: .content[0:200]}' 2>/dev/null | head -50
+
+# Count errors by pattern
+cat ~/.claude/projects/$PROJECT/*.jsonl | \
+  jq -r 'select(.type == "user") | .message.content[]? | select(.type == "tool_result") | .content' 2>/dev/null | \
+  grep -i "error\|failed\|exception" | \
+  sed 's/[0-9]\+//g' | sort | uniq -c | sort -rn | head -20
+```
+
+### Search Across Sessions
+
+```bash
+PROJECT="X--Dev-claude-mods"
+
+# Search user messages
+cat ~/.claude/projects/$PROJECT/*.jsonl | \
+  jq -r 'select(.type == "user") | .message.content[]? | select(.type == "text") | .text' | \
+  grep -i "pattern"
+
+# Search assistant responses
+cat ~/.claude/projects/$PROJECT/*.jsonl | \
+  jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "text") | .text' | \
+  grep -i "pattern"
+
+# Find sessions mentioning a file
+for f in ~/.claude/projects/$PROJECT/*.jsonl; do
+  if grep -q "specific-file.ts" "$f"; then
+    echo "Found in: $(basename $f)"
+  fi
+done
+```
+
+### Conversation Flow Reconstruction
+
+```bash
+SESSION="417ce03a-6fc7-4906-b767-6428338f34c3"
+PROJECT="X--Dev-claude-mods"
+
+# Reconstruct conversation (user/assistant turns)
+jq -r '
+  if .type == "user" then
+    .message.content[]? | select(.type == "text") | "USER: \(.text[0:200])"
+  elif .type == "assistant" then
+    .message.content[]? | select(.type == "text") | "CLAUDE: \(.text[0:200])"
+  else empty end
+' ~/.claude/projects/$PROJECT/$SESSION.jsonl
+```
+
+### Subagent Analysis
+
+```bash
+PROJECT="X--Dev-claude-mods"
+
+# List subagent sessions
+ls ~/.claude/projects/$PROJECT/agent-*.jsonl 2>/dev/null
+
+# Subagent tool usage
+for f in ~/.claude/projects/$PROJECT/agent-*.jsonl; do
+  echo "=== $(basename $f) ==="
+  jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' "$f" | \
+    sort | uniq -c | sort -rn | head -5
+done
+```
+
+## Advanced Analysis
+
+### Token/Cost Estimation
+
+```bash
+SESSION="417ce03a-6fc7-4906-b767-6428338f34c3"
+PROJECT="X--Dev-claude-mods"
+
+# Rough character count (tokens ≈ chars/4)
+jq -r '[
+  (select(.type == "user") | .message.content[]? | select(.type == "text") | .text | length),
+  (select(.type == "assistant") | .message.content[]? | select(.type == "text") | .text | length)
+] | add' ~/.claude/projects/$PROJECT/$SESSION.jsonl | \
+  awk '{sum+=$1} END {print "Total chars:", sum, "Est tokens:", int(sum/4)}'
+```
+
+### File Modification Tracking
+
+```bash
+SESSION="417ce03a-6fc7-4906-b767-6428338f34c3"
+PROJECT="X--Dev-claude-mods"
+
+# Files edited (Edit tool usage)
+jq -r 'select(.type == "assistant") | .message.content[]? |
+  select(.type == "tool_use" and .name == "Edit") | .input.file_path' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl | sort | uniq -c | sort -rn
+
+# Files written
+jq -r 'select(.type == "assistant") | .message.content[]? |
+  select(.type == "tool_use" and .name == "Write") | .input.file_path' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl | sort | uniq
+```
+
+### Session Comparison
+
+```bash
+PROJECT="X--Dev-claude-mods"
+SESSION1="session-id-1"
+SESSION2="session-id-2"
+
+# Compare tool usage between sessions
+echo "=== Session 1 ===" && \
+jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' \
+  ~/.claude/projects/$PROJECT/$SESSION1.jsonl | sort | uniq -c | sort -rn
+
+echo "=== Session 2 ===" && \
+jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' \
+  ~/.claude/projects/$PROJECT/$SESSION2.jsonl | sort | uniq -c | sort -rn
+```
+
+## Quick Reference Commands
+
+| Task | Command Pattern |
+|------|-----------------|
+| List sessions | `ls -lah ~/.claude/projects/$PROJECT/*.jsonl \| grep -v agent` |
+| Entry types | `jq -r '.type' $SESSION.jsonl \| sort \| uniq -c` |
+| Tool stats | `jq -r '... \| select(.type == "tool_use") \| .name' \| sort \| uniq -c` |
+| Extract thinking | `jq -r '... \| select(.type == "thinking") \| .thinking'` |
+| Find errors | `grep -i "error\|failed" $SESSION.jsonl` |
+| Session summaries | `jq -r 'select(.type == "summary") \| .summary'` |
+| User messages | `jq -r 'select(.type == "user") \| .message.content[]?.text'` |
+
+## Usage Examples
+
+### "What tools did I use most in yesterday's session?"
+
+```bash
+# Find yesterday's sessions by modification time
+find ~/.claude/projects/X--Dev-claude-mods -name "*.jsonl" -mtime -1 ! -name "agent-*" | \
+  xargs -I{} jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' {} | \
+  sort | uniq -c | sort -rn
+```
+
+### "Show me my reasoning when debugging the auth issue"
+
+```bash
+# Search for sessions mentioning auth, then extract thinking
+for f in ~/.claude/projects/$PROJECT/*.jsonl; do
+  if grep -qi "auth" "$f"; then
+    echo "=== $(basename $f) ==="
+    jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "thinking") | .thinking' "$f" | \
+      grep -i -A5 -B5 "auth"
+  fi
+done
+```
+
+### "What errors occurred most frequently this week?"
+
+```bash
+find ~/.claude/projects/ -name "*.jsonl" -mtime -7 | \
+  xargs cat 2>/dev/null | \
+  jq -r 'select(.type == "user") | .message.content[]? | select(.type == "tool_result") | .content' 2>/dev/null | \
+  grep -i "error\|failed" | \
+  sed 's/[0-9]\+//g' | sed 's/\/[^ ]*//g' | \
+  sort | uniq -c | sort -rn | head -10
+```
+
+## Privacy Considerations
+
+Session logs contain:
+- Full conversation history including any sensitive data discussed
+- File contents that were read or written
+- Thinking/reasoning (internal deliberation)
+- Tool inputs/outputs
+
+**Before sharing session exports:**
+1. Review for credentials, API keys, personal data
+2. Consider redacting file paths if they reveal project structure
+3. Thinking blocks may contain candid assessments
+
+## Export Formats
+
+### Markdown Report
+
+```bash
+SESSION="session-id"
+PROJECT="X--Dev-claude-mods"
+
+echo "# Session Report: $SESSION"
+echo ""
+echo "## Summary"
+jq -r 'select(.type == "summary") | "- \(.summary)"' ~/.claude/projects/$PROJECT/$SESSION.jsonl
+echo ""
+echo "## Tool Usage"
+jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name' \
+  ~/.claude/projects/$PROJECT/$SESSION.jsonl | sort | uniq -c | sort -rn | \
+  awk '{print "| " $2 " | " $1 " |"}'
+```
+
+### JSON Export (for further processing)
+
+```bash
+jq -s '{
+  session_id: "'$SESSION'",
+  entries: length,
+  tools: [.[] | select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | .name] | group_by(.) | map({tool: .[0], count: length}),
+  summaries: [.[] | select(.type == "summary") | .summary]
+}' ~/.claude/projects/$PROJECT/$SESSION.jsonl
+```