Model or dataset
dwgx/WindsurfAPI avatar
dwgx/WindsurfAPI

WindsurfAPI: a zero-dependency reverse proxy that turns Windsurf and Devin models into OpenAI, Anthropic and Gemini APIs

Turn Windsurf / Devin Desktop's 100+ AI models (Claude, GPT, Gemini, DeepSeek, Kimi, GLM, SWE) into OpenAI-, Anthropic- & Gemini-compatible APIs. Zero-dependency self-hosted reverse proxy for Claude Code, Cline & Cursor. 把 Windsurf/Devin 云端 100+ 模型变成三套兼容 API。

3,039 stars634 forksJavaScriptMIT

At a glance

What is it?
WindsurfAPI exposes one HTTP service on port 3003 that speaks three client protocols and forwards to Windsurf's cloud through the bundled Language Server. It suits self-hosters who already hold Windsurf or Devin credentials and want Claude Code, Cline or Cursor pointed at those models.
Who is it for?
Adopt WindsurfAPI if you already have Windsurf or Devin accounts and want Claude Code, Cline or Cursor pointed at those models without rewriting client code, and if you are comfortable running a proxy that depends on a binary the project installs itself. Do not adopt it if you need a vendor-supported integration, cannot run a long-lived local process, or expect the proxy to perform file edits on its own.
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 last received commits 6 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap WindsurfAPI fills between Windsurf accounts and agent clients

Windsurf and Devin Desktop hold a catalogue of models behind their own client. Claude Code, Cline, Cursor and the OpenAI SDKs each expect a different wire protocol. WindsurfAPI sits between the two: a single Node.js process that accepts OpenAI, Anthropic and Gemini shaped requests and translates them into the gRPC calls the Windsurf Language Server understands. The README describes it as turning Windsurf and Devin models into OpenAI, Anthropic and Gemini compatible APIs, with no npm runtime dependencies.

The audience is narrow and specific. You need an existing Windsurf or Devin account, a machine that can run a background process plus a vendor binary, and a reason to keep using agent clients that speak one of the three protocols. If your team already pays for a first-party API key from Anthropic or OpenAI, this project solves a problem you do not have. If you want to try Claude Code against models your Windsurf subscription already covers, it is aimed squarely at you.

How the proxy turns three client protocols into one gRPC path

The request path has four stages. A client sends JSON or SSE to one of the exposed routes: POST /v1/chat/completions, POST /v1/completions, POST /v1/responses, POST /v1/messages, or POST /v1beta/models/*. A protocol translation layer normalises the payload. An account pool picks a credential with round-robin rotation, per-account rate limit isolation, failover and circuit breaking. Finally the request goes over gRPC to the local Language Server, which speaks HTTPS to server.self-serve.windsurf.com. An optional DEVIN_CONNECT path can reach Devin's cloud over plain HTTPS instead.

One detail matters more than the rest. The proxy strips upstream Windsurf identity before returning, so the model answers as itself rather than as a Windsurf product. The README gives the example that the model will say it is Claude Opus 4.6 developed by Anthropic. That is a deliberate design choice, and it means the response you get is not a verbatim passthrough of what the upstream service produced.

The routing layer also has a subtle behaviour worth knowing. On the Cascade transport, once per-account model catalogues come back from GetCascadeModelConfigs, the pool model list shows the union of those catalogues while routing still enforces the selected account's own catalogue. A model visible in the list can therefore fail to route on a given account. The .env.example notes that missing, empty or failed catalogue fetches fail open, and that WINDSURFAPI_IGNORE_CLOUD_FILTER=1 restores the legacy behaviour of exposing the full static catalogue.

Running it with Docker Compose on port 3003

The repository ships a Dockerfile and a docker-compose.yml that pulls ghcr.io/dwgx/windsurf-api:latest. The Compose file keeps a build context so a fork or a pre-release clone can build from source instead. The container sets PORT=3003, DATA_DIR=/data and DEVIN_CONNECT=1, exposes port 3003, and declares a healthcheck that fetches http://127.0.0.1:3003/health every 30 seconds.

bash
docker compose up

After the container starts, the health endpoint is the first thing to check. A passing response means the Node process is up; it does not yet prove the Language Server is reachable. The image installs the Language Server through install-ls.sh, which the Dockerfile copies and runs during setup, and points LS_BINARY_PATH at /opt/windsurf/language_server_linux_x64 with LS_PORT=42100.

Authentication is fail-closed. An empty API_KEY returns 401 even on a loopback bind, and the .env.example is explicit that a local bind is not the same as no proxy. To open chat access without a key you need both WINDSURFAPI_ALLOW_UNAUTHENTICATED=1 and a local bind. A non-local bind additionally requires DASHBOARD_PASSWORD for panel writes. The repository's own entry point is the npm start script:

bash
npm start

That runs node src/index.js, which is also the bin entry windsurfapi. Point Claude Code or Cline at http://127.0.0.1:3003 with your API_KEY and they will use POST /v1/messages instead. The README is clear that the model does not touch files: the agent client executes edit_file locally and only the tool_use block comes back over the wire.

Where the design fights you: identity stripping, account pools and the Language Server dependency

The Language Server is the weakest link. It is a Windsurf binary installed by install-ls.sh, not a library this project controls. If the vendor changes the binary, the gRPC surface, or the cloud endpoint, the proxy breaks until the maintainers ship a fix. The Dockerfile pins LS_BINARY_PATH and LS_PORT, which means a version bump can move both. There is no documented rollback path in the README for a Language Server that installs but does not authenticate.

Identity stripping is a second trade-off. Making the model answer as Anthropic rather than as Windsurf is convenient for clients that probe the model name, but it removes a signal you might want in logs and audits. It also means the proxy is modifying provider output, which is a policy question each operator has to answer for themselves.

The account pool is the third. Round-robin across accounts with per-account rate limits and circuit breaking is a reasonable design, but it assumes you have more than one usable account and that the pool's health signals are accurate. If you have a single account, the failover and isolation machinery buys you nothing, and the union-versus-routing mismatch on model catalogues becomes a source of confusing 4xx errors rather than a resilience feature.

Finally, the README does not document rollback, migration between versions, or what happens to accounts.json and stats.json when the schema changes. DATA_DIR defaults to the repo root on a bare-source install, which the .env.example warns can scatter state files into the checkout.

How it differs from LiteLLM and other multi-protocol gateways

LiteLLM is the obvious comparison. It is a Python proxy that normalises many provider APIs behind an OpenAI compatible surface, with its own config format and provider list. The difference in approach is where the upstream credentials come from. LiteLLM expects you to hold API keys for each provider and routes between them. WindsurfAPI expects you to hold Windsurf or Devin accounts and routes through the vendor's own client binary. That is a fundamentally different trust and cost model: LiteLLM bills you per provider, WindsurfAPI rides an existing subscription.

The second difference is the dependency footprint. LiteLLM is a Python package with a large dependency tree. WindsurfAPI's package.json declares zero npm runtime dependencies, with image codecs vendored under src/vendor, and its only external requirement is Node plus the Windsurf Language Server. For a small self-hosted deployment that is a real operational difference, though it trades a package manager for a vendor binary.

The third difference is protocol coverage. LiteLLM centres on OpenAI compatibility. WindsurfAPI ships OpenAI chat, OpenAI legacy completions, OpenAI Responses, Anthropic messages and Gemini v1beta routes in the same process, which is what lets Claude Code, Cline and Cursor connect without a translation shim.

Maintenance, licence and what upgrading actually costs

The repository is not archived and the last push was on 2026-09-09. Releases are frequent: v3.9.31 landed on 2026-09-04, with v3.9.30 the same day and v3.9.29 on 2026-08-28. The package.json version is 3.9.34, ahead of the most recent listed release tag, which suggests the version field moves between tagged releases. That cadence is the maintenance cost: you are tracking a fast-moving proxy whose upstream is a vendor binary you do not control.

The code is MIT licensed, and the README adds a separate statement from the author asking users who have not starred or followed the repository not to use it commercially, resell it, deploy it on someone else's behalf, run it as a hosted service, or package it as a relay for sale. The README itself notes this paragraph is the author's personal position and that the code body remains MIT. That is a discrepancy worth reading carefully before a commercial deployment; it is not a legal opinion, and if the distinction matters to your organisation, ask a lawyer rather than the README.

Upgrade mechanics are thin. The repository has update.sh and a CHANGELOG.md, but the README does not describe a supported upgrade procedure, a state migration path, or a compatibility guarantee between minor versions. The test scripts in package.json, including test:release and the smoke tests for the native bridge, Devin connect and the LSP capacity matrix, are the closest thing to a documented verification step.

Editorial conclusion

Adopt WindsurfAPI if you already have Windsurf or Devin accounts and want Claude Code, Cline or Cursor pointed at those models without rewriting client code, and if you are comfortable running a proxy that depends on a binary the project installs itself. Do not adopt it if you need a vendor-supported integration, cannot run a long-lived local process, or expect the proxy to perform file edits on its own. Before committing, verify that install-ls.sh produces a working Language Server on your platform, that a plain curl against /v1/chat/completions returns a completion with your API_KEY set, and that the account pool behaves under your real request rate rather than a single test call.

Frequently asked questions

What is WindsurfAPI used for?

It turns Windsurf and Devin models into OpenAI, Anthropic and Gemini compatible APIs so clients such as Claude Code, Cline and Cursor can connect to them. The proxy listens on port 3003 and translates requests into the gRPC calls the Windsurf Language Server understands.

Is WindsurfAPI free to use?

The code is MIT licensed, so the software itself carries no fee. The README adds a separate author statement asking users who have not starred or followed the repository not to use it commercially or as a hosted relay, and notes that this paragraph reflects the author's personal position rather than the licence.

Does WindsurfAPI need a Windsurf account?

Yes. The proxy routes through the Windsurf Language Server to server.self-serve.windsurf.com, and it maintains an account pool with round-robin rotation, rate limit isolation and failover. Without usable Windsurf or Devin credentials there is nothing for the pool to route through.

Can WindsurfAPI edit files in my project?

No. The README states that the model does not operate on files; file operations are executed locally by the IDE agent client such as Claude Code or Cline. The proxy returns an Anthropic SSE stream containing a tool_use content block, and the client performs the edit.

Official sources

  1. dwgx/WindsurfAPI on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dwgx-windsurfapi.svg)](https://hysenlabs.com/projects/dwgx-windsurfapi)