Skip to main content

Methodology

Every number, and how it could mislead you

AI Stats reads 7 export formats and reports 13 metrics from them. This page states what each one measures, how it is calculated, what a high or low reading means, and what would make it wrong. All 91 source-by-metric claims below are read from the same registry the importers are tested against, so this page cannot drift away from the code.

One rule, from which the rest follows

A session whose export did not report a metric is excluded from that metric's total and counted in the coverage fraction beside it. It is never added as a zero, because a zero is a measurement and an absence is not.

Almost everything else on this page is a consequence of it. It is why totals carry a coverage fraction, why a blank cell has a reason attached instead of a zero, why two periods sometimes refuse to be compared, and why several tiles will be unavailable on your dashboard forever. A product that filled those gaps in would look more finished and tell you less.

The five support grades

Every source-by-metric pair carries one of these. The counts are the live totals across all 7 supported sources.

Available41 of 91
AI Stats reads this from the export today. A blank value on your dashboard therefore describes your particular file, not the format.
Sometimes16 of 91
Some exports of this format carry it and some do not. When yours does not, the value stays unavailable rather than becoming a confident zero.
Shown as AI active time6 of 91
Deliberately not computed, because a better measurement of the same thing is already on the page. Reporting it twice under two names would add a tile, not a measurement.
Not parsed yet0 of 91
The file contains it and AI Stats does not read it yet. This is our work, and naming it is the entire point of having a state for it.
Not in export28 of 91
The file does not contain the information. No future adapter release changes that, and any number shown here would have been invented.

The 13 metrics, one at a time

Each entry answers the same four questions, and the last of them is the one that matters: what would make this number wrong in your hands.

Prompts

Dashboard tile: Prompts

What this measures
How many turns you contributed to a conversation or a run.
How it is calculated
Counted from the user-authored turns the adapter can see in the export. Where a format records branches — ChatGPT's regenerate and edit trees — only the branch that ends at the conversation's current node is counted, so a message you rewrote three times is one prompt rather than four.
What high and low mean
A high count relative to sessions means many short exchanges per conversation. A low count over a long session span means you were reading, or waiting, more than you were typing.
What could mislead you
A prompt is not a unit of work. One sentence to a coding agent that then runs for twenty minutes is one prompt, and so is a one-word correction to a chat answer.
Which sources report prompts, and why the rest cannot.
SourceStatusReason
ChatGPTAvailableCounted from your turns on the branch that ends at `current_node`, so regenerated and edited branches are not double counted.
ClaudeAvailableCounted from the human turns in `chat_messages`.
GeminiAvailableCounted from `Prompted` activity rows only. Canvas creations and `Used Gemini Apps` rows are side effects of a prompt, and counting them inflated prompts by roughly half on real exports.
Claude CodeAvailableCounted from user events in the transcript.
CodexAvailableCounted from user message events in the rollout file.
Gemini CLIAvailableCounted from user events, or from the user messages in a local session snapshot.
CursorAvailableCounted from user headings in a Markdown transcript, or user rows in the workspace snapshot.

Responses

Dashboard tile: Responses

What this measures
How many replies the model produced that you could read.
How it is calculated
Counted from visible assistant turns. Reasoning-only parts are excluded, because a reasoning trace is not an answer and counting it would inflate this metric for exactly the models that expose one.
What high and low mean
Responses tracking prompts closely is the ordinary one-for-one exchange. Responses well above prompts means a source that emits several messages per turn, typically an agent narrating its steps.
What could mislead you
Formats disagree about what a message is. A single agent answer split across several streamed blocks can be recorded as several responses in one export and one in another, so this number is comparable within a provider and not between providers.
Which sources report responses, and why the rest cannot.
SourceStatusReason
ChatGPTAvailableCounted from visible assistant turns. Reasoning-only parts are not answers and are excluded.
ClaudeAvailableCounted from the assistant turns in `chat_messages`.
GeminiSometimesGemini's answers follow the timestamp inside the same activity cell of the `MyActivity.html` export, and are read from there. The JSON activity form of the same Takeout carries no answers at all.
Claude CodeAvailableCounted from assistant events. Tool results are results, not new answers, and are not counted again.
CodexAvailableCounted from assistant message events in the rollout file.
Gemini CLIAvailableCounted from model events, or from the model messages in a local session snapshot.
CursorAvailableCounted from assistant headings in a Markdown transcript, or assistant rows in the workspace snapshot.

Tool calls

Dashboard tile: Tool calls

What this measures
How many tool invocations a source recorded inside a session.
How it is calculated
Counted from the tool-call records the export spells out. Since agent adapter 2.2.0 a tool RESULT is not counted as a new call, so a call and its return are one invocation rather than two.
What high and low mean
High tool counts are the signature of agent work: file edits, searches, shell commands. Chat sessions sit near zero even when the product ran a tool, because most chat exports do not record that it did.
What could mislead you
This counts invocations, not outcomes. A loop that retried a failing command nine times reads as nine tool calls and produced nothing.
Which sources report tool calls, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportThe account export is a record of conversation turns. Tool and browsing invocations are not part of it.
ClaudeSometimesCurrent Claude exports spell out every assistant content block, and `tool_use` blocks are counted from them. An older export that carries message text only leaves this unavailable rather than reporting zero.
GeminiNot in exportTakeout activity rows record no tool invocations.
Claude CodeAvailableCounted from tool invocation events, de-duplicated by call id so a retry is not counted twice.
CodexAvailableCounted from tool, shell, and MCP invocation events, de-duplicated by call id.
Gemini CLIAvailableCounted from tool invocation events and from tool parts in a snapshot. A snapshot is a complete message list, so seeing none there is a proven zero.
CursorSometimesA Markdown transcript labels tool and command turns, so they are counted and an absence is a real zero. A workspace snapshot only reports them when its rows spell each turn out as content parts; older rows that store plain message text leave the count unavailable rather than claiming zero.

Agents launched

Dashboard tile: Agents launched

What this measures
How many sub-agents a session launched.
How it is calculated
Counted from explicit sub-agent launch records. Stop events are not counted as launches, and parent and sub-agent transcript files that belong to the same run are merged before counting so a delegated task is not also counted as a separate session.
What high and low mean
Any non-zero value means the work was delegated rather than done in one thread. It is the clearest available marker of orchestration in your usage.
What could mislead you
Only some formats record a launch at all. A zero here means the export was silent about sub-agents far more often than it means none ran.
Which sources report agents launched, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportChatGPT account exports contain no subagent launches.
ClaudeNot in exportClaude account exports contain no subagent launches.
GeminiNot in exportTakeout activity rows record no subagent launches.
Claude CodeAvailableCounted from subagent start events. A stop event closes a launch rather than opening a new one.
CodexAvailableCounted from subagent start events in the rollout file.
Gemini CLINot in exportNeither Gemini CLI telemetry nor a local session snapshot records subagent launches, so the count is never claimed for this source.
CursorNot in exportBackground Agent chats are not present in regular local history, and neither accepted input records a subagent launch.

Tokens

Dashboard tile: Tokens

What this measures
Input plus output tokens, for the sessions whose export reports both.
How it is calculated
Summed only when BOTH the input and the output count are present for a session; one without the other is treated as unreported rather than as a partial total. Cache reads and cache writes are stored separately and are visible in the API export.
What high and low mean
Tokens are the closest thing to a measure of volume that any export offers, and the only input the cost estimate has.
What could mislead you
Token accounting semantics differ. Codex rollouts report input counts that already include cache reads, so a raw comparison of input tokens between Codex and another source compares two different quantities. This is recorded per session and applied by the cost estimate; it is not something the totals can correct for you.
Which sources report tokens, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportOpenAI does not include token usage in the account export, so no session in a ChatGPT import can have a token count.
ClaudeNot in exportToken usage is genuinely absent from the Claude account export. It is not a parsing gap waiting to be closed.
GeminiNot in exportGoogle Takeout does not report token usage for Gemini Apps.
Claude CodeSometimesRead from the usage block on assistant events. Input excludes cache reads for this source. A transcript recorded without usage leaves tokens unavailable instead of zero.
CodexSometimesRead from the cumulative usage the rollout reports. Input includes cache reads for this source, which is why Codex and Claude Code token totals are not compared with each other. Older rollouts without usage leave tokens unavailable.
Gemini CLISometimesRead from telemetry usage when prompt logging is off and usage is exported. Local session snapshots carry no usage, so a snapshot-only import leaves tokens unavailable.
CursorNot in exportNeither the Markdown export nor the recognized workspace snapshot carries token usage.

API-equivalent cost

Dashboard tile: API-equivalent cost

What this measures
What the same token volume would have cost at published API rates.
How it is calculated
Token categories are multiplied by a dated per-model rate table, chosen by matching the model name recorded on the session against the rates in force on that session's own start date. A session whose model cannot be matched to exactly one rate produces no estimate at all rather than a guess at an average price.
What high and low mean
Read it as a scale marker — the order of magnitude of the compute your work represents — not as a bill.
What could mislead you
This is not what you paid. Almost all of this usage is subscription work, and the estimate excludes taxes, discounts, tool and data-residency charges, and long-context premiums. It is an API-equivalent figure, and it is only as current as the dated rate table behind it.
Which sources report api-equivalent cost, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportCost is priced from token counts, and this export carries none. A figure invented without them would be guesswork wearing a currency symbol.
ClaudeNot in exportCost is priced from token counts, and this export carries none. A figure invented without them would be guesswork wearing a currency symbol.
GeminiNot in exportCost is priced from token counts, and this export carries none. A figure invented without them would be guesswork wearing a currency symbol.
Claude CodeSometimesEstimated from token counts against a dated public price list, and only when both the tokens and a known model rate are present.
CodexSometimesEstimated from token counts against a dated public price list, and only when both the tokens and a known model rate are present.
Gemini CLISometimesEstimated from token counts against a dated public price list, and only when both the tokens and a known model rate are present.
CursorNot in exportCost is priced from token counts, and this export carries none. A figure invented without them would be guesswork wearing a currency symbol.

Models

No dashboard tile

What this measures
Which models the export named on each session.
How it is calculated
Read verbatim from the export where it records them; no name is inferred from a provider, a date, or a response style. A session that used several models is counted once under each.
What high and low mean
The ranking is sessions per model. It says where your work happened, not how much of it, and not how much it cost.
What could mislead you
Several supported exports never name a model at all, so this list describes only the subset of sources that do and silently omits the rest of your work. Reading it as a share of your usage will overstate whichever provider happens to be talkative.
Which sources report models, and why the rest cannot.
SourceStatusReason
ChatGPTAvailableRead from each message's recorded model slug.
ClaudeSometimesRead from a message's model field when a Claude export records one. The current reference export omitted that field, so those sessions remain unavailable rather than being attributed to a guessed model.
GeminiSometimesThe JSON activity form names the model that handled a prompt. The HTML page does not, so an HTML-only import leaves the model blank.
Claude CodeAvailableRead from the model recorded on each event, so a session that switched models lists every one of them.
CodexAvailableRead from the model recorded on each event, so a session that switched models lists every one of them.
Gemini CLISometimesTelemetry names the model that served each turn. A local session snapshot does not.
CursorAvailableRead from the model line in a Markdown transcript, or the model field on a snapshot row.

Summed session span

Dashboard tile: Summed session span

What this measures
The span from a session's first recorded event to its last, summed.
How it is calculated
Last event timestamp minus first event timestamp, per session, added up. Nothing is subtracted for gaps.
What high and low mean
This is elapsed time, not effort. It is the right number for 'how long was this conversation open' and the wrong one for 'how long did this take'.
What could mislead you
Idle time is included in full. A conversation you resumed the next morning is one span of eighteen hours here, which is precisely why this metric and AI active time are kept apart instead of being averaged into one figure.
Which sources report summed session span, and why the rest cannot.
SourceStatusReason
ChatGPTAvailableFirst to last message instant in the conversation. It can include idle gaps.
ClaudeAvailableFirst to last message instant in the conversation. It can include idle gaps.
GeminiAvailableFirst to last activity instant in a session. Takeout logs activities rather than conversations, so a session is a run of activity with no thirty-minute gap in it.
Claude CodeAvailableFirst to last event instant in the session.
CodexAvailableFirst to last event instant in the session.
Gemini CLIAvailableFirst to last event instant in the session.
CursorAvailableFirst to last timestamp found in the transcript or snapshot.

AI active time

Dashboard tile: AI active time

What this measures
Time the model was demonstrably working.
How it is calculated
Working intervals recorded by the source are merged as a union of intervals, so two sub-agents running at once contribute the overlap once rather than twice, and the result is wall-clock working time rather than a sum of effort.
What high and low mean
The closest thing on this site to 'how much AI compute your work actually consumed in time'. A low ratio of active time to session span means long conversations with a lot of thinking between turns.
What could mislead you
Only sources that stamp both a start and a stop can produce this. Where an export records one instant per message it is unavailable, and a total that mixes providers is a total over whichever ones happened to be precise.
Which sources report ai active time, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportThis export stamps each message with a single instant, never a start and a stop, so no waiting or working interval can be measured.
ClaudeSometimesDerived from the union of the start and stop instants Claude stamps on each assistant content block. Blocks that overlap are counted once, so interleaved thinking and tool work is not double counted. Exports without those blocks leave it unavailable.
GeminiNot in exportTakeout logs one instant per activity and no duration, so no working interval can be measured.
Claude CodeSometimesRead from reported turn durations. A transcript that records no turn duration leaves it unavailable.
CodexAvailableRead from the turn durations Codex reports when a turn completes or is aborted.
Gemini CLISometimesRead from telemetry turn durations when they are present. A snapshot-only import has none.
CursorNot in exportNeither accepted Cursor input records per-turn durations, only instants.

Estimated interaction time

Dashboard tile: Estimated interaction time

What this measures
A deliberately conservative estimate of time spent interacting.
How it is calculated
Consecutive event timestamps are sorted; a gap longer than 30 minutes is discarded as a break rather than counted, and every remaining gap is capped at 5 minutes before being added. A session with no qualifying pair of events produces no estimate.
What high and low mean
It is a floor, not a measurement. It exists so a source that timestamps single instants still contributes something honest to a time question.
What could mislead you
The 5-minute cap means genuinely long single turns are undercounted, on purpose. Never compare this against AI active time as though they were the same quantity measured two ways: one is estimated from gaps, the other is measured from intervals, and the estimate is designed to be too small.
Which sources report estimated interaction time, and why the rest cannot.
SourceStatusReason
ChatGPTAvailableEstimated from the gaps between consecutive turns, with each gap capped so an overnight pause cannot inflate it.
ClaudeAvailableEstimated from the gaps between consecutive turns, with each gap capped so an overnight pause cannot inflate it.
GeminiAvailableEstimated from the gaps between consecutive activities, with each gap capped.
Claude CodeShown as AI active timeNot computed for Claude Code, which reports real turn durations. The gap estimate exists for sources that cannot measure the real thing.
CodexShown as AI active timeNot computed for Codex, which reports real turn durations. The gap estimate exists for sources that cannot measure the real thing.
Gemini CLISometimesComputed only when the source reports no real turn duration, so it never sits beside a measured AI active time for the same session.
CursorAvailableEstimated from the gaps between consecutive timestamps, with each gap capped.

User active time

No dashboard tile · unavailable for every supported source

What this measures
Time you spent reading and typing — which no supported export records.
How it is calculated
Not calculated. The field exists on the normalized type, the database columns and the API export so a future source with a real measurement can fill it without a migration, and no adapter sets it.
What high and low mean
There is nothing to interpret. Every account sees this as unavailable, and that is a fact about export formats rather than about your import.
What could mislead you
It could be manufactured by subtracting AI active time from the interaction estimate. That would present the difference between two estimates as a measurement, which is the single most misleading thing this product could do, so it is not done.
Which sources report user active time, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.
ClaudeNot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.
GeminiNot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.
Claude CodeNot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.
CodexNot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.
Gemini CLINot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.
CursorNot in exportNo export records how long you spent reading or typing. It could only be inferred by subtracting one estimate from another, and an inferred number shown as a measurement would be a fabrication.

Waiting time

No dashboard tile · unavailable for every supported source

What this measures
Time spent waiting on the model.
How it is calculated
Not calculated separately, because it is already on the page: waiting on the model is exactly what AI active time measures.
What high and low mean
Read AI active time. A second tile carrying the same seconds under a different name would add a tile, not a measurement.
What could mislead you
Seeing this listed as unavailable can read as a missing feature. It is a deduplication: the number exists, it is just reported once.
Which sources report waiting time, and why the rest cannot.
SourceStatusReason
ChatGPTNot in exportThis export stamps each message with a single instant, never a start and a stop, so no waiting or working interval can be measured.
ClaudeShown as AI active timeWaiting on the model is exactly the AI active time already shown. Repeating it under a second name would add a tile, not a measurement.
GeminiNot in exportThis export stamps each message with a single instant, never a start and a stop, so no waiting or working interval can be measured.
Claude CodeShown as AI active timeWaiting on the model is exactly the AI active time already shown. Repeating it under a second name would add a tile, not a measurement.
CodexShown as AI active timeWaiting on the model is exactly the AI active time already shown. Repeating it under a second name would add a tile, not a measurement.
Gemini CLIShown as AI active timeWaiting on the model is exactly the AI active time already shown. Repeating it under a second name would add a tile, not a measurement.
CursorNot in exportThis export stamps each message with a single instant, never a start and a stop, so no waiting or working interval can be measured.

Project grouping

No dashboard tile

What this measures
Whether a session can be attributed to a project or workspace.
How it is calculated
Taken from the Git remote or working directory the export records, hashed in your browser before anything is uploaded. Sessions whose source names no workspace carry no grouping and are absent from every project ranking rather than being filed under a catch-all.
What high and low mean
A dominant group is where your agent work is concentrated. An empty list is the normal, correct result for an account that has imported only chat products.
What could mislead you
Chat products name no workspace at all, so project rankings describe your coding-agent work almost exclusively — whatever share of your total sessions that happens to be.
Which sources report project grouping, and why the rest cannot.
SourceStatusReason
ChatGPTAvailableSessions are grouped under a provider inbox: this export names no repository or workspace to group by.
ClaudeAvailableSessions are grouped under a provider inbox: this export names no repository or workspace to group by.
GeminiAvailableSessions are grouped under a provider inbox: this export names no repository or workspace to group by.
Claude CodeAvailableGrouped by the Git remote or working directory recorded in the session, hashed before it leaves the browser.
CodexAvailableGrouped by the Git remote or working directory recorded in the session, hashed before it leaves the browser.
Gemini CLIAvailableGrouped by the Git remote or working directory recorded in the session, hashed before it leaves the browser.
CursorAvailableSessions are grouped under a provider inbox: this export names no repository or workspace to group by.

The 7 sources, graded

A source is Verified or Beta. The grade is about how predictable its export shape is, not about how much AI Stats likes it, and the tallies are counted from the same registry the adapters are tested against.

ChatGPT · OpenAI

Verified

Its input contract is exercised by sanitized real-shape fixtures and the capability claims below are asserted against adapter output on every run.

6 reported · 0 sometimes · 7 unavailable · adapter 3.0.0

  • Account exports do not normally include token usage.

Claude · Anthropic

Beta

It parses and is covered by fixtures, but the export shape varies more between accounts than a verified source does, so expect more metrics to land as unavailable on your own file.

5 reported · 3 sometimes · 5 unavailable · adapter 3.1.0

  • Tool calls and AI active time need an export that spells out assistant content blocks.
  • Beta until a sanitized current account export passes.

Gemini · Google

Verified

Its input contract is exercised by sanitized real-shape fixtures and the capability claims below are asserted against adapter output on every run.

4 reported · 2 sometimes · 7 unavailable · adapter 3.1.0

  • Takeout activity does not reliably include responses.

Claude Code · Anthropic

Verified

Its input contract is exercised by sanitized real-shape fixtures and the capability claims below are asserted against adapter output on every run.

7 reported · 3 sometimes · 3 unavailable · adapter 3.1.0

  • Available fields depend on telemetry configuration.

Codex · OpenAI

Verified

Its input contract is exercised by sanitized real-shape fixtures and the capability claims below are asserted against adapter output on every run.

8 reported · 2 sometimes · 3 unavailable · adapter 3.1.0

  • Fields vary between CLI and Desktop rollout versions.

Gemini CLI · Google

Verified

Its input contract is exercised by sanitized real-shape fixtures and the capability claims below are asserted against adapter output on every run.

5 reported · 5 sometimes · 3 unavailable · adapter 3.1.0

  • Prompt logging should be disabled before telemetry capture.

Cursor · Anysphere

Beta

It parses and is covered by fixtures, but the export shape varies more between accounts than a verified source does, so expect more metrics to land as unavailable on your own file.

6 reported · 1 sometimes · 6 unavailable · adapter 3.0.0

  • SQLite snapshots are accepted only for explicit known schema signatures.
  • Background Agent chats are not present in regular local history.
  • Beta until a sanitized current export passes.

Unknown shapes fail closed. A planned source accepts no files at all until it has sanitized real-shape fixtures and passes the same contract suite, because an adapter that half-reads a format produces numbers that look right.

The 2 metrics that are blank for everyone

These are not gaps in the import. No supported export records them, and this list is computed from the support table above rather than maintained by hand — if a future adapter can report one, it leaves this list on its own.

User active time

Not calculated. The field exists on the normalized type, the database columns and the API export so a future source with a real measurement can fill it without a migration, and no adapter sets it.

It could be manufactured by subtracting AI active time from the interaction estimate. That would present the difference between two estimates as a measurement, which is the single most misleading thing this product could do, so it is not done.

Full entry for user active time

Waiting time

Not calculated separately, because it is already on the page: waiting on the model is exactly what AI active time measures.

Seeing this listed as unavailable can read as a missing feature. It is a deduplication: the number exists, it is just reported once.

Full entry for waiting time

What each dashboard section is doing

The same four questions, for the 17 sections of the signed-in dashboard. This is the identical copy the help disclosure on each section shows, read from one registry so the public explanation and the in-product one cannot disagree.

What changed

Measures
The largest movements between the selected period and the equivalent period immediately before it.
Calculated
Each headline metric is compared with its own value in the previous window. A metric enters this summary only when both periods were fully covered by sources that recorded it the same way, so a movement here is never an artefact of one period having better data than the other.
High and low
A large increase or decrease is a real change in your usage. An empty summary means the comparison could not be made honestly, not that nothing happened.
Could mislead
Imported exports are historical and arrive in bulk. A period that gained an import will show enormous growth that reflects when you imported, not when you worked.

Filters

Measures
The slice of your sessions every number, chart, and list on this page is computed from.
Calculated
Date range, providers, project groups, and a model-name substring are combined with AND and written into the page URL. Every section below reads the same filtered set; nothing on this page is computed from a different slice.
High and low
The URL is the whole state. Copy it to return to exactly this view, or to send someone the view that supports a claim you are making.
Could mislead
The date range filters on session start time. A session that began before the window and ran into it is excluded entirely rather than clipped.

Saved views

Measures
Dashboard states you have named and kept, so a slice you return to is one click rather than four selects.
Calculated
A saved view stores its name and the six filter params, in canonical order, and nothing else. Restoring one is a plain link back to this page with those params applied, so the URL remains the only description of what you are looking at.
High and low
Treat these as bookmarks with names. Two views that differ only in the order you picked the providers are the same view, and are stored as one.
Could mislead
A saved view stores the question, never the answer. Re-open one after an import and the numbers will have changed, so a view saved to support a claim does not preserve the figures that were on screen when you saved it.

Comparison setup

Measures
Two independent slices of your sessions — each with its own date range, providers, projects, and model filter — chosen for the sole purpose of being read against each other.
Calculated
Each side is computed exactly as the main dashboard computes its single view, from the same query and the same coverage rules. All twelve params live in the URL, so a comparison is a link.
High and low
Change one thing at a time. Two sides that differ in both provider and date range produce differences that cannot be attributed to either.
Could mislead
Nothing stops you selecting two sides that are the same, or two that overlap. An overlapping pair double-counts the sessions in the overlap on both sides, and the page cannot tell that apart from a genuine difference.

Side-by-side metrics

Measures
Each headline metric on both sides, with the difference between them where a difference is meaningful.
Calculated
The same rule the period-over-period summary uses: a difference is reported only when both sides were fully covered and every contributing session shared the same adapter version, normalization version, quality, source, and calculation. Any side that fails a gate prints the gate it failed instead of a number.
High and low
Read the blocked rows first. They tell you which questions your imported data cannot answer yet, which is usually more actionable than the differences it can.
Could mislead
A comparable row is not automatically a fair one. Two views of very different size can both be fully covered, and a percentage between them still says nothing about which was the better week.

Composition

Measures
How each side's sessions divide across providers, models, and project groups, aligned so the same name sits on one row.
Calculated
Session counts per key, taken from each side's own filtered set. A key present on one side only keeps its row and reads as absent on the other, rather than being dropped.
High and low
The rows reading "Not in this view" on one side are usually the finding: they are what one slice contains and the other does not.
Could mislead
These are session counts, not effort. A provider that creates a session per invocation will out-count one that creates a session per conversation even when far less work went through it.

Provider import status

Measures
For each supported provider: whether it has ever been imported, whether the last attempt succeeded, and whether its sessions came from the current adapter.
Calculated
Read from your import job history and from the adapter and normalization version stamped on each stored session, not from the filtered view — this panel deliberately ignores the date range so a stale provider cannot hide outside the window.
High and low
"Current" means the stored sessions match the adapter that is running today. "Stale" means an adapter has improved since you imported, so re-importing will change the numbers.
Could mislead
A successful import says the file was read, not that it was complete. If you exported a partial history, every metric below is partial in exactly the same way and nothing here can detect it.

Headline metrics

Measures
The totals for the filtered set, each with its coverage, its change against the previous period, and — where a figure is blank or partial — the reason.
Calculated
Every tile sums only the sessions whose source actually reported that metric. Sessions that did not report it are excluded from the sum and counted in the coverage fraction beside it; they are never treated as zero.
High and low
Read the coverage fraction before the total. A large number over a small fraction of sessions is a statement about those sessions, not about the period.
Could mislead
Totals over partial coverage are not comparable between providers, because the missing sessions are not missing at random — they are missing by export format.

Activity timeline

Measures
Sessions that started on each local calendar day in the window.
Calculated
Session start timestamps are converted to your profile timezone and counted per day. Days with no sessions are absent from the series rather than plotted as zero.
High and low
Peaks are days you started a lot of separate conversations. This counts starts, so a single long day of work on one session is a low point on this chart.
Could mislead
Coding agents create a session per invocation and chat products create one per conversation, so a day spent in an agent can out-count a day of equally heavy chat use.

Session duration distribution

Measures
How many sessions in the window fall into each length band, by summed session span.
Calculated
Each session's span is its last recorded event minus its first. Sessions with no usable span are excluded and counted separately below the chart rather than being placed in the shortest band.
High and low
A mass in the short bands means many quick exchanges; a long tail means sustained work, or a session that was left open.
Could mislead
Span includes idle gaps. A conversation resumed the next morning is one very long session here, which is why this is not the same measurement as AI active time.

Provider distribution

Measures
How the filtered sessions divide across the providers in view.
Calculated
Sessions are counted per provider. Prompts are summed only over the sessions of that provider that reported a prompt count, and the fraction is shown when it is partial.
High and low
This shows where your sessions live. It does not show where your time went — compare it with the duration sections before drawing that conclusion.
Could mislead
A provider whose export carries prompt counts will look busier per session than one whose export does not, purely because of what its file contains.

Recent sessions

Measures
The ten most recent sessions in the filtered set, newest first by start time.
Calculated
Titles shown here are the private alias you set, or the title recovered during import, which was parsed in your browser. Prompt counts appear only where the source reported one.
High and low
Use this to check a number you doubt: open a session and its detail page states the adapter version and per-metric provenance behind every figure.
Could mislead
"Recent" means recently started, not recently imported. A freshly imported historical export can add sessions that never appear at the top of this list.

Project groups

Measures
The filtered sessions that carry a project grouping, ranked by session count.
Calculated
Grouping comes from the repository or working directory recorded in the session, hashed in your browser before anything is stored. Sessions from sources that name no workspace carry no grouping and are absent here.
High and low
A dominant group is where your agent work is concentrated. An empty list is normal for accounts with only chat providers.
Could mislead
Chat providers name no workspace at all, so this ranking describes your coding-agent work almost exclusively, whatever share of your sessions that is.

Models

Measures
The models named in the filtered sessions, ranked by how many sessions mention each.
Calculated
Model names are read from the export where it records them. A session that used several models counts once for each. Sessions whose source names no model contribute nothing.
High and low
This is a ranking of sessions per model, not of tokens or time per model.
Could mislead
Several supported exports never name a model, so this list describes the subset of sources that do and silently omits the rest of your work.

Weekly activity heatmap

Measures
Session starts by local weekday and hour across the whole window.
Calculated
Each session's start time is converted to your profile timezone and added to one of the 168 weekday-hour cells. Cell shading is relative to a fixed scale, not to your own maximum.
High and low
Dense bands are the hours you habitually start work. Isolated cells are one-off sessions.
Could mislead
Every session in the window lands in the same weekly grid, so a long window flattens genuine week-to-week change into one average week.

Metric coverage

Measures
For each metric, the share of sessions in view whose source actually supplied a usable value.
Calculated
A session counts as covered when its recorded quality for that metric is exact, source reported, derived, or estimated. Anything else is uncovered, and the row states why.
High and low
This is the confidence line for every total on this page. Read a metric's coverage before you quote its total anywhere.
Could mislead
A permanent zero here is usually a fact about export formats rather than a fault in the import, which is why each row carries its own reason.

Coding and general usage

Measures
The filtered sessions split into coding agents and general chat products.
Calculated
Each provider is classified once, by product surface, in the provider registry. Sessions inherit their provider's class; nothing is inferred from the content of a session.
High and low
The split shows how your usage divides between assistants you talk to and agents you delegate to.
Could mislead
A session is one unit on each side of this split, but the two sides do not create sessions at the same rate, so the ratio is not a ratio of effort.

Versions, prices, privacy, and what is missing from this page

Method versions

Every stored session carries the adapter version that produced it and normalization version 3. Those stamps decide whether two periods can be compared: a metric is differenced only when both sides were produced the same way. When an adapter improves, existing sessions keep their recorded version and the dashboard tells you a re-import will change the numbers, rather than silently reinterpreting them.

Prices

API-equivalent cost uses a dated rate table snapshotted on 2026-08-02, matched against each session’s own start date. It is not a bill, and a session whose model cannot be matched to exactly one rate produces no estimate rather than an average.

Privacy

Your files are parsed in your browser. Prompts, responses, and file contents are never uploaded; normalized counters are. Conversation and workspace names stay hashed unless you opt in per import. Every measurement above is computed from those counters, which is also why none of them can be recovered from text we do not hold. Privacy policy · Security

There is no dated log of method changes here, on purpose

A methodology centre is supposed to carry one. Nothing recorded the date a calculation changed before this page existed, and a page whose whole argument is that numbers are not invented cannot open with invented dates. The versions above are the honest substitute: they are stamped on the data itself, they are visible on your own dashboard, and they are what actually governs whether two figures may be subtracted. Dated entries start from the next method change.