home / skills / 0xdarkmatter / claude-mods / introspect
This skill analyzes Claude Code session logs to extract thinking patterns, tool usage, and errors, improving debugging and workflow efficiency.
npx playbooks add skill 0xdarkmatter/claude-mods --skill introspectReview the files below or copy the command above to add this skill to your agents.
---
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
```
This skill inspects Claude Code session logs and extracts actionable intelligence to improve debugging, tool usage, and reasoning workflows. It summarizes session structure, pulls out thinking blocks, quantifies tool invocations, and surfaces recurring error patterns. Use it to turn raw .jsonl transcripts into focused insights for faster iteration.
The skill parses project session files under ~/.claude/projects, reading entry types like user, assistant, thinking, tool_use, and tool_result. It runs jq- and shell-based queries to produce session overviews, tool frequency tables, thinking/reasoning extracts, error counts, and file-edit histories. Outputs include quick CLI summaries, Markdown reports, or JSON exports for further analysis.
Will the skill expose secrets in logs?
Yes — session logs may include file contents, credentials, and thinking text. Always review and redact before sharing.
How do I limit analysis to a single project?
Encode the current path to match project folder names (double-dash encoding) and run commands against ~/.claude/projects/PROJECT_NAME/*.jsonl.
Can I export results for automation?
Yes — the skill can emit structured JSON or a Markdown report suitable for pipelines or issue tracking.
How are thinking blocks identified?
Thinking blocks are entries of type "thinking" inside assistant message.content; the skill extracts them with jq filters alongside surrounding response context.