DEV Community

APIClaw
APIClaw

Posted on

Pointing VS Code Continue and Windsurf at a custom OpenAI-compatible base URL

Pointing an editor at a custom OpenAI-compatible endpoint is documented as a settings-screen operation. In practice the settings screen is the part that fails silently, and the extension's config file is the part that decides what actually gets sent. These are the steps that hold up on VS Code and on Windsurf, plus the four failures I keep seeing in other people's bug reports.

Prove the endpoint before you touch the editor

Every "the extension won't connect" report I have read this year was really an endpoint problem wearing an editor costume. Test the endpoint from a shell first:

curl -s https://apiclaw.biz/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"YOUR_MODEL_ID","messages":[{"role":"user","content":"say ok"}],"max_tokens":16}'
Enter fullscreen mode Exit fullscreen mode

Three outcomes tell you everything. 401 means the key did not arrive. 404 almost always means the path is doubled — a base URL of .../v1 plus a client that appends /v1/chat/completions gives you /v1/v1/chat/completions. A 400 naming the model means you typed a shortened model id instead of the full one your account can use; copy it, don't retype it.

If that curl returns a completion, the remaining problem is local configuration and you can stop suspecting the network.

Continue on VS Code: the whole config

Continue reads ~/.continue/config.yaml (%USERPROFILE%\.continue\config.yaml on Windows). The minimal working model block looks like this:

name: APIClaw
version: 1.0.0
schema: v1
models:
  - name: APIClaw
    provider: openai
    model: YOUR_MODEL_ID
    apiBase: https://apiclaw.biz/v1
    apiKey: YOUR_API_KEY
    capabilities:
      - tool_use
      - image_input
    roles:
      - chat
      - edit
      - apply
Enter fullscreen mode Exit fullscreen mode

Four details in those twelve lines are the ones that break:

  1. apiBase, not baseUrl. A wrong key name is not an error. Continue ignores it, falls back to api.openai.com, and you get a 401 from a host you never configured.
  2. capabilities overrides autodetection. Continue guesses capability from model names it recognises. An unfamiliar id gets no tool_use, and agent mode then answers with prose and never calls a tool — it looks like a broken agent when it is a broken declaration.
  3. roles decides where the model appears. Missing apply and the Edit pane will appear to do nothing. Missing edit and you can only chat.
  4. Environment variables do not reach the extension host. Continue's IDE extensions cannot read your shell env, so exporting the key in .zshrc accomplishes nothing. Put APICLAW_API_KEY=... in ~/.continue/.env and reference it through Continue's secret lookup syntax in place of the literal apiKey. Then restart the IDE — reloading the window is not enough, the extension host caches the config.

Windsurf is a different problem

Windsurf was renamed Devin Desktop in June 2026, and Cascade was removed in September 2026, leaving Devin Local as the only built-in agent. Devin Desktop has no setting for a custom OpenAI-compatible base URL. There is no field to fill in.

So the gateway is used through an extension, not through the app. Open the Extensions panel — it uses the Open VSX registry, which matters: Roo Code is there, Cline may or may not be depending on your build. Install an OpenAI-compatible coding extension, choose the OpenAI Compatible provider, paste the base URL, the key, and a full model id. Only that extension talks to the gateway. The built-in agent and autocomplete stay on the models the application ships with, which is a feature if you like the app's own completions and a wart if you were hoping to consolidate everything.

The Windsurf path is written up in the APIClaw Windsurf notes, and the VS Code path — including the Copilot Chat option — is in the VS Code guide.

Copilot Chat as a second front end

If you are already inside VS Code, the built-in Copilot Chat can take a custom endpoint: Manage Language Models from the model picker, then the Custom Endpoint provider. The older "OpenAI Compatible" provider is deprecated, so do not start there. The URL must include the path, not just the host — https://apiclaw.biz/v1/chat/completions, or /v1/responses if you set API type to Responses. Bring-your-own-key is enabled by default on Copilot Business and Enterprise, but an admin can switch it off by policy, and it covers chat and agent mode only; inline completions and embeddings stay on the Copilot plan.

The failure table

Symptom Cause Fix
404 on every request path doubled base URL ends at /v1, client appends the rest
401 immediately key never loaded .env file, secret reference, IDE restart
400 "model not found" shortened id copy the full id from the model hub
Agent replies, edits nothing no tool_use declare capabilities
Edit pane inert no apply role add it to roles

Why the indirection is worth it

Because these editors send whatever model id you typed, you can route by role: a mid-weight model for edit and tab-adjacent work, a frontier model when the agent is planning. That is only possible when the models arrive through one endpoint. APIClaw is a flat-rate gateway that answers the OpenAI chat completions schema at https://apiclaw.biz/v1, and it also speaks Anthropic Messages for tools that expect that shape, so a single key covers both generations of tooling — the argument for one key across every model rather than one subscription per editor. The request is the billing unit, heavier models count more against the daily pool, and there is no per-token line on the invoice to reverse-engineer afterwards.

Start with the curl. Nine times out of ten, that is the whole bug.

Top comments (0)