|
@@ -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
|
|
|
|
|
+```
|