Setting the file. One moment. Analyze Session Logs · Retrospecting · bitwarden/ai-plugins · Skills DocsRunning Work Transitions
Raw file
scripts/analyze-session-logs.sh
Shell·178 lines·5 KB
13 echo "Arguments:"
14 echo " session-log.jsonl - Claude Code native session log (JSONL format)"
15 echo ""
16 echo "Example:"
17 echo " PROJECT_DIR=\$(echo \"\${PWD}\" | sed 's/\\//-/g')"
18 echo " LATEST_LOG=\$(ls -t ~/.claude/projects/\${PROJECT_DIR}/*.jsonl | head -1)"
19 echo " $0 \"\$LATEST_LOG\""
20 exit 1
21fi
22
23JSONL_LOG="$1"
24
25if [ ! -f "$JSONL_LOG" ]; then
26 echo "Error: File not found: $JSONL_LOG"
27 exit 1
28fi
29
30# Check if jq is available
31if ! command -v jq &> /dev/null; then
32 echo "Error: jq is required but not installed. Install with: brew install jq"
33 exit 1
34fi
35
36echo "==================================="
37echo "Session Log Analysis"
38echo "==================================="
39echo ""
40echo "File: $JSONL_LOG"
41echo "Size: $(wc -l < "$JSONL_LOG") lines ($(du -h "$JSONL_LOG" | cut -f1))"
42echo ""
43
44# Extract session metadata
45echo "--- Session Metadata ---"
46SESSION_ID=$(head -1 "$JSONL_LOG" | jq -r '.sessionId // "unknown"')
47GIT_BRANCH=$(head -1 "$JSONL_LOG" | jq -r '.gitBranch // "unknown"')
48WORKING_DIR=$(head -1 "$JSONL_LOG" | jq -r '.cwd // "unknown"')
49FIRST_TIMESTAMP=$(head -1 "$JSONL_LOG" | jq -r '.timestamp // "unknown"')
50LAST_TIMESTAMP=$(tail -1 "$JSONL_LOG" | jq -r '.timestamp // "unknown"')
51
52echo "Session ID: $SESSION_ID"
53echo "Git Branch: $GIT_BRANCH"
54echo "Working Directory: $WORKING_DIR"
55echo "First event: $FIRST_TIMESTAMP"
56echo "Last event: $LAST_TIMESTAMP"
57echo ""
58
59# Count message types
60echo "--- Message Statistics ---"
61TOTAL_LINES=$(wc -l < "$JSONL_LOG")
62USER_MESSAGES=$(grep -c '"type":"user"' "$JSONL_LOG" 2>/dev/null || echo "0")
63ASSISTANT_MESSAGES=$(grep -c '"type":"assistant"' "$JSONL_LOG" 2>/dev/null || echo "0")
64FILE_SNAPSHOTS=$(grep -c '"type":"file-history-snapshot"' "$JSONL_LOG" 2>/dev/null || echo "0")
65
66echo "Total lines: $TOTAL_LINES"
67echo "User messages: $USER_MESSAGES"
68echo "Assistant messages: $ASSISTANT_MESSAGES"
69echo "File snapshots: $FILE_SNAPSHOTS"
70echo ""
71
72# Extract user prompts
73echo "--- User Prompts ---"
74echo "First 3 user prompts:"
75grep '"type":"user"' "$JSONL_LOG" | head -3 | jq -r '.message.content' | head -c 200 | while IFS= read -r line; do
76 echo " $line"
77done
78echo ""
79
80# Tool usage analysis
81echo "--- Tool Usage ---"
82echo "Tool call frequency:"
83grep '"type":"assistant"' "$JSONL_LOG" | \
84 jq -r '.message.content[]? | select(.type=="tool_use") | .name' 2>/dev/null | \
85 sort | uniq -c | sort -rn | \
86 awk '{printf " %-20s %d calls\n", $2, $1}'
87
88TOTAL_TOOL_CALLS=$(grep '"type":"assistant"' "$JSONL_LOG" | \
89 jq -r '.message.content[]? | select(.type=="tool_use") | .name' 2>/dev/null | wc -l | tr -d ' ')
90echo ""
91echo "Total tool calls: $TOTAL_TOOL_CALLS"
92echo ""
93
94# Error analysis
95echo "--- Error Analysis ---"
96ERROR_COUNT=$(grep -c '"is_error":true' "$JSONL_LOG" 2>/dev/null || echo "0")
97echo "Failed tool calls: $ERROR_COUNT"
98
99if [ "$ERROR_COUNT" -gt 0 ]; then
100 echo ""
101 echo "Sample errors (first 5):"
102 grep '"is_error":true' "$JSONL_LOG" | head -5 | jq -r '.message.content[]? | select(.is_error==true) | .content' 2>/dev/null | head -c 500 | sed 's/^/ /'
103fi
104echo ""
105
106# Thinking blocks (if enabled)
107echo "--- Thinking Blocks ---"
108THINKING_BLOCKS=$(grep '"type":"assistant"' "$JSONL_LOG" | \
109 jq -r '.message.content[]? | select(.type=="thinking")' 2>/dev/null | wc -l | tr -d ' ')
110echo "Thinking blocks captured: $THINKING_BLOCKS"
111echo ""
112
113# Communication patterns
114echo "--- Communication Patterns ---"
115# Count text responses
116TEXT_RESPONSES=$(grep '"type":"assistant"' "$JSONL_LOG" | \
117 jq -r '.message.content[]? | select(.type=="text") | .text' 2>/dev/null | wc -l | tr -d ' ')
118echo "Text responses: $TEXT_RESPONSES"
119echo ""
120
121# Session complexity assessment
122echo "==================================="
123echo "Recommended Analysis Depth"
124echo "==================================="
125
126COMPLEXITY_SCORE=0
127
128# Factor 1: Number of interactions
129if [ "$USER_MESSAGES" -gt 20 ]; then
130 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 2))
131elif [ "$USER_MESSAGES" -gt 10 ]; then
132 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 1))
133fi
134
135# Factor 2: Tool usage
136if [ "$TOTAL_TOOL_CALLS" -gt 50 ]; then
137 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 2))
138elif [ "$TOTAL_TOOL_CALLS" -gt 20 ]; then
139 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 1))
140fi
141
142# Factor 3: Errors
143if [ "$ERROR_COUNT" -gt 5 ]; then
144 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 2))
145elif [ "$ERROR_COUNT" -gt 0 ]; then
146 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 1))
147fi
148
149# Factor 4: Log size
150if [ "$TOTAL_LINES" -gt 500 ]; then
151 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 2))
152elif [ "$TOTAL_LINES" -gt 200 ]; then
153 COMPLEXITY_SCORE=$((COMPLEXITY_SCORE + 1))
154fi
155
156# Determine depth
157if [ "$COMPLEXITY_SCORE" -le 2 ]; then
158 DEPTH="Quick"
159 TIME="5-10 minutes"
160elif [ "$COMPLEXITY_SCORE" -le 5 ]; then
161 DEPTH="Standard"
162 TIME="15-20 minutes"
163else
164 DEPTH="Comprehensive"
165 TIME="30+ minutes"
166fi
167
168echo "Recommended: $DEPTH retrospective (~$TIME)"
169echo ""
170echo "Rationale:"
171echo " - Complexity score: $COMPLEXITY_SCORE/8"
172echo " - User messages: $USER_MESSAGES"
173echo " - Tool calls: $TOTAL_TOOL_CALLS"
174echo " - Errors: $ERROR_COUNT"
175echo " - Log lines: $TOTAL_LINES"
176echo ""
177
178exit 0