feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: cursor usage meter - #68

Merged
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream
Aug 16, 2026
Merged

feat: cursor usage meter#68
CodeZeno merged 2 commits into
CodeZeno:mainfrom
Rtas-17:feat/cursor-usage-meter-upstream

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor usage meter next to Claude Code, Codex, and Antigravity.

Cursor already keeps the signed-in JWT in its local state.vscdb, and cursor.com/api/usage-summary returns JSON with Auto / API percentages for the current billing cycle. So this is a straight SQLite read + HTTP call — no HTML scraping, no separate login helper.

How auth works

  1. Read cursorAuth/accessToken from %APPDATA%\Cursor\User\globalStorage\state.vscdb (read-only; copies to a temp file if Cursor has the DB locked).
  2. Decode the JWT sub, take the id after the last |, and build WorkosCursorSessionToken=<id>%3A%3A<jwt>.
  3. Optional override: set CURSOR_SESSION_TOKEN to the raw cookie value or JWT if the IDE DB isn't available.

If there's no token the Cursor bar shows ! until you sign in to Cursor (or set the env var).

What this PR adds

  • src/models.rs: optional cursor field on AppUsageData
  • src/poller.rs: poll_cursor() / cookie helpers / fetch_cursor_usage() mapping autoPercentUsed → session bar and apiPercentUsed → weekly bar, with billingCycleEnd as the shared reset. Unit test for the mapping included.
  • src/window.rs: widget bar, Models → Cursor toggle, tray tooltip uses Auto/API wording. When Cursor is the only model enabled, row labels switch from 5h/7d to Auto/API — Cursor has a monthly pool, not a rolling 5-hour window.
  • src/localization/*: cursor_model, cursor_window_title, cursor_auto_window, cursor_api_window
  • Cargo.toml: rusqlite with the bundled feature so we can read the state DB without a system SQLite install

Test plan

  • cargo test passes (verified locally, including cursor_usage_maps_auto_and_api_percentages)
  • cargo build --release clean
  • Live: Models → Cursor shows/hides the bar and persists across restarts
  • Live: with Cursor signed in, Auto/API percentages match https://cursor.com/dashboard
  • Live: Cursor-only mode shows Auto/API labels instead of 5h/7d; mixed with Claude keeps 5h/7d

I checked this on Windows 11 against a Pro account — usage-summary returned Auto ~1%, API 0%, reset at billingCycleEnd.

Design notes

  • Cursor's plan is monthly included usage (Auto + API). There is no Claude-style 5-hour window in the API response, so both bars share billingCycleEnd.
  • Token is read from disk on each poll and never stored by this app. Requests go only to cursor.com over HTTPS.
  • Default build gains rusqlite (bundled). No webview / wry / tao.

What's not in this PR

Risks

  • Cursor changes the usage-summary shape — mitigated by optional fields + a unit test on the known response. Failures show ! rather than fake zeros.
  • state.vscdb locked while Cursor is open — we open read-only and fall back to a temp copy if needed.

Happy to tweak the Auto/API labeling or split anything out if you'd rather review differently.

Adds a Cursor usage meter alongside Claude Code, Codex, and Antigravity.
Cursor stores the signed-in JWT in its local state.vscdb and exposes a JSON
usage summary at cursor.com/api/usage-summary - no HTML scraping needed.
- src/models.rs: new optional 'cursor' field on AppUsageData
- src/poller.rs: read cursorAuth/accessToken from state.vscdb via rusqlite
(bundled), with CURSOR_SESSION_TOKEN env fallback, build the
WorkosCursorSessionToken cookie (user id decoded from the JWT sub claim
joined with the token via ::), and map autoPercentUsed / apiPercentUsed
onto the two bars. billingCycleEnd is the shared reset for both. Includes
a unit test for the mapping (cursor_usage_maps_auto_and_api_percentages).
- src/window.rs: new bar in the widget, Models -> Cursor toggle, tray
tooltip uses "Auto: ... | API: ..." wording. When Cursor is the only
model shown, the row labels switch from 5h/7d to Auto/API since Cursor
has no rolling 5-hour window. Accent is near-black, inverted for dark
taskbars.
- src/localization/*: new cursor_model, cursor_window_title,
cursor_auto_window, cursor_api_window strings across all locales
- Cargo.toml: rusqlite (bundled) to read the Cursor IDE state DB
Verified locally: cargo test --bin claude-code-usage-monitor passes
6/6 (including the new Cursor mapping test), release build unaffected.
Co-authored-by: Cursor <cursoragent@cursor.com>
CopilotAI review requested due to automatic review settings July 25, 2026 20:36

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Cursor” provider to the usage monitor, including polling Cursor’s usage-summary API using a session token sourced from the Cursor IDE’s local state DB (or an env var override), plus UI/toggle/localization updates to render the new meter.

Changes:

  • Extend the core usage model to include optional Cursor usage data.
  • Implement Cursor polling: read session token (env var or state.vscdb), call https://cursor.com/api/usage-summary, and map Auto/API percentages into the existing session/weekly bars.
  • Update the Windows UI/tray + settings + localization to add a Cursor toggle and display Auto/API labeling when Cursor is the only active model.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/window.rsAdds Cursor state fields, toggle plumbing, tray tooltip/icon entries, and bar rendering (including Cursor-only Auto/API labels).
src/poller.rsAdds Cursor poller: token resolution from env/SQLite, usage-summary HTTP fetch, and response mapping + unit test.
src/models.rsAdds AppUsageData.cursor: Option<UsageData> for Cursor usage.
src/localization/mod.rsExtends Strings with Cursor labels/titles (model name + Auto/API window labels + window title).
src/localization/english.rsAdds Cursor strings in English.
src/localization/dutch.rsAdds Cursor strings in Dutch.
src/localization/spanish.rsAdds Cursor strings in Spanish.
src/localization/french.rsAdds Cursor strings in French.
src/localization/german.rsAdds Cursor strings in German.
src/localization/japanese.rsAdds Cursor strings in Japanese.
src/localization/korean.rsAdds Cursor strings in Korean.
src/localization/traditional_chinese.rsAdds Cursor strings in Traditional Chinese.
src/localization/simplified_chinese.rsAdds Cursor strings in Simplified Chinese.
src/localization/russian.rsAdds Cursor strings in Russian.
src/localization/portuguese_brazil.rsAdds Cursor strings in Portuguese (Brazil).
Cargo.tomlAdds rusqlite (bundled) dependency for reading Cursor’s local state DB.
Cargo.lockLocks new dependency graph for rusqlite/sqlite.
Comments suppressed due to low confidence (1)

src/window.rs:500

  • In the loading/error tray-icon state, Cursor is also assigned TrayIconKind::Codex, so hovering is the only way to distinguish it from Codex. If Cursor is meant to have its own tray indicator, it should use a dedicated icon kind.
 if s.show_cursor {
icons.push(tray_icon::TrayIconData {
kind: tray_icon::TrayIconKind::Codex,
percent: None,
tooltip: s.language.strings().cursor_window_title.to_string(),
});

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/window.rs
Comment threadsrc/window.rs
- Give Cursor its own TrayIconKind so it no longer shares Codex's tray
slot/styling when both are enabled.
- Use localized cursor_auto_window / cursor_api_window strings in the
Cursor tray tooltip instead of hard-coded English.
- Also wire Cursor-only auth balloon copy to the Cursor tray icon
(same class of bug as the Ollama review).
Co-authored-by: Cursor <cursoragent@cursor.com>
@CodeZeno
CodeZeno merged commit 39dcbde into CodeZeno:mainAug 16, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Rtas-17@CodeZeno