@viudes/windsurf-api
v0.1.14
Published
Windsurf to OpenAI + Anthropic compatible API proxy. Turns Windsurf's 100+ AI models (Claude, GPT, Gemini, DeepSeek, Grok, Qwen, Kimi, GLM, SWE) into dual-protocol API endpoints. Zero npm deps.
Maintainers
Readme
windsurf-openai
Turn Windsurf (formerly Codeium) cloud models into standard, drop-in APIs:
POST /v1/chat/completions— OpenAI-compatible (any OpenAI SDK)POST /v1/messages— Anthropic-compatible (Claude Code / Cline / Cursor)POST /v1/responses— OpenAI Responses APIGET /v1/models— list available models
100+ models (Claude, GPT-5.x, Gemini, Grok, Qwen, Kimi, GLM, SWE, …). Pure Node.js, zero npm dependencies, requires Node >=24.
Fork of dwgx/WindsurfAPI, rewritten in English with a
windsurf-apiCLI. MIT licensed — see LICENSE.
Quick start (CLI)
npm i -g @viudes/windsurf-api # from npm (or `npm install -g .` from a clone)
windsurf-api install # write .env, create dirs, download the Language Server
windsurf-api login --token <windsurf-token> # add an account (get the token below)
windsurf-api start --port 3003 # boot the proxyOther commands: windsurf-api accounts (list the pool), status (pool summary), --help (all flags). Flags like --port, --api-key, --ls-binary override .env.
The Language Server is Linux/macOS only. On Windows,
installscaffolds.envand the directories but skips the download — use Docker or WSL2, or point--ls-binaryat a Windsurf desktoplanguage_serverbinary. Prebuilt single-file executables are also attached to each GitHub Release.
Docker
cp .env.example .env
docker compose up -d --build
docker compose logs -fState persists under ./.docker-data/; the container auto-downloads the Language Server on first boot if it isn't already there.
Add an account
Grab your token from windsurf.com/show-auth-token, then either:
windsurf-api login --token YOUR_TOKEN
# or over HTTP:
curl -X POST http://localhost:3003/auth/login \
-H "Content-Type: application/json" \
-d '{"token": "YOUR_TOKEN"}'Or open the dashboard at http://YOUR_IP:3003/dashboard and sign in with Google / GitHub / email — it adds the account to the pool automatically.
Use it
OpenAI SDK:
from openai import OpenAI
client = OpenAI(base_url="http://YOUR_IP:3003/v1", api_key="YOUR_API_KEY")
r = client.chat.completions.create(
model="claude-sonnet-4.6",
messages=[{"role": "user", "content": "Hello"}],
)
print(r.choices[0].message.content)Claude Code:
export ANTHROPIC_BASE_URL=http://YOUR_IP:3003
export ANTHROPIC_API_KEY=YOUR_API_KEY
claudeThe OpenAI surface supports streaming, tool/function calling, JSON mode, image inputs, and real token usage. List models with GET /v1/models.
Cursor blocks model names containing
claudeclient-side — use aliases likesonnet-4.6oropus-4.6instead. GPT / Gemini names work as-is.
Configuration
Configure via environment variables (or .env). The common ones:
| Variable | Default | Description |
|---|---|---|
| PORT | 3003 | Service port |
| API_KEY | empty | Required on requests when set; empty disables auth |
| HOST | 0.0.0.0 | Bind host (127.0.0.1 for localhost-only) |
| DATA_DIR | ~/.windsurf-api | Persisted state and logs (/data in Docker) |
| DEFAULT_MODEL | claude-4.5-sonnet-thinking | Model used when none is given |
| MAX_TOKENS | 8192 | Default max response tokens |
| LS_BINARY_PATH | /opt/windsurf/language_server_linux_x64 | Path to the Language Server binary |
| DASHBOARD_PASSWORD | empty | Dashboard password (empty = none) |
See .env.example for the full, annotated list (proxy, account pool, LS pool tuning, lab/experimental flags).
Config file (fallback below ENV)
Instead of (or alongside) environment variables, you can drop a config.json next to the app — a
flat JSON file keyed by the same names as the env vars. It is a fallback: anything already set
in the environment wins, and the file only fills what's missing. Precedence is:
CLI flags > real ENV > .env > config.json > built-in defaults{
"PORT": "3003",
"API_KEY": "sk-...",
"LS_BINARY_PATH": "/opt/windsurf/language_server_linux_x64",
"CODEIUM_AUTH_TOKEN": "..."
}Copy config.example.json to config.json (it's gitignored — it holds
secrets). windsurf-api install writes both .env and config.json for you. Keys prefixed with
_ are treated as comments and ignored.
Required to boot: the server refuses to start unless at least one auth source is configured —
CODEIUM_API_KEY, CODEIUM_AUTH_TOKEN, CODEIUM_EMAIL + CODEIUM_PASSWORD, or a non-empty
accounts.json. Set WINDSURFAPI_ALLOW_NO_AUTH=1 to start empty and add accounts later from the
dashboard.
Dashboard
http://YOUR_IP:3003/dashboard — account management, subscription/balance detection, model whitelist/blacklist, per-account proxies, live logs, and latency/usage stats.
How it works
The proxy translates each request into Windsurf's gRPC/Cascade protocol and relays it through a locally-spawned Language Server, managing a self-healing account pool (round-robin, rate limits, failover) along the way.
This is a chat API, not an IDE agent — it only passes tool_use / tool_result through. Your client (Claude Code, Cline, Cursor, Aider) is what actually reads and writes local files. If the model says it "can't access the filesystem", that's expected: drive it from one of those clients.
License
MIT — see LICENSE.
