Docs
Qwen Code
Qwen Code keeps its endpoints in one file. Declare Kunavo once under modelProviders, set selectedType to openai, and the /model picker switches between Claude, GPT and Gemini on a single key.
Qwen Code reads its endpoints from modelProviders in ~/.qwen/settings.json — one entry with a baseUrl and an envKey puts Claude, GPT and Gemini in its /model picker.
{
"modelProviders": {
"openai": [
{
"id": "claude-sonnet-5",
"name": "Claude Sonnet 5 (Kunavo)",
"baseUrl": "https://api.kunavo.com/v1",
"description": "Kunavo, OpenAI-compatible",
"envKey": "KUNAVO_API_KEY"
}
]
},
"env": {
"KUNAVO_API_KEY": "sk-kn-..."
},
"security": {
"auth": {
"selectedType": "openai"
}
},
"model": {
"name": "claude-sonnet-5"
}
}/v1. The model providers reference settles it in one sentence: when pointing an entry at a hosted OpenAI-compatible gateway, set baseUrl to the API's “/v1 root” rather than the full /v1/chat/completions path, “the SDK appends the request path itself”. Every OPENAI_BASE_URL example in the authentication page ends the same way. A base URL with the route already on it produces a 404, not an authentication error.realtimeOnly route's host be a DashScope endpoint, so that feature stays on its own key wherever you point the chat model./auth list.Step by step
- Create a key at
/app/keysand copy it — it is shown once. - Open
~/.qwen/settings.json(create it if it does not exist) and merge in the four blocks above. The docs recommend declaringmodelProvidersin the user-scope file “to avoid merge conflicts between project and user settings”. - Put the key somewhere better than
envif you can. Qwen Code reads it fromprocess.env[envKey], and the docs rank the sources highest to lowest: a shellexport, then a.envfile, then theenvblock insettings.json— which they flag as plain-text storage. Theenvblock above is the smallest thing that runs, not the best thing to keep. - Run
qwen. Withsecurity.auth.selectedTypeset toopenaiandmodel.namematching anidyou declared, no interactive/authstep is needed — the docs say so in as many words after the one-file example. - Give it a task that reads and edits a file, not a greeting. Qwen Code is an agent: tool calling and streaming are what a first run should exercise, and they are what would fail first against an endpoint that only half fits.
- Add more entries under
modelProviders.openaito switch models at runtime with/model. Those edits hot-reload in a running session;providerProtocolis read once at startup and needs a restart.
Checked against Qwen Code's authentication page, Option 4: API Key (flexible) on September 21, 2026. Third-party settings move; if a field name here no longer matches what you see, that page is the authority, not this one.
Verify before you debug the client
One request settles whether a failure is the endpoint, the key, or the configuration file. If this returns JSON, the same base URL and key work in Qwen Code.
# Settles whether a failure is the endpoint, the key, or the client.
curl -sS https://api.kunavo.com/v1/models \
-H "Authorization: Bearer sk-kn-..."Which model id to put in the field
Every text model is reachable as a model id — the live list is GET /v1/models, and the catalog with prices is on the models page. Rates are USD per 1M tokens, input / output.
| Model id | Kunavo in / out | Where it fits in Qwen Code |
|---|---|---|
claude-sonnet-5 | $2.00 / $10.00 | the default working model — set it as model.name |
claude-opus-5 | $2.00 / $10.00 | a plan that would be expensive to get wrong |
claude-haiku-4-5 | $0.40 / $2.00 | cheap turns: triage, summaries, the loop that runs all day |
gpt-5-6-sol | $2.00 / $12.00 | a second opinion from another family, same key and same baseUrl |
gemini-3-1-pro | $0.70 / $4.20 | long-context reading, still through the openai protocol key |
Three things the docs settle that people guess wrong
These come from the authentication page and the model providers reference linked above, and each one costs real debugging time when it is assumed instead of read.
- A
modelProvidersentry outranks the CLI flags. The documented order, highest first, is: overrides made through/authin the running session, then the selected model provider'senvKey, then CLI arguments such as--openai-api-key, then environment variables, thensecurity.auth.apiKeyin settings. Most people expect the flag to win. It does not — which is why--openai-base-urlcan appear to be ignored. security.auth.apiKeyandsecurity.auth.baseUrlare deprecated. The reference says so and recommends migrating tomodelProviders. If an older tutorial has you editing those two keys, it is editing the route that is on its way out.wireApipicks the request format, and nothing detects a mismatch. Omitting it means Chat Completions, which is what the block above uses. Setting"wireApi": "responses"requires a genuinely Responses-compatible endpoint, and the docs state plainly that no endpoint detection and no automatic fallback occur when a request fails. Kunavo answers/v1/responsesas well as/v1/chat/completions, but this page has tested neither pairing, so start on the default.
If you came here looking for the free tier
Much of what is still written about Qwen Code describes a Qwen OAuth login with a free daily allowance. That option is gone: the documentation records its free tier as discontinued on April 15, 2026, and says Qwen OAuth is no longer a selectable entry in the /auth dialog. The three it lists now are Alibaba ModelStudio — with Coding Plan, Token Plan and Standard API Key in its sub-menu — Third-party Providers, and Custom Provider, described as connecting “a local server, proxy, or unsupported provider”. Kunavo is the third of those. Note also that the ModelStudio sub-menu items are not three ways to pay one bill: each has its own host and its own key, and a Coding Plan key on a Token Plan host will not work.
FAQ
How do I point Qwen Code at a custom API endpoint?
Declare the endpoint in ~/.qwen/settings.json under modelProviders. Use the key "openai" for any OpenAI-compatible host, give the model entry an id, a baseUrl and an envKey naming the environment variable that holds your API key, then set security.auth.selectedType to "openai" and model.name to that id. Run qwen and it starts on that route with no interactive /auth step. The equivalent environment-variable route is OPENAI_API_KEY, OPENAI_BASE_URL and OPENAI_MODEL, but the settings file is what the documentation recommends because it survives shells and supports several endpoints at once.
Does the Qwen Code baseUrl need /v1 on the end?
Yes, for an OpenAI-compatible endpoint. Qwen Code's model providers reference says to set baseUrl to the API's /v1 root, for example https://gateway.example.com/v1, rather than the full /v1/chat/completions path, because the SDK appends the request path itself. For Kunavo that makes the value https://api.kunavo.com/v1. Leaving the route on the end produces a 404 rather than an authentication failure, which is the usual way this shows up.
Is the free Qwen Code tier still available?
No. Qwen Code's own documentation records the Qwen OAuth free tier as discontinued on April 15, 2026, and Qwen OAuth is no longer a selectable entry in the /auth dialog. The documentation also notes that Qwen OAuth models are hard-coded and cannot be overridden through modelProviders, so the old route cannot simply be repointed somewhere else. What remains is Alibaba ModelStudio, a built-in third-party provider, or a custom endpoint you configure yourself.
Can Qwen Code run Claude or GPT models instead of Qwen?
Yes. Qwen Code's protocol table lists the openai provider key as accepting any OpenAI-compatible endpoint, and the model id in a modelProviders entry is passed straight through to the baseUrl you configured, so it is resolved at that endpoint rather than inside the client. A Claude or GPT id therefore works as long as the endpoint serves it. Kunavo serves Claude, GPT and Gemini ids over its OpenAI-compatible surface, and has published this configuration from the vendor's documentation rather than from a test run.
Why is Qwen Code ignoring --openai-base-url?
Because a modelProviders entry outranks it. The documented credential precedence puts overrides entered through /auth in the running session first, the selected model provider's baseUrl and envKey second, and CLI arguments only third, above environment variables and settings. If a provider entry is selected, its baseUrl wins over the flag. Either edit that entry — modelProviders edits hot-reload in a running session — or remove it if you meant the flag to take effect.