A CLIProxyAPI scheduler plugin for Claude and Codex OAuth accounts. It routes each request to the eligible account whose weekly quota resets soonest, so quota that would otherwise expire unused is consumed first.
- Author: Shreyash (webdevcaptain)
- License: MIT
Not affiliated with or endorsed by Anthropic, OpenAI, or CLIProxyAPI. Check each provider's terms before routing subscription credentials through a proxy.
- Claude and Codex pools are ranked independently. Requests spanning multiple providers are left to CLIProxyAPI.
- Rank: earliest weekly reset first. Ties are ordered by credential ID.
- Skip: accounts whose five-hour, weekly, or model-specific (Sonnet/Opus) quota is exhausted.
- Existing credential
prioritytiers still take precedence. - Only candidates offered by CLIProxyAPI are considered, so its model eligibility, cooldowns, and retries still apply.
- Codex: the earliest reset among its weekly or monthly windows is used for ranking.
Example: account A (weekly reset in 20 hours) is chosen over account B (weekly reset in 4 days), even if B's five-hour window resets in 2 hours. If A is exhausted, B is chosen.
- One background worker. Request routing uses cached data and makes no network calls.
- Refreshes every
poll_interval(default 5 minutes) and shortly after any reported reset. Checks for credential changes every 30 seconds. - Read-only
GETrequests to:https://api.anthropic.com/api/oauth/usagehttps://chatgpt.com/backend-api/wham/usage
- No model requests, token refreshes, or credential writes.
The plugin hands the request back to CLIProxyAPI's configured routing strategy when it has no trustworthy data:
- before the first successful quota refresh
- after a 401 or 403 from a quota endpoint
- when cached quota is older than
max_age(other refresh errors keep the last good data until then) - when no eligible account has known quota
Ordering is not guaranteed in these cases. Quota can also change between refreshes.
- CLIProxyAPI v7.3.15 (plugin ABI 1, schema 6). Other versions are untested.
- Linux amd64 or arm64 (glibc 2.34 or newer), macOS 12 or newer on Apple silicon or Intel, or Windows amd64.
- The Intel macOS build uses a patched Go toolchain. See Intel Macs.
- Direct network access to both quota endpoints. Credentials with
proxy_urlorbase_urlare skipped. Quota polling ignores CLIProxyAPI'sproxy-urland proxy environment variables.
-
Download
quota-reset-router_<version>_<os>_<arch>.zipfor your platform from the latest release and check it againstchecksums.txt. Optionally verify its build provenance:gh attestation verify <zip> --repo WebDevCaptain/quota-reset-router. -
Extract
quota-reset-router.so(Linux),quota-reset-router.dylib(macOS), orquota-reset-router.dll(Windows) into CLIProxyAPI's plugin directory (plugins.dir) as a regular file. Symlinks are not loaded. -
Merge into
config.yaml:plugins: enabled: true dir: plugins configs: quota-reset-router: enabled: true priority: 10 mode: shadow
-
Restart CLIProxyAPI.
-
Review the status endpoint. When the proposed choices are correct, switch
modetoactive.
priority orders plugins, not accounts. CLIProxyAPI consults only the highest-priority scheduler plugin.
| Key | Default | Allowed | Purpose |
|---|---|---|---|
mode |
shadow |
shadow, active |
shadow records proposed choices only. active routes requests. |
poll_interval |
5m |
1m to 1h |
Quota refresh interval. |
max_age |
10m |
poll_interval to 1h |
Maximum age of cached quota. |
request_timeout |
10s |
1s to 30s |
Timeout per quota request. |
Change settings without a restart:
PATCH /v0/management/plugins/quota-reset-router/config
{"mode": "active"}
GET /v0/management/plugins/quota-reset-router/status
Requires Management API authentication. Returns the version, mode, selection policy, per-account quota snapshots, refresh errors, the last decision, and routing counters. Credential IDs are included (often file names containing email addresses). OAuth tokens are not.
-
Disable without a restart. CLIProxyAPI's configured routing resumes after it reloads the configuration:
PATCH /v0/management/plugins/quota-reset-router/enabled {"enabled": false} -
Upgrade: stop CLIProxyAPI, replace the plugin file, start CLIProxyAPI.
- Native plugins run inside the CLIProxyAPI process with access to its credentials and traffic. Expected errors fall back to CLIProxyAPI routing; a native crash can still affect the proxy.
- When the plugin selects an account, CLIProxyAPI's built-in strategy, including session affinity, is not used for that request.
- CLIProxyAPIHome dispatch does not consult plugin schedulers.
- The quota endpoints are not stable public APIs. Unrecognized responses trigger fallback.
Build and test targets take TARGET: linux_amd64 (default), linux_arm64, darwin_amd64, darwin_arm64, or windows_amd64.
- Linux and Windows builds,
linux-test,native-test, and Linuxhost-testrun in a pinned Docker image. - macOS builds need a macOS host with Go 1.21+ and the Xcode Command Line Tools. Go 1.26.8 is downloaded automatically.
darwin_amd64first builds the patched toolchain intodist/_go-tls(about a minute, once per checkout), then uses it formake testandmake build.make testneeds Go 1.26+ and a C toolchain.
make test # gofmt, go vet, and unit tests with the race detector
make linux-test # same, in the pinned Linux container
make build # writes dist/<target>/quota-reset-router.<so|dylib|dll>
make native-test # Linux only: loads the library through the plugin C ABI
make host-test # Linux, or macOS CI: runs the official CLIProxyAPI release with the library
make zip # writes dist/release/quota-reset-router_<version>_<target>.zip
make load-test # loads the zip into the official CLIProxyAPI; TARGET must match this machinehost-testandload-testdownload the official CLIProxyAPI v7.3.15 release and verify its checksum.native-testandhost-testrun with networking disabled, local TLS fixtures, and synthetic credentials. On macOS,host-testinstead needs the quota hosts pinned to 127.0.0.1 and the fixture certificate trusted in the System keychain, which CI sets up;SOAK_SECONDSadds a soak under GC pressure.load-teststarts CLIProxyAPI without credentials, so the plugin makes no network requests.- CI builds every target and loads each zip into the official CLIProxyAPI on its own platform.
make cleanremoves build output.
Stock Go on macOS amd64 keeps each thread's current goroutine in one fixed thread-local slot, slot 6, which Apple reserves for Go. Every Go runtime in a process uses that slot. CLIProxyAPI is itself a Go program, so a plugin built with stock Go runs on CLIProxyAPI's goroutines and heap, and CLIProxyAPI v7.3.15 crashes at startup (fatal error: addspecial on invalid pointer; CLIProxyAPI's own Go scheduler example fails with unknown caller pc). Linux, Windows, and Apple silicon give each runtime its own slot, so they are unaffected.
The darwin_amd64 library is built with Go 1.26.8 plus scripts/go-tls-slot.patch. The patch changes two constants so the plugin's runtime uses slot 11, which Apple also reserves and leaves unused. CLIProxyAPI keeps slot 6. The toolchain is built from the checksum-verified upstream source, and the build fails if any goroutine access in the library still uses slot 6.
The CLIProxyAPI plugin store installs from this repository's latest published GitHub release. Each release contains checksums.txt and one quota-reset-router_<version>_<os>_<arch>.zip per target, holding the plugin, LICENSE, and THIRD_PARTY_NOTICES.md.
- Set
pluginVersioninconfig.go, for example0.2.0, and merge tomain. - Push the tag
v<version>. CI builds and tests every target, attests build provenance, and creates a draft release with the assets. - Review the draft and publish it.
make release-assets builds the same set locally on a macOS host with Docker.
Binary releases link the CLIProxyAPI plugin SDK (MIT), gopkg.in/yaml.v3 (MIT and Apache-2.0), and the Go standard library (BSD-3-Clause; patched on darwin_amd64). Windows builds also statically link parts of the MinGW-w64 runtime. See THIRD_PARTY_NOTICES.md.