Help us improve
Share bugs, ideas, or general feedback.
From kookr-toolkit
Analyze Claude Code telemetry, stats-cache, and history data from ~/.claude to identify UX friction, performance issues, workflow inefficiencies, and improvement opportunities.
npx claudepluginhub kookr-ai/kookr --plugin kookr-toolkitHow this skill is triggered — by the user, by Claude, or both
Slash command
/kookr-toolkit:claude-code-metrics-analysisThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Periodically (weekly/monthly) to spot UX friction trends
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
All data lives under ~/.claude/:
| Source | Path | Format | Contains |
|---|---|---|---|
| Stats cache | stats-cache.json | JSON | Aggregate usage: daily activity, model tokens, hour distribution, session totals |
| Telemetry | telemetry/*.json | JSON lines | Granular events: tool use, errors, stalls, rate limits, session lifecycle, performance |
| History | history.jsonl | JSONL | User prompts with timestamps, paste events, session IDs, project paths |
Read ~/.claude/stats-cache.json and extract:
hourCounts): identify peak hours and potential burnout patternsRun a frequency count across all ~/.claude/telemetry/*.json files:
cat ~/.claude/telemetry/*.json | python3 -c "
import sys, json, collections
events = collections.Counter()
for line in sys.stdin:
try:
d = json.loads(line.strip())
if d.get('event_type') == 'ClaudeCodeInternalEvent':
events[d['event_data']['event_name']] += 1
else:
events[d['event_type']] += 1
except: pass
for name, count in events.most_common(80):
print(f'{count:>8} {name}')
"
Parse the telemetry for structured analysis across these dimensions:
Extract from tengu_tool_use_success and tengu_tool_use_error:
cat ~/.claude/telemetry/*.json | python3 -c "
import sys, json, collections
tool_ok = collections.Counter()
tool_err = collections.Counter()
tool_dur = collections.defaultdict(list)
for line in sys.stdin:
try:
d = json.loads(line.strip())
if d.get('event_type') != 'ClaudeCodeInternalEvent': continue
name = d['event_data']['event_name']
meta = json.loads(d['event_data'].get('additional_metadata', '{}'))
if name == 'tengu_tool_use_success':
tn = meta.get('toolName', '?')
tool_ok[tn] += 1
tool_dur[tn].append(meta.get('durationMs', 0))
elif name == 'tengu_tool_use_error':
tool_err[meta.get('toolName', '?')] += 1
except: pass
print('=== Tool Success (top 20) ===')
for tn, c in tool_ok.most_common(20):
durs = tool_dur[tn]
avg = sum(durs)/len(durs) if durs else 0
err = tool_err.get(tn, 0)
rate = err/(c+err)*100 if (c+err) else 0
print(f' {c:>6}x {tn:<25} avg={avg:>8.0f}ms errors={err} ({rate:.1f}%)')
"
What to look for:
Extract from tengu_tool_use_granted_in_config vs total tool uses:
What to look for:
granted_in_config = user is clicking "approve" repeatedlytengu_bash_security_check_triggered count = how often security checks fire (may cause friction if too aggressive)Extract from tengu_api_error and tengu_claudeai_limits_status_changed:
What to look for:
status: "rejected" count = hard rate limit hits (user is blocked)status: "allowed_warning" = approaching limits (user may feel pressure)errorType: "rate_limit" with model breakdown = which models hit limitsExtract from tengu_streaming_stall and tengu_exit (frame rate data):
What to look for:
Extract from tengu_exit events:
What to look for:
tengu_cost_threshold_reached frequency — how often cost warnings fireExtract from tengu_post_autocompact_turn and tengu_context_size:
What to look for:
Extract from tengu_input_prompt and tengu_paste_text:
What to look for:
is_negative: true = user sent rejection/correction (friction signal)is_keep_going: true = user had to manually continue (automation gap)Signal: Tool X has high usage count but low granted_in_config count.
Impact: User clicks "approve" dozens of times per session.
Fix: Add the tool to settings.local.json allowlist or use --allowedTools.
Signal: Multiple rejected limit status changes in a session; tengu_api_retry events.
Impact: User's flow is broken waiting for rate limits to reset.
Fix: Reduce concurrent agent count, use Haiku for exploration, batch requests.
Signal: tengu_streaming_stall with durations > 30s, especially on Opus.
Impact: User sees frozen terminal, may think it crashed.
Fix: Awareness only (server-side). Consider switching to Sonnet for interactive work.
Signal: Sessions with high cost but low lines_added + lines_removed.
Impact: Budget burn without visible progress.
Fix: Review what these sessions did — likely research/exploration. Consider using Haiku subagents for exploration.
Signal: Frequent tengu_post_autocompact_turn events in a session.
Impact: Lost context, repeated work, confused agent.
Fix: Break work into smaller sessions, use tengu_token_efficiency skill patterns.
Signal: High is_negative rate in tengu_input_prompt, or repeated similar prompts in history.jsonl.
Impact: User is spending time correcting instead of building.
Fix: Encode corrections as CLAUDE.md rules or skills so they persist.
After analysis, produce a report with:
## Claude Code Metrics Report — {date range}
### Summary
- Total sessions: X | Total messages: Y | Total cost: $Z
- Models used: {breakdown}
- Peak hour: {hour} ({count} sessions)
### Friction Signals (ordered by impact)
1. **{Pattern Name}** — {description}
- Evidence: {metric values}
- Impact: {user experience effect}
- Recommendation: {specific action}
2. ...
### Efficiency Metrics
- Tool error rate: X%
- Auto-approved tools: X/Y (Z%)
- Rate limit rejections: N
- Streaming stalls: N (avg duration: Xms)
- Auto-compactions: N
### Trends
- Usage trend: {increasing/stable/decreasing}
- Cost trend: {per-session cost over time}
- Model migration: {any model switches visible in data}
This skill is designed for manual invocation (/claude-code-metrics-analysis). The analysis reads local files only — no network calls needed. All Python scripts use only stdlib (json, sys, collections). The telemetry directory can be large (400MB+), so parsing may take 30-60 seconds.