Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate. [Bug]: CLIProxy reset times are available in Usage but missing from thread recovery; queued messages block snoozing #26574 is related: it covers CLIProxy data missing from thread recovery. This issue covers the thread-details Limits row.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web
Steps to reproduce
- Add a Claude provider instance (driver
claudeAgent) with environmentANTHROPIC_BASE_URL=http://127.0.0.1:8317andANTHROPIC_AUTH_TOKEN=<CLIProxyAPI client key>. - Add a usage limit source
kind: "cliproxy"with the same URL and the management key. The hub has exactly one Claude OAuth account. - Open a thread on that provider, then open thread details with "Usage limits" enabled.
Expected behavior
The Limits row shows the 5h and weekly windows of the hub's Claude account, which is the account that actually serves this provider's requests.
Actual behavior
- Thread details shows Limits: Unavailable.
- The Usage dialog shows the same account's limits from the CLIProxyAPI source correctly (5h 32%, 7d 5% at the time).
UsageLimitSources.readSourcesucceeds. A manual managementapi-calltohttps://api.anthropic.com/api/oauth/usagefor that account returns 200 with validfive_hourandseven_daydata.
Cause, traced in the shipped 0.1.7 bundle:
- The provider's own limits are always unavailable here. A non-
api.anthropic.comANTHROPIC_BASE_URLmakes the Claude provider auth{ type: "customEndpoint" }with no email.probeClaudeCapabilitiesgets no usage from Claude Code in env-token mode, so the result ismakeUnavailableUsageLimits({ reason: "probeFailed" }). - Source accounts are never tied to a provider instance. The report builder used by thread details, in the web
usageLimitsmodule, pushes provider entries withinstanceIdand cliproxy source accounts (sourceLabel: "CLI Proxy") withoutinstanceId. - Thread details looks up by
instanceIdonly:So it always falls back to step 1's unavailable limits.report?.accounts.find(e => e.instanceId === threadInstanceId)?.limits ?? providers.find(e => e.instanceId === threadInstanceId)?.usageLimits
- Email merging can't help. The
driver:emailkey isnullbecause the custom-endpoint provider has noauth.email.
Suggested fix: when the thread's claudeAgent provider has auth.type === "customEndpoint" and its ANTHROPIC_BASE_URL matches an enabled cliproxy source url (after normalising scheme, host, port and trailing slash), use that source's Claude account limits in thread details:
- Exactly one non-disabled Claude account: use its
usageLimits. - More than one: keep
Unavailable, with a tooltip saying the hub has several accounts and routing is ambiguous. Don't guess. - Same idea for
codexproviders pointed at a hub viaOPENAI_BASE_URL.
Not covered by this fix: per-turn rate_limit_event. Claude Code doesn't emit it in env-token mode even when the proxy forwards the anthropic-ratelimit-unified-* headers (CLIProxyAPI requests.passthrough-headers: true; verified forwarded).
Impact
Minor bug or occasional failure
Version or commit
T3 Code desktop 0.1.7
Environment
Windows 11 Pro, Claude Code 2.1.318, CLIProxyAPI 8.0.44 on localhost
Logs or stack traces
Provider event logs: direct claudeAgent threads contain rate_limit_event entries; cliproxyapi-claude threads contain 0.
UsageLimitSources.readSource / publish: exit Success.
Workaround
Read the limits from the Usage dialog (CLIProxyAPI source).
Activity
EhsanulHaqueSiam commentedon Nov 4, 2026
Note
🤖 Opus 5.5 responding on behalf of EhsanulHaqueSiam
#27740 fixes this case. In its
resolveThreadDetailsLimits(apps/web/src/components/chat/ThreadDetailsUsage.logic.ts), when the instance's own limits carry a notice (hereprobeFailed), the card falls back to a connected hub if exactly one hub account serves that driver, and the rows sayFrom <hub label>.canServeInstanceskips a hub account only when both sides have an email and they differ, so acustomEndpointinstance with no email still matches the hub's Claude account. Codex instances take the same path.Two differences from the suggested fix:
ANTHROPIC_BASE_URLwith the source URL.For hubs with several accounts, #29978 (built on #27740) uses the account the hub's
usage-queuerecorded for the thread's session id, opt-in per hub. #30634 takes a different approach to that case.I read #27740's code but have not run your exact setup (
ANTHROPIC_BASE_URLin the provider instance's environment) against it.