feat: add ClinePass usage provider#1888
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.
|
Codex review: needs maintainer review before merge. Reviewed July 4, 2026, 11:34 AM ET / 15:34 UTC. Summary Reproducibility: not applicable. as a feature PR. For the prior PR bug, source and test inspection show the versioned base URL path now normalizes and has regression coverage. 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:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the provider only after maintainers accept ClinePass's API-key quota endpoint contract, or keep the linked feature request open until Cline documents or supports that third-party contract. Do we have a high-confidence way to reproduce the issue? Not applicable as a feature PR. For the prior PR bug, source and test inspection show the versioned base URL path now normalizes and has regression coverage. Is this the best way to solve the issue? Unclear until maintainers accept the endpoint contract. The implementation is narrow and follows provider patterns, but the linked owner direction requested supported quota endpoints before merging dashboard-derived API use. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 3191f129f994. Label changesLabel changes:
Label 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
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4a81bb9f4
ℹ️ 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".
| } | ||
| let prefix = components.percentEncodedPath | ||
| let trimmedPrefix = prefix.hasSuffix("/") ? String(prefix.dropLast()) : prefix | ||
| components.percentEncodedPath = trimmedPrefix + encodedSuffix |
There was a problem hiding this comment.
Normalize Cline API base path before appending endpoints
When CLINE_API_BASE_URL is set to Cline's documented API base such as https://api.cline.bot/api/v1 (their examples call /api/v1/...: https://docs.cline.bot/api/getting-started), this preserves that path and then appends another /api/v1, so the provider requests /api/v1/api/v1/users/me and all account reads fail. Either treat the override as the versioned API root and append /users/me, or strip an existing /api/v1 before adding these suffixes.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 3b737da. endpoint() now normalizes the base path — it strips a trailing slash and a trailing /api/v1 (case-insensitive) before appending the versioned suffix, so both the bare host (https://api.cline.bot) and Cline's documented versioned root (https://api.cline.bot/api/v1) resolve to a single /api/v1/... path instead of doubling it. Host-level prefixes (e.g. a reverse-proxy /gateway) are preserved. Verified live against api.cline.bot with a versioned CLINE_API_BASE_URL, and added normalizedBasePath unit tests plus an integration test asserting no doubled /api/v1.
Behavior ProofCLI output (
|
|
Proof: PR builds, compiles, and runs clean against live ClinePass API.
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
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. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed the sole blocking review finding (doubled Fix: Verification:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
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.