Model or dataset
jasonxu114514/opencode2api avatar
jasonxu114514/opencode2api

opencode2api: a Go gateway that puts OpenAI and Anthropic endpoints in front of OpenCode Zen

A Go-based OpenCode Zen / Zen Go API proxy with OpenAI & Anthropic API compatibility, key/proxy pooling, automatic routing, and WebUI.

324 stars68 forksGoLicense varies

At a glance

What is it?
opencode2api is a Go proxy that speaks Chat Completions, Responses and Anthropic Messages while pooling Zen and Go upstream keys. It is a single binary with an embedded WebUI, and the README leaves the licence unstated.
Who is it for?
Adopt opencode2api if you already hold Zen or Go credentials and want OpenAI or Anthropic shaped endpoints on one local port, with pooling and a management UI you can reach at http://localhost:8081. Do not adopt it if you need a stated licence before shipping, or if you expect the gateway to supply credentials for you: the README treats Zen and Go keys as inputs, and anonymous mode only works if the public credential is accepted.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
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 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap opencode2api fills between OpenCode Zen keys and OpenAI shaped clients

OpenCode Zen and Zen Go speak their own upstream protocols. Most client software, however, is written against one of three wire formats: OpenAI Chat Completions, OpenAI Responses, or Anthropic Messages. Without a translator, a tool built for one of those formats cannot talk to a Zen credential at all. opencode2api is that translator. The README describes it as a Go gateway that exposes Chat Completions, Responses and Anthropic Messages endpoints, translates between their native protocols, and manages upstream keys and proxies. The intended user is someone who holds Zen or Go credentials and wants existing clients to keep working unchanged. It is not a client library and not a hosted service. You run the binary, point your client at http://localhost:8080, and the gateway handles the protocol conversion and key selection upstream.

How the gateway routes requests, pools keys and translates protocols

The data flow is one hop. A client calls one of the three inference paths with a local key in the Authorization or x-api-key header. The gateway validates that key against the server_keys list, picks an upstream credential from the Zen or Go pool, rewrites the request into the upstream protocol, and streams the answer back in the shape the caller expects. The README states that server_keys authenticate clients to this gateway and are separate from zen_keys and go_keys, and are never used as upstream credentials. That separation matters: rotating a client key does not touch your upstream accounts. Routing is not a simple round robin. The README lists separate Zen and Go key pools, configurable tier preference, retries, and session affinity. Session affinity is the interesting part, because it implies the gateway tries to keep a conversation on the same upstream key rather than scattering turns across the pool. What the README does not document is the affinity window or how it behaves when the pinned key fails. Anonymous mode is a separate path: setting anonymous to true with empty upstream key arrays lets the gateway use the OpenCode public credential, which the README describes as optional anonymous Zen access. File content is passed through only where the target protocol can represent it, so a request carrying an attachment may lose that attachment depending on which endpoint you called. API request bodies are capped at 32 MiB.

Building opencode2api and sending a first request

The README gives two install routes: download a binary from GitHub Releases, or build from source with Go 1.24 or newer. The build route is short.

bash
git clone https://github.com/jasonxu114514/opencode2api.git
cd opencode2api
cp config.example.json config.json
go build -o opencode2api ./cmd/opencode2api

Before starting, the README asks for three edits in config.json: replace server_keys with your own local API key, supply Zen or Go keys (or set anonymous to true and empty both upstream key arrays), and replace webui.password. The example enables the WebUI with username admin. Then start the service.

bash
./opencode2api -config config.json

The example listens on 127.0.0.1:8080 for the API and 0.0.0.0:8081 for the WebUI. Note that 0.0.0.0 is not localhost; the README warns to restrict management access and use an HTTPS reverse proxy when reaching it over a network. Discover a model before calling anything, because the model ID you need comes from this response.

bash
curl http://localhost:8080/v1/models \
  -H "Authorization: Bearer YOUR_LOCAL_API_KEY"

Take an ID from that list and send it to the endpoint matching your client.

bash
curl http://localhost:8080/v1/chat/completions \
  -H "Authorization: Bearer YOUR_LOCAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"MODEL_ID","messages":[{"role":"user","content":"Hello"}]}'

Anthropic clients use a different header set: x-api-key for the local key and anthropic-version: 2023-06-01. Streaming works by adding "stream": true to the body and using curl -N. Every response carries an x-request-id for correlation. The executable includes the WebUI, and running the service requires no Node.js runtime or database, so there is no second process to supervise.

Where opencode2api is the wrong tool, and what the README does not answer

The first limitation is credentials. opencode2api does not grant access to Zen or Go. It pools keys you already have, or falls back to the OpenCode public credential when anonymous is true. If anonymous access is refused upstream, or if your account is rate limited, the gateway has nothing to route with, and the README does not describe a fallback beyond the pools you configured. The second limitation is the licence. The repository metadata does not state one, and no licence file appears among the top-level entries listed for the repository. For an internal experiment that is tolerable. For anything you distribute or run commercially, an unstated licence is a blocker you have to resolve with the author first. The third is operational exposure. The example binds the WebUI to 0.0.0.0:8081 with username admin and a password you are told to replace. Configuration editing, a Playground, diagnostics, token statistics and live logs all sit behind that login. Anyone who reaches that port and guesses the password gets your upstream keys. The README does not document rollback when a configuration hot reload is rejected, only that validation happens before new requests switch to a replacement gateway. Finally, the configuration directory must be writable for password migration, configuration saves and model caches, which rules out running the binary from a strictly read-only mount without a separate state volume.

Docker deployment and how it differs from a LiteLLM style proxy

The published image is ghcr.io/jasonxu114514/opencode2api, and compose.yaml runs it with read_only: true, no-new-privileges:true, a writable named volume opencode2api-state at /var/lib/opencode2api, and a tmpfs on /tmp. The container runs as an unprivileged user. One behaviour catches people out: compose imports the host configuration into the state volume only on first startup, so later edits must go through the WebUI or be copied in explicitly.

bash
docker compose cp config.json opencode2api:/var/lib/opencode2api/config.json
docker compose restart

Host port variables are OPENCODE2API_PORT (default 8080) and OPENCODE2API_WEBUI_PORT (default 8081). Changing host ports does not change container listeners, and if you change the internal API port you must also update the port mapping and the image health check, which probes port 8080. A proxyfile used in Docker must exist inside the container at the configured path. The honest comparison is with a general purpose LLM proxy such as LiteLLM. LiteLLM targets many providers and normalises them behind one OpenAI compatible surface. opencode2api targets one upstream family, OpenCode Zen and Zen Go, and puts its effort into that family's specifics: separate Zen and Go pools, tier preference, session affinity, anonymous access, and a bundled management UI. If you need five providers behind one endpoint, opencode2api is the wrong shape. If you need Zen and Go handled carefully with a single binary and no database, the narrower scope is the point.

Maintenance, upgrade cost and the missing licence

The repository is not archived, and the last push was on 2026-09-14, the same day as the v1.3.0 release. That date is three days before this writing, and the preceding releases v1.2.4 and v1.2.3 landed on 2026-09-05 and 2026-09-03, so the release cadence is dense. Dense releases also mean upgrade cost. Configuration is hot reloaded with validation before new requests switch over, which lowers the risk of a bad config, but the README does not describe a downgrade path, and the Docker image defaults to the latest tag. Pinning OPENCODE2API_VERSION to a release tag is the only version control the README offers for containers. On licence: nothing in the repository metadata states a licence. Without one, the default position is that the author retains all rights, and you should not assume you may redistribute the binary or the image. That is a factual gap, not a legal opinion, and it is the first thing to clear up before this gateway sits in front of production traffic.

Editorial conclusion

Adopt opencode2api if you already hold Zen or Go credentials and want OpenAI or Anthropic shaped endpoints on one local port, with pooling and a management UI you can reach at http://localhost:8081. Do not adopt it if you need a stated licence before shipping, or if you expect the gateway to supply credentials for you: the README treats Zen and Go keys as inputs, and anonymous mode only works if the public credential is accepted. Verify three things first: that the repository carries a licence file, that your Zen or Go keys authenticate against a real request, and that the WebUI is bound to localhost or behind an HTTPS reverse proxy before anyone else can reach port 8081.

Frequently asked questions

How do I get my OpenCode API key?

opencode2api does not issue Zen or Go credentials; you supply them. The README says to put them in the zen_keys or go_keys arrays in config.json, or to set anonymous to true with both arrays empty so the gateway uses the OpenCode public credential.

Can I use Open API for free with opencode2api?

The README describes optional anonymous Zen access using the OpenCode public credential, enabled by setting anonymous to true and leaving both upstream key arrays empty. Whether that access is actually granted is determined upstream by OpenCode, not by this gateway, and the README does not promise free usage.

Is there a free API for OpenCode Zen?

The only free-adjacent path documented is anonymous mode, which uses the OpenCode public credential instead of your own Zen keys. The README does not state any pricing, quota or guarantee attached to that credential.

How much does an OpenCode Go subscription cost?

The README does not mention pricing for Zen or Go. It only describes how to supply go_keys to the gateway and how the Go pool is selected alongside the Zen pool.

Official sources

  1. Issues
  2. jasonxu114514/opencode2api on GitHub
  3. README
  4. Releases
Community notes

Community notes