WorkBuddy2API: An OpenAI-Compatible Gateway for CodeBuddy Accounts
WorkBuddy的 OpenAI 兼容反向代理,支持 OAuth 登录、多账号轮转、工具调用与流式响应。
At a glance
- What is it?
- WorkBuddy2API is a self-hosted Go reverse proxy that turns one or more CodeBuddy accounts into a single OpenAI-compatible endpoint, with OAuth device login, account pool rotation, circuit breaking and session stickiness. It is built for personal multi-account use, not for resale or shared public endpoints.
- Who is it for?
- Adopt it if you already hold one or more CodeBuddy accounts you are authorised to use and want an OpenAI-shaped local endpoint without rewriting your client. Skip it if you need a supported vendor API, a prebuilt binary, or a shared multi-tenant service: the repository ships no releases and the README restricts use to personal, private environments.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What WorkBuddy2API actually solves
CodeBuddy does not publish an OpenAI-shaped open API. WorkBuddy2API sits in front of it and exposes a single /v1/chat/completions surface, so an SDK or front end already written against OpenAI can point at a different base URL and keep working. The README describes the target audience plainly: individuals holding multiple CodeBuddy accounts who want them shared behind one endpoint, with automatic failover when one account breaks, cooling and circuit breaking to stop a cascade, and session stickiness so multi-turn context does not jump between accounts mid-conversation.
The project is explicit that it is an unofficial gateway. The README restricts use to accounts you are authorised to operate, on a local machine or private environment, and states the author accepts no responsibility for account bans or terms violations. That boundary matters more than any feature list: this is a personal tool that happens to speak a standard protocol, not a hosted service.
Account pool selection: four weighted factors and a Top-5 shortlist
The interesting engineering is in how one account gets picked per request. The README describes a weighted score built from four inputs: credits ratio (weighted x10), idle compensation, success rate (x3), and the share of credits expiring soon (x8, within the pool.expiring_soon window, default 7 days). Accounts are sorted by weight, the top five form a shortlist, and the final pick is a weighted draw inside that shortlist. Equal-weight candidates are shuffled first to avoid a thundering herd, and an LRU fallback covers the full candidate set.
Two mechanisms sit on top. A skip rule drops any account selected within the last 100ms, which stops several idle accounts from being hammered at once. An in-flight lease (pool.max_in_flight) caps concurrent requests per account, and a saturated account simply leaves the candidate set. There is also a cost ledger: each successful request records usage.credit against a (account, model) pair to derive a per-thousand-token price, smoothed by EMA and invalidated after six hours without updates. Cheap or free accounts get preferred. That last one is the most opinionated part of the design, and it means selection quality depends on the upstream reporting usage consistently.
Cooling, breaking and model-scoped rate limits
Failures are classified rather than retried blindly. A 429 triggers a soft cooldown starting at 600s with exponential backoff, capped by soft_rate_max. A 404 gets a fixed shallow cooldown. A 402 or exhausted balance gets a hard cooldown until 04:00 the next day. Consecutive failures trip a breaker after breaker_threshold, with exponential backoff capped at 6h.
The notable case is error 6004, which means the model quota is exhausted rather than the account. WorkBuddy2API cools only the model that triggered it, so switching to a different model works immediately, and /status exposes a rate_limited_models ledger. Pool state (credits, cooldowns, breaker, counters) is written atomically to state.json and can optionally be mirrored to Upstash Redis, with preferential recovery after a restart. Anyone running this should treat state.json as the source of truth when diagnosing why an account is not being selected, and remember that the Redis mirror is optional, not a replacement.
Installing WorkBuddy2API with Docker Compose
Docker Compose is the recommended path, and the image already contains the app user and the tool scripts. Clone the repository, copy the example config, then edit it. The README states that api_key must be set at minimum, because an empty value means no authentication at all.
git clone https://github.com/Sliverkiss/workbuddy2api.git
cd workbuddy2api
cp config.example.json config.jsonWith config.json edited, run the login script to add an account. Repeating it adds further accounts. It performs the OAuth device flow, polls for the token, does a first check-in, writes auths/workbuddy-<uid>.json, and restarts the container. The README notes there is no PKCE here; state is issued by the server.
./login.sh
docker compose up -d --buildThe compose file maps port 7863 and bind-mounts ./auths, ./data and config.json (read-only). If the container user app (uid 10001) cannot write state.json, the compose comments give the fix: chown -R 10001:10001 ./data on the host. After startup, the health endpoint returns a healthy count and a service field that confirms which gateway answered.
curl -s http://localhost:7863/healthz
# {"healthy":2,"total":3,"service":"workbuddy2api"}A first real call is a streaming chat completion. The README's example uses deepseek-v4-flash and forces stream:true on the outbound side regardless, but the client can request either mode.
curl -sN http://localhost:7863/v1/chat/completions \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"hi"}],"stream":true}'The account pool aligns itself with the auths/ directory at container start, so a new credential file is discovered without further configuration. Building from source is also documented: Go 1.22.5 or newer, then go build ./..., go vet ./... and go test ./... for the full suite, with go run ./cmd/server -config config.json to start it.
Where the design gets thin
The repository ships no releases or tags. The README states this outright: the artifact is a source build, produced locally by the multi-stage Dockerfile, and there is no checksum for the output. go.sum constrains Go module dependencies only. If your deployment process expects a signed binary or a pinned image digest, this project does not offer one, and you are accepting that gap.
The compliance position is the other hard limit. The README restricts the gateway to your own authorised accounts in a local or private environment, and forbids sharing, resale or redistribution. Credentials land in auths/ as plaintext JSON, which is why the documentation tells you to protect both that directory and the gateway port. The scheduled tasks (check-in at 09 and 21, activity reporting at 10, cat travel at 09 and 21, token keep-alive at 22, and two event-specific jobs) are convenient but they are automated actions against a third-party account, which is exactly the kind of behaviour platform terms tend to look at. This is the wrong tool for anything commercial, multi-tenant, or exposed to the public internet without an api_key.
How it differs from LiteLLM Proxy
LiteLLM Proxy is the obvious comparison point for anyone wanting an OpenAI-compatible gateway. The difference is in what sits behind it. LiteLLM targets provider APIs with published keys and normalises across many vendors; routing is about cost and availability across officially supported endpoints. WorkBuddy2API targets one upstream, CodeBuddy, reached through an OAuth device flow rather than an API key, and most of its code exists to manage the consequences: credential files on disk, token refresh, cooldowns keyed to upstream error codes like 429, 402 and 6004, and a session header family (X-Conversation-Request-ID as the aggregation key, X-Conversation-ID passthrough, B3 tracing) so that rotation and retries reuse the same conversation key and upstream billing does not fragment.
It also adapts both the CN and Global realms, sharing one pool and routing by account realm or a cn: / global: model prefix, with global.enabled able to lock a deployment to CN only. LiteLLM has no equivalent concept because it does not model a single account-based upstream. If your accounts are official API keys, LiteLLM is the better fit. If they are CodeBuddy logins, LiteLLM has nothing to route to.
Maintenance, licence and upgrade cost
The last push to master was on 2026-09-14, and the repository is not archived. The licence is MIT, which permits commercial use of the code; that is separate from the platform terms question, and the README's own restriction to personal, non-commercial use is a project-level statement rather than a licence term. Nothing here is legal advice, and the two documents should be read together before you deploy anything.
Upgrade cost is low in the ordinary case: pull, rebuild, restart. The friction is in state. Pool state lives in state.json with an optional Redis mirror, and credentials live in auths/ as files named workbuddy-<uid>.json. Both are bind-mounted, so a rebuild does not wipe them, but a schema change in state.json would be the thing to watch after pulling. There are no releases to diff against, so the practical upgrade signal is the commit log, not a changelog.
Editorial conclusion
Adopt it if you already hold one or more CodeBuddy accounts you are authorised to use and want an OpenAI-shaped local endpoint without rewriting your client. Skip it if you need a supported vendor API, a prebuilt binary, or a shared multi-tenant service: the repository ships no releases and the README restricts use to personal, private environments. Verify first that config.json has a non-empty api_key, that ./login.sh writes a credential under auths/, and that /healthz reports a non-zero healthy count before pointing any client at port 7863.
Frequently asked questions
What is WorkBuddy2API and who is it for?
It is a self-hosted OpenAI-compatible reverse proxy that wraps CodeBuddy accounts behind a single /v1/chat/completions endpoint. The README targets individuals with multiple CodeBuddy accounts who want them shared, rotated and failed over automatically.
How do I install WorkBuddy2API?
Clone the repository, copy config.example.json to config.json and set api_key, run ./login.sh to add an account, then start it with docker compose up -d --build. The service listens on port 7863 and /healthz reports the healthy and total account counts.
Does WorkBuddy2API support streaming and tool calling?
Yes. The README states that outbound requests are forced to stream:true, SSE frames are rebuilt against an OpenAI whitelist, and non-streaming responses are aggregated locally. Tool calling and tool_choice normalisation are part of the outbound rewrite pipeline.
What happens when a CodeBuddy account hits a rate limit?
A 429 starts a soft cooldown at 600s with exponential backoff capped by soft_rate_max, while a 402 or exhausted balance triggers a hard cooldown until 04:00 the next day. Error 6004 is handled differently: only the model that triggered it is cooled, so other models remain usable.
Is there a prebuilt release or Docker image for WorkBuddy2API?
No. The README states the repository has no Release or tag, and the artifact is a source build produced locally by the Dockerfile. There is also no checksum for the built output; go.sum only constrains Go module dependencies.
Can I run WorkBuddy2API for multiple users or sell access?
The README restricts it to your own authorised accounts in a local or private environment and forbids sharing, resale or redistribution. Credentials are stored as plaintext JSON under auths/, so the documentation also tells you to protect that directory and the gateway port.
Community notes