Claude-skill-registry introspect
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.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/introspect" ~/.claude/skills/majiayu000-claude-skill-registry-introspect && rm -rf "$T"
manifest:
skills/data/introspect/SKILL.mdsource content
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
# 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 messages | , , |
| Claude responses | , , |
| Reasoning blocks | , (in content array) |
| Tool invocations | , , (in content array) |
| Tool outputs | , |
| Conversation summaries | , |
| File state checkpoints | File contents at point in time |
| System context | Initial context, rules |
Core Analysis Patterns
List Sessions for Current Project
# 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
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
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
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
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
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
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
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
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
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
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 | |
| Entry types | |
| Tool stats | |
| Extract thinking | |
| Find errors | |
| Session summaries | |
| User messages | |
Usage Examples
"What tools did I use most in yesterday's session?"
# 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"
# 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?"
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:
- Review for credentials, API keys, personal data
- Consider redacting file paths if they reveal project structure
- Thinking blocks may contain candid assessments
Export Formats
Markdown Report
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)
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