feat: add ClinePass usage provider#1896
Conversation
Add support for ClinePass, Cline's flat-rate subscription, surfacing
its three rolling usage windows (5-hour, weekly, monthly) as percentage
bars with reset countdowns, plus plan name and account email.
Data source: three Cline account API endpoints behind a single
CLINE_API_KEY (Bearer auth, {success,data,error} envelope):
- GET /api/v1/users/me -> account email
- GET /api/v1/users/me/plan -> plan displayName
- GET /api/v1/users/me/plan/usage-limits -> server-computed
{ type, percentUsed, resetsAt } per window (five_hour/weekly/monthly)
The /plan and /plan/usage-limits endpoints are dashboard-derived (not
in Cline's published Enterprise API Reference); usage-limits is fetched
best-effort so a 404 or transient failure degrades to showing plan name
+ email without usage windows rather than failing the whole fetch.
The three reads are independent (all use the literal 'me' path) and run
concurrently via withThrowingTaskGroup, collapsing three serialized
round trips into one (~0.7s -> ~0.25s). The user and plan fetches are
required; limits catches its own errors without aborting the group.
Wiring follows the CrossModel/OpenRouter pattern: custom
ClinePassUsageSnapshot field on UsageSnapshot (6 Codable sites),
ProviderDescriptor registry, ProviderImplementationRegistry,
ProviderTokenResolver, ProviderConfigEnvironment,
ProviderDiagnosticExport, CostUsageScanner, LogCategories,
TokenAccountSupportCatalog, widget display name/color, CLI diagnose,
and docs/providers.md (count 57 -> 58).
Additional hardening vs the initial implementation:
- parseTimestamp uses a two-formatter approach (withFractionalSeconds
then plain) to handle timezone offsets (Z, +HH:mm, +HHmm) that the
original truncating parser silently dropped.
- ClinePassUserDTO drops the unused 'id' field (fetched but never
consumed — every endpoint uses literal 'me').
- ClinePassUsageError.networkError removed (dead code, never thrown).
- Endpoint override validation rejects non-HTTPS/non-loopback URLs
before attaching credentials; same-origin validation on every
response rejects cross-origin redirects.
Tests: 13 core tests (snapshot mapping, full fetch flow, pagination,
401/envelope-error/cross-origin rejection, Codable round-trip, timestamp
parsing) plus menu descriptor, CLI output, CLI diagnose, config env,
diagnostic export, icon resources, providers pane, token account
precedence, and debug log coverage.
Docs: docs/clinepass.md, docs/providers.md updated.
Addresses PR steipete#1888 review (Codex + ClawSweeper): when CLINE_API_BASE_URL is set to Cline's documented versioned root (https://api.cline.bot/api/v1), the endpoint builder preserved that path and appended another /api/v1, producing /api/v1/api/v1/users/me so every account read 404'd. endpoint() now strips a trailing slash and a trailing /api/v1 (case-insensitive) from the base path before appending the versioned suffix, so both the bare host and the versioned root resolve to the same URL. Host-level prefixes (e.g. a reverse-proxy /gateway) are preserved. Adds unit coverage for normalizedBasePath edge cases and an integration test asserting a versioned base URL never yields a doubled /api/v1 path.
|
Codex review: found issues before merge. Reviewed July 4, 2026, 4:44 PM ET / 20:44 UTC. Summary Reproducibility: not applicable. as a feature PR. Current-main source inspection confirms the provider is absent, and the posted screenshots show the proposed provider rendering after a live setup. Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land the provider only after maintainers accept the ClinePass API-key quota endpoint contract, or keep #1786 open until Cline documents or supports it. Do we have a high-confidence way to reproduce the issue? Not applicable as a feature PR. Current-main source inspection confirms the provider is absent, and the posted screenshots show the proposed provider rendering after a live setup. Is this the best way to solve the issue? Unclear until maintainers accept the endpoint contract. The implementation is narrow and follows existing provider patterns, but related owner guidance requested a supported ClinePass quota contract before code lands. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 23e2d30d3cbe. Label changesLabel justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (6 earlier review cycles)
|
Replace the placeholder ticket glyph with Cline's official bot logomark (from cline.bot/brand, Bot icon SVG), simplified to a single currentColor path so it renders as a menu-bar template image and recolors to the label color like every other provider icon.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39b8d0cec8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Addresses PR steipete#1896 Codex review (P2): the /plan/usage-limits task's best-effort catch converted a cancelled refresh into .limits(nil), so fetchUsage returned a successful partial snapshot (plan + email, no windows) that the caller then recorded instead of suppressing the cancelled refresh. The catch now rethrows CancellationError and cancelled URLError, and checks Task.isCancelled before treating a limits failure as best-effort — matching the CrossModel fetcher's cancellation handling. Only genuine endpoint failures (404/transient) still degrade to plan + email. Adds two regression tests asserting a cancelled limits request propagates CancellationError rather than yielding a partial snapshot.
Review follow-ups1. Cancellation (Codex P2) — fixed in bf89ddf. 2. Quota-window contract (addresses @steipete's audit on #1786 and ClawSweeper's rank-up P2). The audit correctly noted that Cline's published Enterprise API Reference only documents
This returns server-computed used%/reset per window — exactly the "map each to a CodexBar Design decisions matching the audit's guardrails:
Live verification (real ClinePass account at All three endpoints return 200; the percentages match the Cline web dashboard's Usage limits page exactly. Caveat for maintainer sign-off: |
|
@clawsweeper re-review — Codex P2 (cancellation) fixed in bf89ddf with regression tests; quota-window contract + live verification documented above. |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@codex review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
The prior cancellation tests threw CancellationError / URLError.cancelled synchronously, exercising only the two typed catch arms. Add an end-to-end test that cancels the parent refresh while /plan/usage-limits is genuinely in flight and the transport then fails with a GENERIC error (URLError.timedOut) — the case the `if Task.isCancelled` guard exists for. An actor gate cancels only once the limits request is in flight to avoid a dispatch/cancel race. Verified load-bearing: with the Task.isCancelled guard removed the test fails (a partial plan+email snapshot is returned instead of propagating cancellation); with it restored, all 20 ClinePass tests pass.
|
@clawsweeper re-review — added behavior-proof screenshots to the PR description (menu card + Settings → Providers pane, both showing the live ClinePass usage windows against a real account, email redacted). |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Maintainer decision needed: ClinePass quota endpoint@steipete — this PR is blocked on one call that only you can make (per your contract audit on #1786), so here's the decision teed up. No further code change will move it. The one open questionClinePass exposes its 5-hour / weekly / monthly usage windows only through So there is currently no Cline-published quota API to target. The feature is only implementable today via this dashboard-derived endpoint. How the PR respects your audit's guardrails
Live proof (screenshots in the PR description)Verified against a real ClinePass account at Your options (from ClawSweeper's review)
Happy to adjust to whichever direction you prefer. The code, tests (20 ClinePass tests incl. an adversarially-verified cancellation regression), logo, and docs are otherwise complete. |
|
@clawsweeper re-review — the only remaining item is a maintainer decision on the dashboard-derived |
The merge combined the ClinePass CostUsageScanner change with upstream's CostUsage updates; regenerate the vendored-parser hash to match the merged source (lint enforces it).
Summary
Adds a new ClinePass provider to CodexBar, surfacing Cline's flat-rate subscription usage as three rolling percentage bars (5-hour, weekly, monthly) with reset countdowns, plus plan name and account email.
Data source
Three Cline account API endpoints behind a single
CLINE_API_KEY(Bearer auth,{success,data,error}envelope):GET /api/v1/users/me→ account emailGET /api/v1/users/me/plan→ plandisplayNameGET /api/v1/users/me/plan/usage-limits→ server-computed{ type, percentUsed, resetsAt }per window (five_hour/weekly/monthly)The
/planand/plan/usage-limitsendpoints are dashboard-derived (extracted from the Cline web dashboard's JavaScript bundle — not in Cline's published Enterprise API Reference). Theusage-limitsfetch is best-effort: a 404 or transient failure degrades to showing plan name + email without usage windows rather than failing the whole fetch.Concurrency
The three reads are independent (all use the literal
mepath) and run concurrently viawithThrowingTaskGroup, collapsing three serialized round trips into one (~0.7s → ~0.25s). Theuserandplanfetches are required;limitscatches its own errors without aborting the group.Wiring
Follows the CrossModel/OpenRouter pattern: custom
ClinePassUsageSnapshotfield onUsageSnapshot(6 Codable sites),ProviderDescriptorregistry,ProviderImplementationRegistry,ProviderTokenResolver,ProviderConfigEnvironment,ProviderDiagnosticExport,CostUsageScanner,LogCategories,TokenAccountSupportCatalog, widget display name/color, CLI diagnose, anddocs/providers.md(count 57 → 58).Hardening
parseTimestampuses a two-formatter approach (withFractionalSecondsthen plain) to handle timezone offsets (Z,+HH:mm,+HHmm) that the original truncating parser silently dropped.ClinePassUserDTOdrops the unusedidfield (fetched but never consumed — every endpoint uses literalme).ClinePassUsageError.networkErrorremoved (dead code, never thrown).Commands run
swift build -c release— cleanswift build— clean (after rebasing onto latestmainwith ClawRouter provider)./Scripts/regenerate-codex-parser-hash.sh— hash updated to75eb44533cdd6d4c./Scripts/package_app.shand launched — confirmed runningTests
13 core tests (
ClinePassUsageStatsTests): snapshot mapping, full fetch flow, pagination, 401/envelope-error/cross-origin rejection, Codable round-trip, timestamp parsing. Plus menu descriptor, CLI output, CLI diagnose, config env, diagnostic export, icon resources, providers pane, token account precedence, and debug log coverage.Screenshots
Enable ClinePass in Settings → Providers → ClinePass, paste your API key (created at app.cline.bot → Settings → API Keys). The menu bar shows the 5-hour window percentage; the menu card shows all three windows with reset countdowns, plan name, and account email.
Menu card — ClinePass with the Cline bot logo, plan name, and all three usage windows (account email redacted):
Settings → Providers pane —
Source: api,Plan: Cline Pass (Monthly), the three usage windows, and the Menu bar metric picker:Review fix (base-URL normalization)
Addresses the Codex + ClawSweeper review on the prior PR: when
CLINE_API_BASE_URLis set to Cline's documented versioned root (https://api.cline.bot/api/v1), the endpoint builder previously preserved that path and appended another/api/v1, producing/api/v1/api/v1/users/meso every account read 404'd.endpoint()now normalizes the base path — strips a trailing slash and a trailing/api/v1(case-insensitive) before appending the versioned suffix — so both the bare host and the versioned root resolve to the same URL; host-level prefixes (e.g. a reverse-proxy/gateway) are preserved. AddednormalizedBasePathunit coverage and a doubled-path regression test. Verified live againstapi.cline.botwith a versioned base URL.Supersedes #1888 (recreated on a clean branch with tidied commit history; same diff).