Skip to content

fix(cursor): read usage from dashboard API when local tokenCount is zero #196

Closed

Description

@florianbehrend

Summary

Cursor usage in PokeTokenBar is read from state.vscdb → cursorDiskKV bubble rows (tokenCount.inputTokens / outputTokens). Since roughly February 2026, new Cursor builds persist 0/0 token counts in those bubbles, so the local SQLite scan under-reports (often showing 0 input tokens) even while the Cursor dashboard shows accurate per-request usage including cache read/write.

Environment

  • macOS: 14+ (Sonoma)
  • PokeTokenBar: 2.5.x (current main)
  • Cursor: logged-in IDE session (cursorAuth/accessToken present in state.vscdb)
  • Repro: use Cursor normally for a day, compare PokeTokenBar Cursor totals vs. cursor.com/dashboard/usage

Expected behavior

Today's Cursor token total (input + output + cache write + cache read) should match the dashboard for the same local day.

Actual behavior

Local bubble parsing finds rows but tokenCount is zero for new usage, so totals are missing or far too low.

Proposed solution

  1. Primary: fetch authoritative usage from the dashboard JSON endpoint the web UI uses:
    • POST /api/dashboard/get-filtered-usage-events (paginated JSON with tokenUsage.cacheReadTokens, etc.)
    • startDate / endDate must be sent as epoch milliseconds in string form; ISO8601 bounds are rejected with HTTP 500.
    • The response carries events under usageEventsDisplay plus a totalUsageEventsCount, which is what pagination should key off when no pagination object is returned.
  2. Auth: read cursorAuth/accessToken from Cursor's state.vscdb (ItemTable) when the user is logged into Cursor IDE. Build the browser cookie as WorkosCursorSessionToken={jwt.sub}::{accessToken}. Allow override via CURSOR_SESSION_TOKEN (also read from login shell through UsageEnvironment). Disable with CURSOR_USAGE_API=0.
  3. Cache: store responses under ~/Library/Application Support/PokeTokenBar/cursor-usage-api-cache.json as an offline fallback when the network request fails (reload on each provider refresh). Scope the cache to the signed-in account and expire it so a stale file cannot silently stand in for live data.
  4. Fallback: keep the existing local bubble scan when API data is unavailable.
  5. No double counting: when dashboard data is present, do not merge stale bubble estimates (different entry ids would inflate totals).

Privacy / network note

This would add cursor.com to the app's outbound hosts when the user is signed into Cursor. The request carries only the session credential needed to read the signed-in user's own usage summary — not prompts, project paths, or chat content. Worth documenting in README Privacy section (similar to the existing Claude limits fetch).

References

Happy to submit a PR implementing the above if this approach sounds good.

Activity

  1. scvsoft-diegomera commented on Aug 24, 2026

    @scvsoft-diegomera

    any news with this? is there any plans to approve these changes and make a release?

  2. b-vb commented on Aug 27, 2026

    @b-vb

    I'm a new user of this t, I'm solely using Cursor, but I found that my whole db has the 0 tokenCount, so the project is currently unusable for me.

    @chattymin anything I can do to help getting this improvement merged?

  3. susishopware commented on Aug 27, 2026

    @susishopware

    First off: great app. The Pokémon framing is doing something no dashboard ever managed, half of my company is suddenly comparing sprites and arguing about graduation thresholds after we found it. Several of us work primarily in Cursor, which is how we ended up here.

    I independently traced this before finding #196, so here is confirming evidence plus two details that may help.

    The cutover has an exact date: 2026-02-06.

    I aggregated tokenCount across all 79,330 bubbleId:* rows in my state.vscdb. The last day with any non-zero value is 2026-02-06. Every bubble after that carries {"inputTokens": 0, "outputTokens": 0} while still setting createdAt correctly. messageRequestContext:* stops at the same rowid, and from there on the new agent stack agentKv:blob:* takes over (108,437 rows in my case). So this is not intermittent 0/0 as "often stores" suggests, it is a clean architectural cutover: the old chat stack carried the counters, the new one does not.

    There is no local fallback left, anywhere.

    Before accepting a network call I tried hard to avoid one. I searched all four cursorDiskKV namespaces, all 1,493 ItemTable keys, 81 workspaceStorage databases, ai-code-tracking.db, conversation-search.db, 30,610 files under ~/.cursor/projects, 2.4 GB of Cursor logs, and every Electron storage layer (Local/Session Storage, IndexedDB, WebStorage, CacheStorage, blob_storage, Partitions). The only hits were JavaScript source and my own chat content. Notably I scanned the 21,148 most recent agentKv blobs, including ones written minutes earlier: no usage fields. The aiserver.v1 protobuf definitions are in the app bundle, so Cursor itself asks the server too.

    That matters for the decision in #197: the dashboard API is not the convenient path, it is the only one. The sole local artifact is cursorAuth/accessToken, exactly as the PR uses it.

    #197 looks blocked on mechanics, not on review. The API reports mergeable_state: dirty, so it currently has conflicts against main. Since two people here are waiting on a release, a rebase might be all that stands in the way.

    Interim workaround for anyone stuck (works on shipped 2.5.2, no patched build):

    Your per-provider additional scan folders from #177/#187 are enough to bridge this. I point customScanRoots.cursor at a folder holding a synthetic state.vscdb with just cursorDiskKV, and a small script writes one bubbleId:* row per day with tokenCount and createdAt, sourced from another tool that already queries the Cursor API. Append-only with per-day deltas, since the reader watermarks on rowid. Cursor totals, weekly, monthly and cost all read correctly again. Only the in/out/cache breakdown is a placeholder, because my source aggregates to a daily total. Happy to share the script if it is useful to others while #197 lands.

    Environment: PokeTokenBar 2.5.2, Cursor 3.15.6, macOS 26.5.2. Cursor plan: Team.

  4. florianbehrend commented on Aug 27, 2026

    @florianbehrend
    ContributorAuthor

    I resolved the merge conflicts. So the pull request would be ready to merge again.

  5. chattymin commented on Aug 29, 2026

    @chattymin
    Owner

    Thanks everyone for the thorough discussion here.

    Sorry for the slow replies. I have a full-time job, so I do check in during the week but can't always keep up, and I mostly get to this project on weekends.

    @florianbehrend thank you for tracking down the cause and putting up the fix, and thanks to everyone who shared reproduction details and evidence. I'll get the change merged and ship a release with it.

    Thanks again to all of you.

  6. added a commit that references this issue on Aug 29, 2026
    4fe965e
  7. added 2 commits that reference this issue on Aug 31, 2026
    003907d
    979726e
  8. added a commit that references this issue on Sep 15, 2026
    6d11dd1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions