feat: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17
, '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: ollama cloud usage meter - #67

Open
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter
Open

feat: ollama cloud usage meter#67
Rtas-17 wants to merge 3 commits into
CodeZeno:mainfrom
Rtas-17:feat/ollama-cloud-usage-meter

Conversation

@Rtas-17

Copy link
Copy Markdown
Contributor

Summary

Adds an Ollama Cloud (ollama.com) usage meter alongside the existing Claude Code, Codex, and Antigravity meters. Ollama exposes a quota page at https://ollama.com/settings but it is HTML, not an API — the only public Ollama Cloud API key only identifies the plan tier, not consumption — so this PR scrapes the aria-labelled percentages from the authenticated settings page using a captured browser session cookie.

How the user authenticates

Ollama Cloud auth is WorkOS-hosted; a raw Cookie: header from a non-Chrome process fails the session-binding check and returns 303 to signin.ollama.com. So this PR includes:

  1. A standalone ollama-login-helper.exe process that opens an embedded WebView2 window (via wry+tao), lets the user complete WorkOS auth, and writes the resulting cookie to %LOCALAPPDATA%\ClaudeCodeUsageMonitor\ollama_session_cookie.txt.
  2. A new tray menu item: right-click → Models → "Log in to Ollama…" — feature-gated behind --features ollama-login-webview (off by default because wry/tao add ~6 MB to the release binary).
  3. Environment-variable fallback: setting OLLAMA_CLOUD_SESSION in env or ~/.claude/settings.json#env.OLLAMA_CLOUD_SESSION also works for headless setups.

What this PR adds

  • src/models.rs: new optional ollama field on AppUsageData
  • src/poller.rs: new poll_ollama() + read_ollama_session_cookie() + fetch_ollama_usage() + parse_ollama_usage() that scrape aria-labelled percentages from ollama.com/settings. Parser unit tests included (parses the real page structure, returns AuthExpired when logged out, returns ParseFailed when structure changes, etc.).
  • src/window.rs: new bar in the widget, Models → Ollama toggle entry, localization entries, draw code. All gated behind the same toggle pattern as the other providers.
  • src/main.rs: registers the new modules
  • src/ollama_login.rs: tray-side helper that spawns the webview login process
  • src/ollama_login_helper.rs: standalone WebView2 process (only built with --features ollama-login-webview) that opens an embedded Edge window, captures cookies, writes them to disk, then exits.
  • Cargo.toml: registers the ollama-login-webview feature, optional wry/tao deps, and the second [[bin]] target for ollama-login-helper
  • src/localization/*: new ollama_model and ollama_window_title strings across all 11 language files

Test plan

  • cargo test passes (12/12 verified locally, including the new ollama parser tests)
  • cargo build --release clean, no warnings
  • cargo build --release --features ollama-login-webview clean
  • Live: tray shows Ollama bar; toggling Models → Ollama shows/hides it and persists across restarts
  • Live: with a captured cookie, the Ollama bar shows the real session/weekly percentages

I verified all of these on Windows 11 locally with the dev account — cookie capture works against ollama.com/settings, returns session=100% and weekly=44.2%.

Design notes

  • Ollama returns an HTML page, not JSON, so I matched the actual aria-label structure with explicit regexes. I added a separate OllamaParseError enum so changes to ollama.com layout surface as PollError::RequestFailed rather than panicking.
  • The webview login is a separate process because wry's EventLoop::run() on Windows must own the Win32 message pump — running it inside the tray's DispatchMessageW handler starves the event loop and WebView2 doesn't paint.
  • The tray process never embeds wry/tao. The helper exe is the only thing that depends on it. Default builds add zero new dependencies.
  • The Ollama parser deliberately fails (rather than showing fake zeros) when there's no cookie. The tray displays ! in the bar to make the missing-auth state obvious.

Why this is upstream-friendly

  • No new runtime dependencies in the default build (wry/tao are feature-gated).
  • Parser unit tests cover the happy path, zero-usage, and structure-change cases.
  • Cookie capture is non-invasive — the tray just writes a plain text file the poller reads back.

What's not in this PR

Risks

  • Ollama.com layout change would break parsing. Mitigated by explicit OllamaParseError::AuthExpired and ParseFailed returning rather than panicking, plus the test fixtures.
  • The cookie is captured in a regular WebView2 process rather than the user's Chrome profile, so it's a separate session. This is fine for Ollama Cloud auth because Ollama doesn't bind to the browser identity like Anthropic does — only the session cookie matters.

Let me know if you'd like the PR split or merged differently — happy to split out the webview login helper into a follow-up PR if you'd rather review the parsing change alone first.

Working tree before branch split. Will be reorganized into feat/ollama-cloud-usage-meter,
feat/minimax-usage-meter, and feat/fable-5-usage-meter as separate commits.
Adds an Ollama Cloud (ollama.com) usage meter alongside Claude Code, Codex,
and Antigravity. The Ollama Cloud usage page is HTML, not an API, so this
commits a browser-style session cookie capture path:
- src/models.rs: new optional 'ollama' field on AppUsageData
- src/poller.rs: new fetch_ollama_usage() + parse_ollama_usage() that scrape
the aria-labelled percentages from ollama.com/settings using a captured
session cookie. Includes parser tests.
- src/window.rs: new bar in the widget, models menu entry, localization,
draw code. All gated behind the same toggle pattern as the other providers.
- src/main.rs: registers the new modules
- src/ollama_login.rs: tray-side helper that spawns the webview login process
- src/ollama_login_helper.rs: standalone WebView2 process (only built with
--features ollama-login-webview) that opens an embedded Edge window,
captures the cookie after WorkOS auth, and writes it to disk.
- Cargo.toml: registers the ollama-login-webview feature, wry/tao optional
deps, and the second [[bin]] target for ollama-login-helper
- src/localization/*: new ollama_model and ollama_window_title strings
How users get a cookie: right-click the tray -> Models -> 'Log in to Ollama...'
(or set OLLAMA_CLOUD_SESSION in env). Without a cookie the bar shows '!' until
the user authenticates.
Verified locally: cookie capture works against ollama.com/settings, returns
session=100% and weekly=44.2% for the test account. 12/12 tests pass, builds
clean for both --features ollama-login-webview and the default feature set.
CopilotAI review requested due to automatic review settings July 24, 2026 18:44

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 an Ollama Cloud usage meter to the existing multi-provider usage monitor, including polling/scraping Ollama’s authenticated settings page and optional WebView2-based login helper tooling.

Changes:

  • Extend the usage data model and poller to optionally fetch/parse Ollama session + weekly usage from https://ollama.com/settings.
  • Update the widget/tray UI to render and toggle an Ollama meter, including localized model/window strings.
  • Add a feature-gated ollama-login-helper binary and tray integration to capture an authenticated cookie via WebView2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/window.rsAdds Ollama state, UI rendering, tray/menu toggles, and polling integration.
src/poller.rsAdds Ollama polling/scraping, parsing helpers, and unit tests; updates polling aggregation.
src/ollama_login.rsAdds tray-side helper spawner for the feature-gated login flow.
src/ollama_login_helper.rsAdds the standalone WebView2 login helper that captures cookies to disk.
src/models.rsExtends AppUsageData with an optional ollama usage section.
src/main.rsRegisters the optional ollama_login module behind the feature gate.
src/localization/*Adds ollama_model and ollama_window_title strings across languages.
src/localization/mod.rsExtends the Strings struct to include Ollama strings.
Cargo.tomlAdds the ollama-login-webview feature, optional deps, and the helper [[bin]] target.
Cargo.lockUpdates lockfile for new optional dependencies.

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

Comment threadsrc/window.rs
Comment threadsrc/window.rs
Comment threadsrc/poller.rs Outdated
Comment threadsrc/ollama_login_helper.rs
Comment threadsrc/ollama_login_helper.rs
@Rtas-17Rtas-17 mentioned this pull request Jul 25, 2026
5 tasks
- Give Ollama its own TrayIconKind so it no longer shares Antigravity's
tray slot/styling when both are enabled.
- Use Ollama-specific auth balloon copy when only Ollama is enabled.
- Fix GNOME-shell typo in the poller comment.
- Set windows_subsystem = "windows" on ollama-login-helper so tray login
does not spawn an extra console window.
- Document why the session cookie file stays plaintext (same trust
boundary as OLLAMA_CLOUD_SESSION / settings.json overrides).
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants

@Rtas-17