AI Dashboard — Complete Guide

Galaxy Web Links Dev Team  ·  Explains every metric, chart, and calculation in plain English

Contents

  1. How Data Flows Into the Dashboard
  2. KPI Overview Cards
  3. Weekly Summary Table
  4. Weekly Drill-Down (click any week)
  5. AI Efficiency Score — Full Calculation
  6. Team Dashboard — Overview & Leaderboard
  7. Team Weekly Summary
  8. Export Report
  9. How to Improve Your Score

How Data Flows Into the Dashboard

Where every number comes from — end to end.

Every time you use Claude Code (in VS Code or terminal), it silently writes a log file called a transcript. These logs are the primary data source for the dashboard.

You chat
with Claude Code
~/.claude/projects/
*.jsonl

Log files on your PC
parse_transcripts.py
Reads & extracts data
export_data.py
Processes & builds JSON
metrics_data.json
Local summary file
sync_to_supabase.py
Pushes to cloud DB
dashboard.html
Shows charts

Step 1  ·  ~/.claude/projects/*.jsonl — The raw log files

Claude Code automatically creates one .jsonl file per conversation. Every message is appended to that file in real-time as the conversation happens — not daily, not batched. When you send a message it is written immediately; when Claude responds it is written immediately.

One file = one session (conversation)

~/.claude/projects/ └── d--myprojects-ai-dashboard/ ├── 0b720226-a84b-452e-88ee-e7fed92ea4b1.jsonl ← Session 1 ├── 3f91c112-... .jsonl ← Session 2 └── ... ← one file per chat

Three types of lines inside each file

Line typeWhen it appearsKey fields
type: "human" Every message you send to Claude sessionId, timestamp, cwd (your project folder)
type: "assistant" Every reply Claude sends back usage.input_tokens, usage.output_tokens, model, content[] (tool calls inside)
type: "tool_result" Result returned to Claude after a tool ran Output text of the tool — not used by the dashboard

Example assistant line (simplified)

{ "type": "assistant", "sessionId": "0b720226-a84b-452e-88ee-e7fed92ea4b1", "timestamp": "2026-06-18T07:39:49.098Z", "cwd": "d:\\myprojects\\ai-dashboard", "message": { "role": "assistant", "model": "claude-sonnet-4-6", "usage": { "input_tokens": 4521, "output_tokens": 892, "cache_read_input_tokens": 1200 }, "content": [ { "type": "tool_use", "name": "Edit", "input": { "file_path": "login.html", "new_string": "..." } } ] } }

From this one line the parser extracts: 5,413 tokens consumed, 1 tool call (Edit), 1 code change to login.html.

Step 2  ·  parse_transcripts.py — The reader

Reads every .jsonl file in ~/.claude/projects/ and extracts structured metrics from the raw messages. This is the only step that touches the raw log files.

Incremental cache — fast re-runs

It never re-reads a file that hasn't changed. It stores results in .parse_state.json and checks each file's mtime (last-modified time). If unchanged → skip. This makes repeated runs fast even with 60+ sessions.

.parse_state.json (cache file — one entry per session) { "0b720226-a84b-...": { "mtime": "2026-06-24T13:40:28.303776+00:00", ← last file modified time "data": { "session_id": "0b720226-a84b-...", "project_path": "d:\\myprojects\\ai-dashboard", "start_time": "2026-06-18T07:39:45.031Z", "end_time": "2026-06-24T13:40:28.159Z", "turns": 575, "input_tokens": 2030, "output_tokens": 1213384, "model": "claude-sonnet-4-6", "tool_calls": [ { "tool_name": "Read", "timestamp": "...", "is_mcp": false }, ... ], "code_changes": [ { "file_path": "login.html", "lines_changed": 109, "language": "HTML" }, ... ], "daily": { "2026-06-18": { "turns": 263, "input_tokens": 703, "output_tokens": 459184 }, "2026-06-19": { "turns": 89, "input_tokens": 412, "output_tokens": 184200 }, ... } } } }

What it extracts per session

FieldHow it is counted
turnsCount every role: "human" line — one per message you send
input_tokensSum usage.input_tokens from all assistant lines
output_tokensSum usage.output_tokens from all assistant lines
tool_callsEvery content block with type: "tool_use" across all assistant lines
code_changesTool calls where name = Write / Edit / NotebookEdit — lines counted from new_string / content field
dailyTokens + turns broken down by day (timestamp[:10]) within the session

Output: In-memory Python dicts — no file written. Data is passed directly to export_data.py.

Step 3  ·  export_data.py — The calculator

Calls parse_transcripts.py, then aggregates the raw session data into every number the dashboard needs. Two time windows are used depending on the metric:

What it calculatesWindowHow
KPI cards (sessions, lines, tool calls, avg iterations)Last 30 daysSimple sums and averages across sessions in the 30-day window
KPI tokens & turnsAll timeSummed from the weekly summary so the KPI board always matches the weekly table total
Daily dataLast 30 daysMerges the per-day breakdown from every session — if a session spans 5 days, all 5 days get contributions
Weekly summaryAll timeGroups all sessions (from install date to today) into ISO weeks (2026-W24) — so older weeks never disappear as the 30-day window rolls forward
Tool usageLast 30 daysCounts how many times each tool was called; top 20 returned
Language breakdownLast 30 daysGroups code_changes by file extension (.py → Python, .html → HTML) and sums lines
Iterations distributionLast 30 daysBuckets sessions by turn count: 1, 2, 3, 4, 5, 6–10, 11–20, 20+

Output: Writes metrics_data.json to the project folder. This file is overwritten on every refresh run.

Step 4  ·  metrics_data.json — The local summary file

The output of export_data.py. Contains only computed numbers — no raw conversation text. This is the file that gets uploaded to Supabase.

Top-level keyTypeContents
generated_atstringISO timestamp of when this file was built
days_analyzednumberAnalysis window (default 30)
kpisobjectTotal sessions, tokens, turns, lines generated, tool calls, avg iterations
daily_dataarrayOne object per active day: { day, sessions, tokens, turns, lines }
weekly_summaryarrayOne object per ISO week: { week, sessions, tokens, turns, lines }
tool_usagearrayTop 20 tools: { tool_name, cnt } sorted by count
language_breakdownarrayLines written per language: { language, lines }
iterations_distarraySession count per turns bucket: { bucket, sessions }
mcp_usagearrayMCP server call counts (if you use MCP tools)
ai_tools_comparisonarrayUsage summary across Claude Code, ChatGPT, Copilot (reserved fields)
Real values from this team's data
{ "generated_at": "2026-07-02T11:30:46Z", "days_analyzed": 30, "daily_data": [ { "day": "2026-06-08", "sessions": 8, "tokens": 567234, "turns": 344, "lines": 9494 }, { "day": "2026-06-09", "sessions": 6, "tokens": 363764, "turns": 392, "lines": 4260 }, ... ], "weekly_summary": [ { "week": "2026-W24", "sessions": 22, "tokens": 3310997, "turns": 2193, "lines": 29712 }, { "week": "2026-W25", "sessions": 16, "tokens": 2261895, "turns": 1481, "lines": 13333 }, ... ], "tool_usage": [ { "tool_name": "Edit", "cnt": 1373 }, { "tool_name": "Read", "cnt": 1365 }, { "tool_name": "Grep", "cnt": 432 }, { "tool_name": "Bash", "cnt": 296 } ], "language_breakdown": [ { "language": "HTML", "lines": 17188 }, { "language": "Python", "lines": 15447 }, { "language": "SQL", "lines": 2945 } ], "iterations_dist": [ { "bucket": "6-10", "sessions": 16 }, { "bucket": "11-20", "sessions": 15 }, { "bucket": "20+", "sessions": 17 } ] }

Step 5  ·  sync_to_supabase.py — The uploader

Reads metrics_data.json and pushes it to the shared Supabase database so your data appears on the team dashboard for everyone to see.

What it doesDetail
Identify you Looks up your UUID — first checks SUPABASE_USER_ID in .env (fastest); falls back to Supabase admin API lookup by your email
Ensure role If you have no role yet, inserts USER into user_roles (safe no-op if already set)
Upsert member_metrics One row per team member — if your row already exists it is updated (merged). The entire metrics_data.json is stored in the data column (JSONB)
Upsert member_metrics_history Writes one snapshot per day keyed on team_member_name + usage_date — powers the long-term trend charts

What gets written to Supabase

{ "team_member_name": "Sunil Carpenter", "team_member_role": "Backend Developer", "team_name": "Galaxy Web Links Dev Team", "user_id": "uuid-from-auth", "data": { ...entire metrics_data.json... } }

The team dashboard reads the data column for every member and renders the leaderboard from it.

Note: Raw transcript data stays on your local machine — only metrics_data.json (computed numbers, no conversation text) is uploaded to the shared Supabase database.

KPI Overview Cards

The five summary numbers shown at the top of dashboard.html for the selected time period.

Claude Sessions
47
Tokens Consumed
1.2M
Lines of Code Gen
3.4K
Avg Iterations
4.2
Tool Calls
620

What each card means

CardSource fieldMeaning
Claude Sessions kpis.total_sessions Total number of separate Claude Code conversations in the period. One session = one conversation from start to finish.
Tokens Consumed kpis.total_tokens Sum of all input + output tokens across every session. A token ≈ one word.
Lines of Code Gen kpis.lines_generated Total lines Claude wrote or edited using Write/Edit tools. Reflects AI contribution to your codebase.
Avg Iterations kpis.avg_iterations Average turns (messages you sent) per session. Lower = more precise prompts.
Tool Calls kpis.total_tool_calls Total number of internal operations Claude performed (Read, Edit, Bash, Grep, etc.) across all sessions.

Input vs Output tokens explained

TypeWhat it isExample
Input tokensText sent TO ClaudeYour question + every file Claude reads to answer it
Output tokensText Claude sends BACKClaude's answer + all the code it writes
Why input is usually bigger: When you ask "fix the bug in App.java", Claude reads the entire App.java file before writing even one line of fix. That whole file counts as input tokens.

Weekly Summary Table

Your Claude Code activity grouped by calendar week — shown in dashboard.html.

What the Week column means — ISO week format

The Week column shows dates in ISO 8601 week format: YYYY-Www

2026-W23 │ │ Year Week number (1–52, starts Monday)

Each week runs Monday → Sunday. Examples:

WeekDate Range
2026-W21Mon 18 May – Sun 24 May 2026
2026-W22Mon 25 May – Sun 31 May 2026
2026-W23Mon 1 Jun – Sun 7 Jun 2026
2026-W24Mon 8 Jun – Sun 14 Jun 2026
Tip: The week value is also a clickable link — click it to open the Weekly Drill-Down for that week.

What each column means

ColumnMeaning
WeekISO week — Monday to Sunday. Clickable: opens the daily drill-down modal.
SessionsNumber of separate Claude Code conversations that week.
TokensTotal input + output tokens consumed that week.
Total TurnsTotal number of messages you sent to Claude across all sessions that week.
Avg IterationsTotal Turns ÷ Sessions for that week. Lower means more efficient prompting.
EfficiencyA color-coded tag based on Avg Iterations — see table below.

Efficiency tag thresholds

Avg IterationsTagMeaning
Less than 5EfficientPrompts are clear and precise — Claude usually gets it right in a few turns.
5 – 9ModerateSome back-and-forth. Room to be more specific in prompts.
10 or moreComplexHigh iteration count — either a complex task or vague prompts.

Search & pagination

Use the search box above the table to filter by week (e.g. W23, 2026). Use the page buttons below to navigate if you have many weeks of data.

Weekly Drill-Down

Click any week in the Weekly Summary table to open a detailed breakdown for that specific week.

What opens when you click a week

A modal popup appears with four stat cards and two bar charts:

ElementShows
📅 Sessions cardTotal sessions in that week
🔤 Tokens cardTotal tokens consumed in that week
✍️ LOC Gen cardLines of code generated that week
🔄 Avg Turns cardAverage turns per session (color-coded green/yellow/red)
Sessions per Day chartBar chart — one bar per day of the week
Tokens per Day chartBar chart — one bar per day of the week

Avg Turns color coding in the drill-down

Avg TurnsColor
4 or fewerGreen — efficient
5 – 7Yellow — moderate
8 or moreRed — high iteration
No daily chart? Some weeks (especially seed/historical data) have a weekly total but no day-by-day breakdown. In that case the four stat cards still appear using the weekly total, and the charts area shows "No per-day breakdown available for this week."
How to close the drill-down
Click the button in the top-right corner of the modal, or click anywhere outside the modal (on the dark backdrop).

AI Efficiency Score — Full Calculation

A score out of 100 that measures how actively and effectively you use AI tools. Higher = you use AI more and better.

The 4 components

1. Usage Score max 30 points
Sessions per day = total_sessions ÷ days_analyzed Score = min(30, sessions_per_day × 6)

More sessions = higher score. Using Claude Code every day gets full 30 points.

2. Output Score max 25 points
Lines per day = total_lines_generated ÷ days_analyzed Score = min(25, lines_per_day ÷ 3)

More code generated by Claude each day = higher score.

3. Prompt Quality Score max 25 points
Score = max(0, 25 − (avg_iterations − 1) × 2.5) Special case: if avg_iterations = 0 (no data) → defaults to 12 points

Fewer back-and-forth messages = higher score. Clear, detailed prompts that get the answer in 1–3 turns score highest.

Avg turns per sessionPrompt Quality Score
1 turn25 points (max)
3 turns20 points
5 turns15 points
11 turns0 points (minimum)
4. Tool Diversity Score max 20 points
tool_calls_per_day = total_tool_calls ÷ days_analyzed Score = min(20, tool_calls_per_day × 1.0)

More tool calls per day = higher score. 20+ tool calls/day earns the full 20 points.

Final formula

Total Score = min(100, Usage + Output + PromptQuality + ToolDiversity) = 30 + 25 + 25 + 20 = max 100 points

Real example — score of ~70 (sample member)

InputValue
Total sessions90
Days analyzed30
Lines generated1,800
Avg turns per session4.2
Total tool calls460
Usage = min(30, (90 ÷ 30) × 6) = min(30, 18) = 18 pts Output = min(25, (1800 ÷ 30) ÷ 3) = min(25, 20) = 20 pts Prompt = max(0, 25 − (4.2 − 1) × 2.5) = max(0, 17) = 17 pts Tools = min(20, (460 ÷ 30) × 1.0) = min(20, 15.3) = 15 pts TOTAL = 18 + 20 + 17 + 15 = 70 → Power User

Badge levels

ScoreBadgeMeaning
75 – 100AI ChampionHeavy daily AI user, efficient prompts, high tool usage
55 – 74Power UserRegular user with good habits
35 – 54Active LearnerGrowing usage, still building habits
15 – 34Getting StartedOccasional use, not yet daily
0 – 14Needs CoachingJust starting out

Team Dashboard — Overview & Leaderboard

Aggregates data from all team members via Supabase. Open team_dashboard.html to see this.

How team data works

Each team member runs refresh_silent.ps1 (Windows) or refresh_silent.sh (Mac/Linux) on their own machine. This syncs their metrics to the shared Supabase database:

Your machine → refresh_silent.ps1 → parse_transcripts.py → export_data.py → sync_to_supabase.py → Supabase ↓ team_dashboard.html reads all members

Team Overview KPI strip

The five summary cards at the top of team_dashboard.html aggregate data across the whole team:

Active Members
8/12
Total Sessions
340
Total Tokens
9.4M
Total LOC Gen
18K
Tool Calls
4.2K
CardMeaning
Active MembersMembers who have at least 1 session in the period, out of total members in Supabase.
Total SessionsSum of all sessions across the entire team.
Total TokensSum of all input + output tokens across the entire team.
Total LOC GeneratedSum of all AI-written lines across the entire team.
Tool CallsTotal internal operations across the entire team.

Leaderboard columns

The main ranking table sorted by AI Efficiency Score by default. Click any column header to re-sort.

ColumnMeaning
#Rank. 🥇🥈🥉 medals for top 3.
MemberName and role. Sortable A–Z.
SessionsTotal Claude Code conversations in the period.
TokensTotal tokens consumed (input + output).
LOC GenLines of code generated by Claude.
Avg TurnsAverage turns per session. Color-coded: green ≤4, yellow ≤7, red >7.
ScoreAI Efficiency Score (0–100) with color bar.
BadgeLevel label — AI Champion, Power User, Active Learner, Getting Started, Needs Coaching.
Search: Use the search box above the leaderboard to filter by member name or role. Results update live as you type.

Team Weekly Summary

Shows each member's activity broken down by week, below the leaderboard in team_dashboard.html.

Columns in the team weekly table

ColumnMeaning
MemberTeam member name. Clickable — opens the Weekly Drill-Down modal for that member and week.
WeekISO week badge (e.g. 2026-W24). Shows the last 4 weeks per member by default.
SessionsSessions that member had in that week.
TokensTokens consumed by that member that week.
TurnsTotal message turns across all sessions that week.
Avg IterationsEfficiency badge: Efficient (avg <5), Moderate (avg 5–9), or the raw number if ≥10.

Search & pagination

Use the search box to filter by member name or week number (e.g. John, W23). Use the pagination buttons to navigate through all rows.

Export Report

Both dashboards have an Export Report button in the top-right header that downloads a spreadsheet.

dashboard.html — what's in the XLSX

SheetColumns
KPI SummaryMetric, Value — your overall totals for the period
Daily DataDate, Sessions, Tokens, Lines Generated, Turns — one row per day
Weekly SummaryWeek, Sessions, Tokens, Total Turns, Avg Iterations — one row per week

team_dashboard.html — what's in the XLSX

SheetColumns
Team LeaderboardRank, Name, Role, Score, Badge, Sessions, Tokens, LOC Generated, Avg Iterations, Tool Calls
Daily DataMember, Date, Sessions, Tokens, Lines, Turns — per-member per-day
Weekly SummaryMember, Week, Sessions, Tokens, Turns — per-member per-week

How to Improve Your Score

Practical steps to increase your AI Efficiency Score.

Quick wins

ActionImpact
Use Claude Code at least once every working day+Usage Score (up to 30 pts)
Ask Claude to write new files, not just explain code+Output Score (LOC Gen)
Write detailed prompts — include file name, expected behavior, constraints+Prompt Quality Score (fewer turns)
Let Claude use tools freely on complex tasks (Read, Edit, Bash, Grep)+Tool Diversity Score (20+ tool calls/day = full 20 pts)

Good prompt vs bad prompt example

Bad — many iterationsGood — few iterations
"Fix the bug" "Fix the NullPointerException in OrderService.java line 45. The order.getUser() can return null when the guest checkout flag is true. Add a null check and return an empty Optional instead."
Results in 5–10 back-and-forth turns Usually solved in 1–2 turns

Refresh your dashboard

After using Claude Code, run the refresh script to update all metrics:

Windows: powershell -ExecutionPolicy Bypass -File refresh_silent.ps1 Mac / Linux: bash refresh_silent.sh

Or just wait — the scheduler does this automatically Mon–Fri at 18:30 if you set it up.