One endpoint rotates across several subscriptions
Underclass accepts OpenAI-style Responses and Chat Completions requests, then sends each one through a pool of ChatGPT/Codex or GitHub Copilot accounts. A quota error cools an account until its reset window, and the account returns to rotation automatically. When every eligible account is cooling, the proxy returns HTTP 429 with the earliest reset time. It does not leave the caller waiting on an empty pool.
Sticky bindings keep a session on one subscription for 24 hours, which preserves upstream prompt-cache behavior across turns. The selection policy prefers accounts with fewer requests in flight and filters them by the model catalog. State survives a restart in SQLite. For a developer with several existing subscriptions, that is a specific solution to a real nuisance: client tools see one address while Underclass tracks which account can still accept work.
This design also concentrates access. The same database holds account credentials, sticky bindings, model entries, and minted keys. Underclass says it does not log authorization headers, refresh tokens, or prompt bodies, while account labels and usage do appear in its diagnostics and UI. The burden sits with the operator to protect pool.db, the admin token, backups, and the host itself.
What happened when we ran it
Our sandbox installed commit 3e35c3b in 16 seconds and pulled 271 Rust packages. The build succeeded in 177 seconds, and cargo test completed in 85 seconds. All 178 tests passed with 0 failures. The container had 3 CPUs, 12 GB of RAM, no secrets, and no elevated privileges. This was a clean result for the repository mechanics we could exercise.
The checkout was only 0.5 MB, with 66 files and about 8,315 lines of source. It has a tests directory and 1 CI workflow. There is no Dockerfile. The small tree makes the proxy easier to inspect than a multi-service gateway, although its 271-package dependency graph and 177-second build still deserve normal supply-chain review and pinned artifacts.
We did not connect a paid account, spend quota, or send a live request to either provider. The passing 178-test suite covers the local test harness at that commit. It does not prove that an OAuth flow, quota response, model catalog, or provider policy will remain unchanged. Those surfaces belong to services outside this repository and need a live acceptance test with accounts you are authorized to use.
Two bearer secrets protect different surfaces
The quick start asks for a proxy key for /v1/* clients and a separate UI token for administration. Each subscription then goes through its provider's device flow. By default the server binds to 127.0.0.1:8080, and the NixOS module keeps the firewall closed. Those are sensible defaults for a service holding several OAuth tokens. Binding it beyond localhost changes the risk sharply.
The CLI can write an Underclass provider and credential entry into OpenCode's global configuration. It makes backups, supports a dry run, and can remove its changes. Nix users get a package, app, development shell, and NixOS module. Everyone else can run it through Cargo. With no Dockerfile in the 66-file repository, teams standardized on containers must create and maintain that packaging themselves.
Streaming errors never move to a second account
Failover ends once the first response byte has been sent. If the chosen upstream breaks later, Underclass passes the error to the caller because silently replaying part of a generated answer could duplicate or corrupt output. That is the right trade for correctness, but it means account pooling cannot make a long streaming request immune to provider failures.
Automatic use of banked Codex resets is enabled by default. When all eligible Codex accounts are unavailable, Underclass may spend one reset on the account facing the longest wait. Operators who treat those credits as manually controlled inventory should set UNDERCLASS_AUTO_CODEX_RESETS=false. Token totals also exclude attempts whose upstream counts are missing, so the dashboard describes those totals as lower bounds rather than complete billing data.
OpenCode v2 compatibility still needs a local check
Open issue 3 reports that the generated OpenCode configuration sent Chat Completions fields to the Codex Responses path. The maintainer replied on September 23, 2026 that the integration had been created for OpenCode v1 and that v2 had not yet been tried. The issue remains open. A README quick start can be accurate for one client generation and still fail for the next, so run underclass connect --dry-run and make a real request before changing team configs.
The web UI and terminal monitor are useful once the proxy is live. They show account state, a 60-minute attempt chart, current-month token accounting, sticky sessions, and Codex quota windows. The local monitor socket avoids placing an admin token in a terminal command, but its snapshot includes account labels and usage. Local users allowed to read that socket receive operational metadata.
Version 0.1.0 has no tagged release
The repository was pushed on October 7, 2026, the day of our review, and GitHub showed 177 stars. Its 9 open issues and pull requests split into 2 issues and 7 pull requests, with most pull requests opened by dependency automation. Current activity is clear. A broad contributor community is not.
GitHub returned no latest release, the repository had 0 tags, and Cargo.toml still declared version 0.1.0. That early state matters more here because the tool stores OAuth credentials and sits between coding clients and paid services. The 178 passing tests are a strong start, especially beside the explicit routing ADRs, yet teams should pin a commit and rehearse database backup and credential rejection before depending on it.
Underclass is easiest to recommend to one technical operator who understands every account in the pool. Our 85-second test run found no failing test at commit 3e35c3b. The unresolved OpenCode v2 report and missing release history still make a staged deployment the sensible choice: localhost first, one disposable client configuration, then additional subscriptions only after routing, cooldowns, and reset behavior match your expectations.

