I made a dashboard to track actual costs after Sept 15 pricing…

After Sept 15, I kept refreshing the dashboard trying to figure out if I’m about to blow through my limit or not. The dashboard has a limitation of 30 days but doesn’t actually answer:

  • Am I spending $20 this month or $200?

  • LOCAL CURRENCY CONVERSION???

  • Which model is eating my budget? (Turns out Sonnet 4 is 80% of my costs)

  • What’s my actual daily burn vs one-off spikes?

What it does:

  • Real projected monthly cost based on your patterns (not just token counts)

  • Model-by-model breakdown with merge duplicates - cuts through seeing “Claude 4.5 Sonnet” listed 6 times

  • Daily/weekly trends and spike alerts

  • Compare what you’d pay for Real API vs Cursor’s pricing

Vibe coded it in ~8hrs with Cursor itself. Pretty rough but way more useful than doing mental math every time I check the official dashboard.​

The merge feature especially helps. Instead of scrolling through a cluttered list, you see your actual spending by model at a glance.

:link: View Your Dashboard → cursortokens.vercel.app

Would love feedback on what else would actually be useful.​

13 Likes

Very useful.
Pie charts - Overlapping text. May be limit by top 5 . Or add a slider on top of each chart to that ranges from 3 to 10.

1 Like

This is personally what my metrics say, teams/business plan saves a lot of money. Or rather, the old legacy pricing. This is true for people on old pricing plan too.

For some reason, it is pulling only 2 days of data for me. Not sure what I’m doing wrong.

Another issue, clicking the range selector slider under summary led to this

Thanks for the feedback. For the data, press refresh twice so it will do a hard refresh. It aggressively caches so you don’t impact cursor’s API too heavily.

The range selector slider is a bit buggy, I am looking for better alternative to this.

I quickly added more charts that might be interesting to look at!

Fix: The currency selection was not working for some reason.

1 Like

Update: I added even more charts! I did research on what kinds of charts people might actually be interested in seeing, or looking at.

Hey this is really cool but I’m not sure whether it’s working correctly

You’re hitting the arbitrary 10k limit I set. But I already made it handle cases like this, try hitting refresh twice to do a hard refresh and see if that fixes it. :slightly_smiling_face: Otherwise what do your logs look like?

I’m not experience in web stuff but I’m just going to assume you are asking for the console output, this is the console output after pressing hard refresh (hitting refresh twice)
```
index-DJJbZN1F.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: false (0), apiData: false (0), events: 0
index-DJJbZN1F.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: false (0), apiData: false (0), events: 0
index-DJJbZN1F.js:578 :package: Loaded sample data from cache: 7578 events
index-DJJbZN1F.js:578 :package: Loaded API data from cache: 10000 events (21s old)
index-DJJbZN1F.js:578 :pushpin: Restored API data view from last session
index-DJJbZN1F.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Setting persisted API cache data directly: 10000 events
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-DJJbZN1F.js:579 :package: Loaded from persistent API cache: 10000 events (last updated 21s ago)
index-DJJbZN1F.js:579 :rocket: Initial load (full history)
index-DJJbZN1F.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)…
index-DJJbZN1F.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)…
index-DJJbZN1F.js:579 :bust_in_silhouette: Fetching profile for “Taitranz” (not cached)…
index-DJJbZN1F.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-DJJbZN1F.js:579 :white_check_mark: Profile cached for “Taitranz”
index-DJJbZN1F.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-DJJbZN1F.js:579 :white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history)
index-DJJbZN1F.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-DJJbZN1F.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Full refresh completed at 09:15:09
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Setting API data directly: 10000 events
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-DJJbZN1F.js:579 :white_check_mark: Successfully fetched and merged API data: 10000 events
index-DJJbZN1F.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-DJJbZN1F.js:579 :high_voltage: Single press: triggering FAST incremental refresh (24h lookback)
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Setting persisted API cache data directly: 10000 events
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-DJJbZN1F.js:579 :package: Loaded from persistent API cache: 10000 events (last updated 5s ago)
index-DJJbZN1F.js:579 :high_voltage: Incremental refresh (last 24 hours) - fast updates
index-DJJbZN1F.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (incremental: last 24h from 19/10/2025, 09:15:14)…
index-DJJbZN1F.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (incremental from 2025-10-18T23:15:14.292Z)…
index-DJJbZN1F.js:579 ✓ Using cached profile for “Taitranz” (0m old)
index-DJJbZN1F.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-DJJbZN1F.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Double-press detected: triggering FULL refresh from startDate: 0
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Full refresh (from startDate: 0) - catching all corrections
index-DJJbZN1F.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)…
index-DJJbZN1F.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)…
index-DJJbZN1F.js:579 ✓ Using cached profile for “Taitranz” (0m old)
index-DJJbZN1F.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-DJJbZN1F.js:579 :white_check_mark: Pro data for “Taitranz”: 2248 events fetched (new since last fetch)
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Incremental 24h fetch: processing 2248 events with 10000 existing events…
index-DJJbZN1F.js:579 :white_check_mark: Merged total: 10000 events (7752 kept + 2248 from fetch)
index-DJJbZN1F.js:579 ✓ No changes since last fetch
index-DJJbZN1F.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-DJJbZN1F.js:579 ✓ Data looks complete: 10000 events spanning 112h (oldest: 15/10/2025, 17:10:26)
index-DJJbZN1F.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-DJJbZN1F.js:579 :pause_button: This fetch was cancelled, skipping state update
index-DJJbZN1F.js:579 :white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history)
index-DJJbZN1F.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-DJJbZN1F.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-DJJbZN1F.js:579 :counterclockwise_arrows_button: Full refresh completed at 09:15:16
index-DJJbZN1F.js:579 :white_check_mark: Successfully fetched and merged API data: 10000 events
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 0
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 1
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 2
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 3
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 4
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 5
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 6
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 7
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 8
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 9
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 10
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 11
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 12
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 13
index-DJJbZN1F.js:578 :counterclockwise_arrows_button: Refreshing table row 14
```

Hey I fixed this issue now, just reload the page and fetch from the api again. Thank you trying it out! Let me know if it has been fixed.

Here’s a screenshot and the console output logs
Console output
``
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: false (0), apiData: false (0), events: 0
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: false (0), apiData: false (0), events: 0
index-BOomlTIK.js:578 :package: Loaded sample data from cache: 7578 events
index-BOomlTIK.js:578 :package: Loaded API data from cache: 10000 events (22s old)
index-BOomlTIK.js:578 :pushpin: Restored API data view from last session
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Setting persisted API cache data directly: 10000 events
index-BOomlTIK.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-BOomlTIK.js:579 :package: Loaded from persistent API cache: 10000 events (last updated 22s ago)
index-BOomlTIK.js:579 :rocket: Initial load (full history)
index-BOomlTIK.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)…
index-BOomlTIK.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)…
index-BOomlTIK.js:579 :bust_in_silhouette: Fetching profile for “Taitranz” (not cached)…
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-BOomlTIK.js:579 :white_check_mark: Profile cached for “Taitranz”
index-BOomlTIK.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-BOomlTIK.js:579 :white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history)
index-BOomlTIK.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-BOomlTIK.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Full refresh completed at 09:41:11
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Setting API data directly: 10000 events
index-BOomlTIK.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-BOomlTIK.js:579 :white_check_mark: Successfully fetched and merged API data: 10000 events
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-BOomlTIK.js:579 :high_voltage: Single press: triggering FAST incremental refresh (24h lookback)
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Setting persisted API cache data directly: 10000 events
index-BOomlTIK.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-BOomlTIK.js:579 :package: Loaded from persistent API cache: 10000 events (last updated 5s ago)
index-BOomlTIK.js:579 :high_voltage: Incremental refresh (last 24 hours) - fast updates
index-BOomlTIK.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (incremental: last 24h from 19/10/2025, 09:41:16)…
index-BOomlTIK.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (incremental from 2025-10-18T23:41:16.134Z)…
index-BOomlTIK.js:579 ✓ Using cached profile for “Taitranz” (0m old)
index-BOomlTIK.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Double-press detected: triggering FULL refresh from startDate: 0
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Full refresh (from startDate: 0) - catching all corrections
index-BOomlTIK.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)…
index-BOomlTIK.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)…
index-BOomlTIK.js:579 ✓ Using cached profile for “Taitranz” (0m old)
index-BOomlTIK.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-BOomlTIK.js:579 :white_check_mark: Pro data for “Taitranz”: 2191 events fetched (new since last fetch)
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Incremental 24h fetch: processing 2191 events with 10000 existing events…
index-BOomlTIK.js:579 :white_check_mark: Merged total: 10000 events (7809 kept + 2191 from fetch)
index-BOomlTIK.js:579 ✓ No changes since last fetch
index-BOomlTIK.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-BOomlTIK.js:579 ✓ Data looks complete: 10000 events spanning 112h (oldest: 15/10/2025, 17:10:26)
index-BOomlTIK.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-BOomlTIK.js:579 :pause_button: This fetch was cancelled, skipping state update
index-BOomlTIK.js:579 :white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history)
index-BOomlTIK.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-BOomlTIK.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Full refresh completed at 09:41:18
index-BOomlTIK.js:579 :white_check_mark: Successfully fetched and merged API data: 10000 events
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 0
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 1
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 2
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 3
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 4
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 5
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 6
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 7
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 8
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 9
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 10
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 11
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 12
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 13
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 14
index-BOomlTIK.js:578 :eye: Page visibility changed: HIDDEN - slowing down refresh
index-BOomlTIK.js:578 :eye: Page visibility changed: VISIBLE - resuming normal refresh
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Setting persisted API cache data directly: 10000 events
index-BOomlTIK.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-BOomlTIK.js:579 :package: Loaded from persistent API cache: 10000 events (last updated 71s ago)
index-BOomlTIK.js:579 :high_voltage: Incremental refresh (last 24 hours) - fast updates
index-BOomlTIK.js:579 :rocket: Fetching from 1 account(s): 0 Business, 1 Pro (incremental: last 24h from 19/10/2025, 09:42:29)…
index-BOomlTIK.js:579 :bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (incremental from 2025-10-18T23:42:29.212Z)…
index-BOomlTIK.js:579 ✓ Using cached profile for “Taitranz” (1m old)
index-BOomlTIK.js:579 :page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)…
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 0
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 1
index-BOomlTIK.js:579 :white_check_mark: Pro data for “Taitranz”: 2191 events fetched (new since last fetch)
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Incremental 24h fetch: processing 2191 events with 10000 existing events…
index-BOomlTIK.js:579 :white_check_mark: Merged total: 10000 events (7809 kept + 2191 from fetch)
index-BOomlTIK.js:579 ✓ No changes since last fetch
index-BOomlTIK.js:579 :tada: Total merged data: 10000 events from 1/1 accounts
index-BOomlTIK.js:579 ✓ Data looks complete: 10000 events spanning 112h (oldest: 15/10/2025, 17:10:26)
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 2
index-BOomlTIK.js:578 :white_check_mark: Cached to IndexedDB: 10000 events (4.47MB)
index-BOomlTIK.js:579 :counterclockwise_arrows_button: Setting API data directly: 10000 events
index-BOomlTIK.js:578 :counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events
index-BOomlTIK.js:579 :white_check_mark: Successfully fetched and merged API data: 10000 events
index-BOomlTIK.js:578 :magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7578), apiData: true (10000), events: 10000
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 3
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 4
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 5
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 6
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 7
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 8
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 9
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 10
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 11
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 12
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 13
index-BOomlTIK.js:578 :counterclockwise_arrows_button: Refreshing table row 14
```

Ah. It’s because you’re on the old 10k page size still and got stuck there. Try again, reload the page (F5) and then do a hard refresh, you need to actually reload the page too. This should be fixed now, I pushed another change.

maybe it takes awhile to change, I retried on a different browser
console logs
```
:magnifying_glass_tilted_left: Key state changed - dataSource: sample, sampleData: false (0), apiData: false (0), events: 0 2 index-BImp0crC.js:578:120397
:package: Loaded sample data from cache: 7646 events index-BImp0crC.js:578:121346
:pushpin: Restored sample data view from last session index-BImp0crC.js:578:122128
:pause_button: Auto-fetch disabled (sample/manual import mode) index-BImp0crC.js:578:122385
:magnifying_glass_tilted_left: Key state changed - dataSource: sample, sampleData: true (7646), apiData: false (0), events: 7646 index-BImp0crC.js:578:120397
:counterclockwise_arrows_button: Switching from sample to API mode - sample data will remain in memory index-BImp0crC.js:579:10695
:white_check_mark: Old cache cleared - fetching fresh API data index-BImp0crC.js:579:10848
:high_voltage: Single press: triggering FAST incremental refresh (24h lookback) index-BImp0crC.js:579:11142
:high_voltage: Skipping progressive refresh (transitioning from manual import to API data) index-BImp0crC.js:579:12031
:rocket: Initial load (full history) index-BImp0crC.js:579:12582
:rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)… index-BImp0crC.js:579:12643
:bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)… index-BImp0crC.js:579:7458
:bust_in_silhouette: Fetching profile for “Taitranz” (not cached)… index-BImp0crC.js:579:7881
:white_check_mark: Profile cached for “Taitranz” index-BImp0crC.js:579:8325
:page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)… index-BImp0crC.js:579:8633
:counterclockwise_arrows_button: Switching from sample to API mode - sample data will remain in memory index-BImp0crC.js:579:10695
:white_check_mark: Old cache cleared - fetching fresh API data index-BImp0crC.js:579:10848
:counterclockwise_arrows_button: Double-press detected: triggering FULL refresh from startDate: 0 index-BImp0crC.js:579:11037
:high_voltage: Skipping progressive refresh (transitioning from manual import to API data) index-BImp0crC.js:579:12031
:counterclockwise_arrows_button: Full refresh (from startDate: 0) - catching all corrections index-BImp0crC.js:579:12381
:rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)… index-BImp0crC.js:579:12643
:bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)… index-BImp0crC.js:579:7458
✓ Using cached profile for “Taitranz” (0m old) index-BImp0crC.js:579:7706
:counterclockwise_arrows_button: Manual hard refresh - will re-learn optimal page size for “Taitranz” index-BImp0crC.js:579:8538
:page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)… index-BImp0crC.js:579:8633
:white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history) index-BImp0crC.js:579:10497
:tada: Total merged data: 10000 events from 1/1 accounts index-BImp0crC.js:579:15604
:white_check_mark: Cached to IndexedDB: 10000 events (4.47MB) index-BImp0crC.js:578:114252
:counterclockwise_arrows_button: Full refresh completed at 10:04:20 am index-BImp0crC.js:579:16998
:pause_button: This fetch was cancelled, skipping state update index-BImp0crC.js:579:17319
:white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history) index-BImp0crC.js:579:10497
:tada: Total merged data: 10000 events from 1/1 accounts index-BImp0crC.js:579:15604
:white_check_mark: Cached to IndexedDB: 10000 events (4.47MB) index-BImp0crC.js:578:114252
:counterclockwise_arrows_button: Full refresh completed at 10:04:22 am index-BImp0crC.js:579:16998
:counterclockwise_arrows_button: Setting API data directly: 10000 events index-BImp0crC.js:579:17507
:counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events index-BImp0crC.js:578:120082
:white_check_mark: Successfully fetched and merged API data: 10000 events index-BImp0crC.js:579:17593
:magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7646), apiData: true (10000), events: 10000 index-BImp0crC.js:578:120397
:high_voltage: Single press: triggering FAST incremental refresh (24h lookback) index-BImp0crC.js:579:11142
:counterclockwise_arrows_button: Setting persisted API cache data directly: 10000 events index-BImp0crC.js:579:11646
:counterclockwise_arrows_button: setApiDataAndUpdate called with: 10000 events index-BImp0crC.js:578:120082
:package: Loaded from persistent API cache: 10000 events (last updated 20s ago) index-BImp0crC.js:579:11765
:high_voltage: Incremental refresh (last 24 hours) - fast updates index-BImp0crC.js:579:12494
:rocket: Fetching from 1 account(s): 0 Business, 1 Pro (incremental: last 24h from 19/10/2025, 10:04:42 am)… index-BImp0crC.js:579:12643
:bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (incremental from 2025-10-19T00:04:42.088Z)… index-BImp0crC.js:579:7458
✓ Using cached profile for “Taitranz” (0m old) index-BImp0crC.js:579:7706
:page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)… index-BImp0crC.js:579:8633
:magnifying_glass_tilted_left: Key state changed - dataSource: api, sampleData: true (7646), apiData: true (10000), events: 10000 index-BImp0crC.js:578:120397
:counterclockwise_arrows_button: Double-press detected: triggering FULL refresh from startDate: 0 index-BImp0crC.js:579:11037
:counterclockwise_arrows_button: Full refresh (from startDate: 0) - catching all corrections index-BImp0crC.js:579:12381
:rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)… index-BImp0crC.js:579:12643
:bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)… index-BImp0crC.js:579:7458
✓ Using cached profile for “Taitranz” (0m old) index-BImp0crC.js:579:7706
:counterclockwise_arrows_button: Manual hard refresh - will re-learn optimal page size for “Taitranz” index-BImp0crC.js:579:8538
:page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)… index-BImp0crC.js:579:8633
:counterclockwise_arrows_button: Double-press detected: triggering FULL refresh from startDate: 0 index-BImp0crC.js:579:11037
:counterclockwise_arrows_button: Full refresh (from startDate: 0) - catching all corrections index-BImp0crC.js:579:12381
:rocket: Fetching from 1 account(s): 0 Business, 1 Pro (full history from 0)… index-BImp0crC.js:579:12643
:bust_in_silhouette: Fetching Pro/Ultra data for “Taitranz” (full history)… index-BImp0crC.js:579:7458
✓ Using cached profile for “Taitranz” (0m old) index-BImp0crC.js:579:7706
:counterclockwise_arrows_button: Manual hard refresh - will re-learn optimal page size for “Taitranz” index-BImp0crC.js:579:8538
:page_facing_up: Fetching page 1 for “Taitranz” (pageSize: 10000)… index-BImp0crC.js:579:8633
:white_check_mark: Pro data for “Taitranz”: 2106 events fetched (new since last fetch) index-BImp0crC.js:579:10497
:counterclockwise_arrows_button: Incremental 24h fetch: processing 2106 events with 10000 existing events… index-BImp0crC.js:579:14471
:white_check_mark: Merged total: 10000 events (7894 kept + 2106 from fetch) index-BImp0crC.js:579:15205
✓ No changes since last fetch index-BImp0crC.js:579:15481
:tada: Total merged data: 10000 events from 1/1 accounts index-BImp0crC.js:579:15604
✓ Data looks complete: 10000 events spanning 112h (oldest: 15/10/2025, 5:10:26 pm) index-BImp0crC.js:579:16623
:white_check_mark: Cached to IndexedDB: 10000 events (4.47MB) index-BImp0crC.js:578:114252
:pause_button: This fetch was cancelled, skipping state update index-BImp0crC.js:579:17319
:white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history) index-BImp0crC.js:579:10497
:tada: Total merged data: 10000 events from 1/1 accounts index-BImp0crC.js:579:15604
:white_check_mark: Pro data for “Taitranz”: 10000 events fetched (full history) index-BImp0crC.js:579:10497
:tada: Total merged data: 10000 events from 1/1 accounts index-BImp0crC.js:579:15604
:white_check_mark: Cached to IndexedDB: 10000 events (4.47MB) index-BImp0crC.js:578:114252
:counterclockwise_arrows_button: Full refresh completed at 10:04:44 am index-BImp0crC.js:579:16998
:white_check_mark: Successfully fetched and merged API data: 10000 events index-BImp0crC.js:579:17593
:white_check_mark: Cached to IndexedDB: 10000 events (4.47MB) index-BImp0crC.js:578:114252
:counterclockwise_arrows_button: Full refresh completed at 10:04:44 am index-BImp0crC.js:579:16998
:pause_button: This fetch was cancelled, skipping state update index-BImp0crC.js:579:17319
:counterclockwise_arrows_button: Refreshing table row 0 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 1 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 2 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 3 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 4 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 5 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 6 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 7 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 8 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 9 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 10 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 11 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 12 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 13 index-BImp0crC.js:578:124759
:counterclockwise_arrows_button: Refreshing table row 14 index-BImp0crC.js:578:124759

```

First of all, this is an absolutely delightful tool for someone who refreshes the dashboard at least once every five requests (me). Second:

  • It needs a manual option to set the exchange rate.
  • It would be helpful to show the dollar amount in small type when a non-dollar currency is chosen as the primary currency.
  • How do you detect “unusually high usage”?
  • All my requests are marked as MAX, even though I hardly used MAX — is that intentional? (I have Pro+)
  • I get that it’s a different metric, but it’s still weird that Savings doesn’t include the value of things received for free beyond the purchased plan.
  • There should be a toggle to turn colors/columns on or off in the chart.
  • First screenshot:
    • “Excellent Cache Usage” should be green.
    • I used GPT-5 Pro only once — it’s strange that it’s listed in High Impact.
    • “3 High-Usage Models Detected Models with unusual usage: GPT-5 High, Grok Code Fast 1, GPT-5. Review these for optimization opportunities.” — that’s a weird message, because most likely those were requests that ran continuously on the models for 15–40 minutes and completed successfully or with some degree of success.
    • “You’re 73.0% over your monthly budget.” — official usage shows I’m over 100%.
  • The Pro+ monthly budget is $70.00, not $60.00.


:thinking::thinking::thinking:

Okay… so the difference was that the API for business accounts and pro/ultra accounts return the same data… there was no pagination and thought it was only 1 page (hence the logs)

All these issues are fixed now, including some fallbacks and more safety margins. I set it to 50k by default for now too. And lastly, you can set the page size yourself in the settings (inside accounts) if all else fails.

Thank you for the feedback! These are all helpful, just shows vibe coding and letting it be free won’t get it perfect :sweat_smile:

And as for your “MAX”, that’s because you have max calls MERGED, you can separate them at the top, select “Split by Mode” or “Fully Separate”.

The pricing you see in there when it’s merged should still account for max/non-max properly, but I can see there’s a big discrepancy. Does the $201.06 line up when you separate them?

The Three Modes:

1. Combined ('merged')

  • Merges everything together
  • Respects “Merge Checkpoints” setting
  • Doesn’t separate by maxMode
  • Example: claude-4-sonnet, claude-4-sonnet-1m, and claude-4-sonnet-2m all merge into one row

2. Split by Mode ('separate-max')

  • Does separate by maxMode (MAX vs non-MAX)
  • Does respect “Merge Checkpoints” setting
  • Example with “Merge Checkpoints” ON:
    • claude-4-sonnet + claude-4-sonnet-1m with maxMode: false → one row
    • claude-4-sonnet + claude-4-sonnet-1m with maxMode: true → separate row

3. Fully Separate ('fully-separated')

  • Does separate by maxMode (MAX vs non-VARIABLE)
  • Ignores “Merge Checkpoints” setting (always keeps variants separate)
  • Example (even with “Merge Checkpoints” ON):
    • claude-4-sonnet (maxMode: false) → separate row
    • claude-4-sonnet-1m (maxMode: false) → separate row
    • claude-4-sonnet (maxMode: true) → separate row
    • claude-4-sonnet-1m (maxMode: true) → separate row

So “Fully Separate” means: separate by MAX mode AND keep all context window variants separate (even if you have “Merge Checkpoints” enabled).

In all modes all models in “Summary by Model” says, that they used in MAX.

This is probably the default label for all requests sent using pay-per-use mechanics (both included and not included in the plan), not the old requests mechanics.

99.9% of the code in my projects over the past six months has been written by Agent. I also heard a good phrase that a vibe coder becomes a software engineer when he begins to analyze what he has done.

You should be able to confirm this by going into either dashboard or cursor tokens → F12 → Network Tab → View the JSON of one of the filtered-events requests.

It looks something like this:

{
	"totalUsageEventsCount": 1918,
	"usageEventsDisplay": [
	{
            "timestamp": "1760312227492",
            "model": "grok-code-fast-1",
            "kind": "USAGE_EVENT_KIND_INCLUDED_IN_PRO_PLUS",
            "requestsCosts": 1.100000023841858,
            "usageBasedCosts": "-",
            "isTokenBasedCall": true,
            "tokenUsage": {
                "inputTokens": 3441,
                "outputTokens": 1331,
                "cacheReadTokens": 2094336,
                "totalCents": 4.457141876220703
            },
            "owningUser": "...",
            "cursorTokenFee": 0
        },
}

"isTokenBasedCall": true → Max

"isTokenBasedCall": false → Non-Max

Can you take a screenshot how it looks like with “Split by Mode”? From my understanding, ALL your calls show up as max?