cursorhub
Track your Cursor subscription usage from a desktop tray toast or the terminal.
- Tray toast (
cursorhub): an always-on-top card in the top-right corner showing your included-plan percentage, on-demand spend, and when the billing cycle resets. Refreshes every 5 minutes; dodges out of the way when your cursor gets near it. - CLI (
cursorhub usage, or the dependency-freestandalone/cursor_usage.py): print usage on demand as a table or JSON. - Day heartbeat (
cursorhub mark): send one tiny real Cursor request per calendar day so the day shows up as active in the Cursor dashboard, even if you never opened the editor. Off unless Cursor's CLI is installed.
How it works
Cursor stores a session JWT in its local VS Code-style state database
(state.vscdb, key cursorAuth/accessToken). Your userId is the sub claim of
that token. Cursor's own web dashboard authenticates to cursor.com/api/* with a
cookie WorkosCursorSessionToken={userId}::{token}. cursorhub reads the token,
builds the same cookie, and calls GET /api/usage-summary.
This needs no API key and works for any signed-in Cursor user - Pro,
Business, or a member of an Enterprise team. You do not need to be a team
admin (the official api.cursor.com/teams/* Admin API is admin-only; cursorhub
does not use it).
The state DB is read from:
| OS | Path |
|---|---|
| Windows | %APPDATA%\Cursor\User\globalStorage\state.vscdb |
| macOS | ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb |
| Linux | ~/.config/Cursor/User/globalStorage/state.vscdb |
Install
pip install cursorhub
Or from a checkout:
pip install -e .
The tray app needs PySide6 (pulled in automatically). The standalone script needs nothing but Python 3.11+.
Usage
cursorhub # launch the tray toast
python -m cursorhub # same thing
cursorhub usage # print a table (your usage)
cursorhub usage team # your usage plus team usage
cursorhub usage --json # normalized JSON
cursorhub usage --raw # raw Cursor API responses (debugging)
cursorhub mark # mark today as a Cursor-used day
cursorhub mark --status # heartbeat state, no request sent
python standalone/cursor_usage.py # no install required
python standalone/cursor_usage.py --json
Example table (cursorhub usage):
Cursor usage - you@example.com (enterprise)
====================================================
Included plan [######------------------] 25.6%
included 2000 + bonus 45 = 2045
On-demand (you) $0.00 / $300.00 left $300.00
Billing cycle resets in 24d 13h (2026-08-11T19:09:10.000Z)
You've used 26% of your included total usage
With cursorhub usage team, team usage appears between the on-demand block
and the billing cycle:
Cursor usage - you@example.com (enterprise)
====================================================
Included plan [######------------------] 25.6%
included 2000 + bonus 45 = 2045
On-demand (you) $0.00 / $300.00 left $300.00
Team usage
On-demand (team)$342.16 / $2,500.00 left $2,157.84
Billing cycle resets in 24d 13h (2026-08-11T19:09:10.000Z)
You've used 26% of your included total usage
Marking the day as used
Reading usage does not count as usage. GET /api/usage-summary is a passive
dashboard read - polling it all day long will never make a day show up as active
on cursor.com. The only thing that registers a day is a genuine model request
billed to your account.
So cursorhub can send one, once per calendar day, through Cursor's official CLI.
It looks for cursor-agent on PATH, then in ~/.local/bin, and finally falls
back to the copy Cursor's own agent-worker extension keeps under globalStorage
- so on a machine with the Cursor editor installed there is usually nothing to
install. Check with
cursorhub mark --status; if it saysnot found:
irm 'https://cursor.com/install?win32=true' | iex # macOS/Linux: curl https://cursor.com/install -fsS | bash
cursor-agent login
cursor-agent status
Then:
cursorhub mark # mark today if it isn't already marked
cursorhub mark --force # mark again regardless
cursorhub mark --status # show state; makes no request
The tray app does this for you: once at launch and on every 5-minute tick. After
the first success each day the check is just a date comparison against
heartbeat.json in cursorhub's state directory - no subprocess, no request. Left
running overnight, it marks the new day on the first tick after midnight. The
tray menu also has Mark today used now.
Two things worth knowing:
- It costs real usage. One short prompt per day, on your account. Set
CURSORHUB_HEARTBEAT=0to turn it off entirely. - It never runs tools. The request goes out as
cursor-agent -p ... --mode ask --trust:--mode askis read-only (no edits, no shell),--trustskips the workspace-trust prompt that would otherwise block a headless run, and it all happens in a throwaway temp directory.
With no cursor-agent anywhere, cursorhub carries on as before: the toast shows
no cursor-agent and cursorhub mark exits non-zero with a clear message.
Configuration (env vars)
| Variable | Purpose |
|---|---|
CURSOR_SESSION_TOKEN |
Use this raw JWT instead of reading the state DB |
CURSOR_STATE_DB |
Path to a non-default state.vscdb |
CURSORHUB_HEARTBEAT |
0/false disables the once-a-day "mark as used" request |
CURSORHUB_AGENT_BIN |
Explicit path to cursor-agent (else PATH, then ~/.local/bin) |
CURSORHUB_HEARTBEAT_MODEL |
Model for the daily request (else your account default) |
CURSORHUB_HEARTBEAT_PROMPT |
Prompt for the daily request |
CURSORHUB_STATE_DIR |
Where heartbeat.json lives (default %APPDATA%\cursorhub) |
Caveats
- These dashboard endpoints are unofficial / internal to Cursor and can change without notice. Every call degrades to a clear error rather than crashing.
- The session token expires when you sign out of Cursor. Sign back in and the tray toast recovers on its next refresh.
- On-demand amounts are reported by Cursor in cents and shown here in whole dollars.
License
MIT - see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cursorhub-0.1.3.tar.gz.
File metadata
- Download URL: cursorhub-0.1.3.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
988ee0938a32a01f6106a34146cd02b9ed14c2b411744a9b6290d53eac516a7c
|
|
| MD5 |
9c9605e8a6838429ca1ae621ea027e8a
|
|
| BLAKE2b-256 |
d9669ac7584089e620096d46d9a0911c6e978e521af58380a1c1c412d53e24cd
|
File details
Details for the file cursorhub-0.1.3-py3-none-any.whl.
File metadata
- Download URL: cursorhub-0.1.3-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cba975a465a09259fc3069c97902dd651263e449a36898c51e36e94cb9b807d9
|
|
| MD5 |
c371a1423bf5a3c9ef090c77386f86fa
|
|
| BLAKE2b-256 |
be1dbf25b0376c4fbd2bd537c4fc37b9c445552c443b23e518f702ceeb55c2dd
|