Refactor from monolithic proxy to multi-backend architecture (Backend interface: OpenCode Zen + Kilo gateway). - Add auto rate-limit jailing: models returning HTTP 429 are hidden from /v1/models immediately and re-probed every 30 min - Backend interface supports model aliases, custom headers, and per-backend routing - Full Anthropic Messages API support with OpenAI format conversion - 9 free models across two backends with Claude name aliases
6.7 KiB
Free IDE Proxy
OpenAI/Anthropic-compatible proxy that aggregates free models from OpenCode Zen and Kilo Code under a single endpoint. Use DeepSeek V4 Flash, StepFun, Nemotron, OpenRouter free, and more — for free — in any OpenAI-compatible tool (Cursor, Claude Code, Continue, Cline, etc.).
How it works
Your tool → free-ide-proxy (localhost:6446) → { opencode.ai/zen/v1 | api.kilo.ai/api/gateway }
The proxy routes by model name to the matching backend, injecting the required headers. OpenCode Zen expects x-opencode-* headers with Bearer public; Kilo's gateway needs no auth for free models. Your tools talk standard OpenAI protocol to the proxy; the proxy handles the rest.
Auto rate-limit jailing
When an upstream starts returning HTTP 429 (rate limit) for a model, the proxy automatically cages it — the model disappears from /v1/models immediately. A background checker re-probes caged models every 30 minutes; if they recover, they reappear.
This means your client just needs to query /v1/models before each request and pick an available model. No hardcoded model names, no manual retries.
Quick Start
# Build
go build -o free-ide-proxy .
# Run (no auth)
./free-ide-proxy
# Run with API key protection
./free-ide-proxy -api-key "your-secret-key"
# Or via env var
export OPENCODE_PROXY_KEY="your-secret-key"
./free-ide-proxy
The server starts on http://127.0.0.1:6446.
CLI Flags
| Flag | Default | Description |
|---|---|---|
-port |
6446 |
Server port |
-host |
127.0.0.1 |
Server host |
-api-key |
(none) | API key to protect the proxy |
-version |
— | Show version and exit |
Also reads OPENCODE_PROXY_KEY environment variable if -api-key is not set.
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check (version, active model count, auth status) |
GET |
/v1/models |
List currently active (not rate-limited) free models |
GET |
/v1/models/{id} |
Single model detail (404 if rate-limited) |
POST |
/v1/chat/completions |
OpenAI Chat Completions (streaming + non-streaming) |
POST |
/v1/messages |
Anthropic Messages API |
POST |
/v1/v1/messages |
Workaround for Claude Code double-path bug |
Authentication
If -api-key is set, all requests require one of:
Authorization: Bearer <key>x-api-key: <key>
Available Models
OpenCode Zen (5 models) — opencode.ai/zen/v1
| Model ID | Aliases | Context | Max Output |
|---|---|---|---|
deepseek-v4-flash-free |
deepseek, deepseek-v4, ds |
1M | 384K |
big-pickle |
pickle |
200K | 32K |
mimo-v2.5-free |
mimo, mimo-v2.5, xiaomi |
1M | 32K |
north-mini-code-free |
north, north-mini, cohere |
256K | 64K |
nemotron-3-ultra-free |
nemotron, nemotron-3, nvidia |
1M | 16K |
API auth: Bearer public (no real token needed).
Kilo gateway (4 models) — api.kilo.ai/api/gateway
| Model ID | Aliases | Context | Max Output |
|---|---|---|---|
stepfun/step-3.7-flash:free |
stepfun, stepfun-free |
256K | 32K |
poolside/laguna-m.1:free |
poolside, poolside-free, laguna |
256K | 32K |
nvidia/nemotron-3-ultra-550b-a55b:free |
— | 1M | 16K |
openrouter/free |
openrouter |
256K | 32K |
API auth: None needed for free models.
All models support streaming, tool calls, and system messages. Reasoning models (DeepSeek, Nemotron, StepFun) need max_tokens ≥ 500 or they return empty content (first tokens go to reasoning).
Claude Code
Claude Code appends /v1/messages to ANTHROPIC_BASE_URL automatically. Set:
export ANTHROPIC_BASE_URL=http://127.0.0.1:6446
export ANTHROPIC_MODEL=claude-sonnet-4-6 # maps to deepseek-v4-flash-free
The proxy also handles /v1/v1/messages as a fallback for the double-path issue.
Claude model name aliases (Claude Code validates model names client-side):
| Claude Model | Maps to |
|---|---|
claude-sonnet-4-6, claude-sonnet-4-5, claude-sonnet-4 |
deepseek-v4-flash-free |
claude-opus-4-8, claude-opus-4-5, claude-opus-4 |
deepseek-v4-flash-free |
claude-haiku-4-5, claude-haiku-4 |
north-mini-code-free |
claude-3.5-sonnet |
north-mini-code-free |
claude-3.5-haiku |
big-pickle |
Tool Configuration
Cursor / Continue / Cline
- Base URL:
http://127.0.0.1:6446/v1 - API Key: your proxy key (or empty if no auth)
- Model:
deepseek-v4-flash-free(or any alias)
Any OpenAI SDK
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:6446/v1",
api_key="your-proxy-key"
)
response = client.chat.completions.create(
model="deepseek-v4-flash-free",
messages=[{"role": "user", "content": "Hello!"}]
)
Deploy on VPS
# Build for Linux
GOOS=linux GOARCH=amd64 go build -o free-ide-proxy .
# Copy and run
scp free-ide-proxy user@vps:/home/user/
ssh user@vps './free-ide-proxy -api-key "secure-key" -host 0.0.0.0'
systemd service
[Unit]
Description=Free IDE Proxy
After=network.target
[Service]
ExecStart=/home/user/free-ide-proxy -api-key "${PROXY_KEY}" -host 0.0.0.0
Restart=always
User=user
EnvironmentFile=/etc/free-ide-proxy.env
[Install]
WantedBy=multi-user.target
Local SSH tunnel
ssh -L 6446:127.0.0.1:6446 user@your-vps
Then point your tools at http://127.0.0.1:6446/v1.
Quirks & Gotchas
- No tests exist yet. All manual testing.
- In-memory only — session and health state dies on restart. Health map auto-rebuilds via initial scan.
- Health check logs show rate-limit activity:
sudo journalctl -u free-ide-proxy | grep health - Unknown models are forwarded as-is via the default backend (opencode) — catch-all for new models.
- Reasoning model caveat: DeepSeek, Nemotron and StepFun need
max_tokens≥ 500; with very low values they return empty content. This is model behaviour, not a proxy bug.
Architecture
Client → internal/server/ (HTTP, auth, routing)
→ internal/proxy/ (model resolve, backend router, session mgmt,
forwarding, Anthropic↔OpenAI conversion)
→ Backend → upstream
- Pure stdlib Go 1.22 — no router, no dependencies beyond stdlib.
- Multi-backend via
Backendinterface (internal/proxy/backend.go). Add a new backend by implementing the interface and registering it inNewProxy(models.go). - Model aliases live in each backend (
opencode.go,kilo.go). - Auto rate-limit jailing built into
Models()— models returning 429 are hidden until they recover.
License
MIT