Files
free-ide-proxy/README.md
T
Renato 05a52d29e2 feat: multi-backend proxy with auto rate-limit jailing
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
2026-06-26 19:08:01 +02:00

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 Backend interface (internal/proxy/backend.go). Add a new backend by implementing the interface and registering it in NewProxy (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