Contents
- Why this exists - Supported providers - [Compatible CLIs & coding
agents](#compatible-clis--coding-agents) - How it compares - Features - Quick start - [Desktop
app](#desktop-app) - Works with OpenAI-compatible clients - Languages - [Premium (live
catalog)](#premium-live-catalog) - Using the API - Screenshots - How it works - FAQ -
Limitations - Contributing - Disclaimer
Guides: Install & deploy · API reference · Clients & coding agents · [Prompt
compression](docs/compression.md) · Architecture & internals · Documentation index · [Contributor
guide](CONTRIBUTING.md)
Why this exists
Every serious AI lab now offers a free tier, a few million tokens a month, a few thousand requests a day. On its own each tier is a toy. Stacked
together, they add up to roughly 7.4 billion tokens per month of working inference capacity, across **474 model families / 635 provider
endpoints** from small-and-fast to reasonably capable.
The problem is that stacking them by hand is painful: thirty-four different SDKs, thirty-four different rate limits, thirty-four places a request can
fail. FreeLLMAPI collapses that into one OpenAI-compatible endpoint. Point any OpenAI client library at your local server, and it routes transparently
across whichever providers you've added keys for.
And the free-tier landscape shifts weekly: providers launch models, retire them, and change quotas without notice. FreeLLMAPI tracks all of that for
you. The router pulls a signed model catalog from freellmapi.co on its own, so your install keeps up without a git pull.
See Premium (live catalog) for how fast it keeps up.

Supported providers
Groq | Cerebras | OpenCode Zen | |
Mistral | OpenRouter | Cloudflare | Cohere |
Z.ai (Zhipu) | NVIDIA | HuggingFace | |
| ModelScope Qwen3 · DeepSeek V4 · GLM-5 (needs Aliyun cn binding) |
Plus a custom provider — point chat, embedding, image, or audio models at any OpenAI-compatible endpoint (llama.cpp, LM Studio, vLLM, a local Ollama, or a remote gateway) from the Keys page.
The full, always-current list lives at freellmapi.co/models with per-model rate limits, context windows, and free-token budgets.
Compatible CLIs & coding agents
Claude Code | Codex CLI | Gemini CLI | Aider |
Cline | Roo Code | Continue | OpenCode |
Goose | Qwen Code | Kilo Code | Crush |
Cursor | Zed | JetBrains AI | DeepSeek Harness |
Most of these configure themselves with one command — npx freellmapi setup-claude, setup-codex, setup-aider, setup-dsh (DeepSeek Harness), and
eleven more generators that fetch your live catalog, back up existing config, and never clobber what's already there. Claude Code and Codex also get
zero-persistence launchers (freellmapi launch, freellmapi launch-codex) that inject credentials into the child process only. Zed and JetBrains AI
connect through the opt-in Ollama emulation; Gemini CLI speaks its native wire on /v1beta.
Per-tool recipes, the setup CLI reference, revocable URL tokens for headerless clients, and the MCP server all live in Clients & coding agents →
How it compares

Based on public documentation, July 2026 — corrections welcome.
Features

- Every OpenAI-style surface —
/v1/chat/completions,/v1/responses(what Codex CLI needs),/v1/completions(editor ghost-text autocomplete),
/v1/images/generations, /v1/videos/generations, /v1/audio/speech, /v1/audio/transcriptions, /v1/embeddings, and /v1/models — streaming and
non-streaming, from the official SDKs or any OpenAI-compatible client. API reference → - Anthropic Messages API — /v1/messages
speaks Anthropic's wire format over the same router, so Claude Code and the official Anthropic SDKs run against your free pool. [Details
→](docs/api.md#anthropic--claude-clients) - Native Gemini + Ollama surfaces — Gemini CLI can use /v1beta (generateContent, streaming, token
counting, models), while opt-in Ollama emulation serves NDJSON chat/generate, tags, metadata, and embeddings for Zed, JetBrains, and other local-model
clients. - Fusion (multi-model synthesis) — request the virtual fusion model and the router fans your prompt out to a panel of diverse free
models in parallel, then a judge model synthesizes one answer from the drafts. Details → - **Image, video
& speech generation** — /v1/images/generations, /v1/videos/generations, and /v1/audio/speech route across the providers that serve media models;
images and speech also accept custom OpenAI-compatible media endpoints. Video jobs are normalized across synchronous and queued providers and return a
completed MP4. - Tool calling & structured outputs — OpenAI-style tools round-trip across providers (plain-text tool calls are rescued into real
tool_calls), plus response_format, seed, logprobs, penalties, and the rest of the sampling params passed through per provider. - **Smart
routing, six strategies** — live per-model speed/capability/reliability scores rank your chain; automatic fallover retries the next model on 429/5xx
with cooldowns and key rotation. Routing in detail → - Unified models & profiles — the same model on
several providers collapses into one entry with strict in-group failover; named fallback-chain profiles (a coding chain, a vision chain) switch from
the dashboard or per request via auto:<profile>. - Per-key rate tracking — RPM/RPD/TPM/TPD counters per (platform, model, key) that learn
providers' reported ceilings, so routing always stays under every cap. - Self-updating model catalog — the router syncs a signed catalog from
freellmapi.co twice a day: new models, quota changes, and provider quirk fixes land automatically. Free installs track the monthly snapshot, which
each model joins 30 days after it lands in the live feed; premium routers get it same-day. Premium → - **Sticky sessions &
context handoff** — conversations stay on one model for 30 minutes; an optional compact handoff note keeps the thread coherent when a mid-chat switch
does happen. Details → - Prompt compression (opt-in) — a shared, fail-open request pipeline can deduplicate
prompts, filter tool output, compact repeated JSON, and trim stale context before cache lookup and routing. Details → -
Encrypted keys, one token out — provider keys are AES-256-GCM encrypted in SQLite and decrypted in-memory per request; your apps only ever see a
single unified freellmapi-… bearer token. - Admin dashboard & analytics — React UI to manage keys, reorder the chain, run a playground, and read
p50/p95/TTFT analytics over 24h–90d windows; login-gated, dark/light themes, 60 languages. - MCP server & interactive docs — agents
can introspect usable models, provider health, and routing strategy over /mcp; a dependency-free OpenAPI viewer lives at /v1/docs. [Coding agents
→](docs/clients.md) - Ops niceties — opt-in response cache, encrypted DB backups, periodic key health checks, bulk key import/export, declarative
startup config. Install & deploy → - Runs anywhere Node 20+ runs — Windows, macOS, Linux servers, or a small ARM SBC (Raspberry
Pi included). ~40 MB RSS at idle behind PM2 / systemd / whatever supervisor you prefer.
The scope is deliberately narrow — see what's not supported yet.
Quick start
One-liner (Docker required — sets up ~/freellmapi, generates an encryption key, pulls the image, and starts the container):
curl -fsSL https://freellmapi.co/install.sh | bash
Prefer to read before you pipe to bash? The script is here. Re-running it is safe: your .env (and encryption
key) is preserved and the container updates to :latest.
Open http://localhost:3001, add your provider keys on the Keys page, reorder the Fallback Chain to taste, and grab your unified API key from
the Keys page header. That unified key is what you point your OpenAI SDK at.
On Windows, the easiest path is the desktop .exe installer from Releases (below).
On Android, see the experimental Termux guide.
Everything else — Docker Compose, local development, declarative startup config, production builds, LAN access, and backups — is in docs/install.md.
Desktop app
A native menu-bar app lives in desktop/: the entire router + dashboard running locally from your tray, with a glass popover showing live request stats.

Download from Releases — the macOS .dmg and the Windows .exe installer are
attached to every release. No account or password to set up: the only credential you need is the unified API key from the tray popover.
Build-from-source steps and where your data lives: docs/install.md.
Works with OpenAI-compatible clients
Anything that can target an OpenAI-compatible base URL works: set it to http://localhost:3001/v1 with the unified key from the dashboard. **Claude
Code, Codex CLI, Cline / Roo Code, Continue (including inline autocomplete), Aider, opencode, and Cursor** each have a short
recipe in docs/clients.md — and the router doubles as an MCP server your agents can introspect mid-session.
The fastest setup is generated from the models available on your live server:
npx freellmapi setup-claude --url http://localhost:3001 --api-key <unified-key>
Every generator supports --dry-run, creates a timestamped backup before changing an existing file, and merges into the user's configuration.
Launchers keep credentials out of config files entirely: npx freellmapi launch for Claude Code and npx freellmapi launch-codex for Codex.
| Agent | Automated setup | Base URL | | --- | --- | --- | | Claude Code | setup-claude | root | | Codex CLI | setup-codex | /v1 | | Cline |
setup-cline | /v1 | | Continue | setup-continue | /v1 | | Aider | setup-aider | /v1 | | OpenCode | setup-opencode | /v1 | | Goose |
setup-goose | /v1 | | Qwen Code | setup-qwen | /v1 (or native /v1beta) | | Roo / Kilo / Crush | setup-roo / setup-kilo / setup-crush |
/v1 | | DeepSeek Harness | setup-dsh | /v1 | | MiMo Code | setup-mimo | /v1 | | Cursor | setup-cursor guide | public /v1 URL |
FreeLLMAPI is local-first and single-user by design. Your provider keys stay in your SQLite database, encrypted at rest, and requests go from your machine to the upstream providers you enabled.
Languages
The dashboard ships in 60 languages (the desktop tray menu in 6). The UI auto-detects your browser/system language on first load and you can
switch any time from ⋯ → Settings; the choice is remembered. Right-to-left languages (العربية, עברית, فارسی, اردو) flip the whole layout
automatically, and only the active language's dictionary is loaded — the rest never touch your bandwidth.
<img src="https://flagcdn.com/24x18/us.png" srcset="https://flagcdn.com/48x36/us.png 2x" width="24" height="18" alt="United States" title="United
States"> ![]()
<img
src="https://flagcdn.com/24x18/fr.png" srcset="https://flagcdn.com/48x36/fr.png 2x" width="24" height="18" alt="France" title="France"> <img
src="https://flagcdn.com/24x18/br.png" srcset="https://flagcdn.com/48x36/br.png 2x" width="24" height="18" alt="Brazil" title="Brazil"> <img
src="https://flagcdn.com/24x18/it.png" srcset="https://flagcdn.com/48x36/it.png 2x" width="24" height="18" alt="Italy" title="Italy"> <img
src="https://flagcdn.com/24x18/in.png" srcset="https://flagcdn.com/48x36/in.png 2x" width="24" height="18" alt="India" title="India"> <img
src="https://flagcdn.com/24x18/sa.png" srcset="https://flagcdn.com/48x36/sa.png 2x" width="24" height="18" alt="Saudi Arabia" title="Saudi Arabia">
![]()
<img
src="https://flagcdn.com/24x18/pk.png" srcset="https://flagcdn.com/48x36/pk.png 2x" width="24" height="18" alt="Pakistan" title="Pakistan"> <img
src="https://flagcdn.com/24x18/id.png" srcset="https://flagcdn.com/48x36/id.png 2x" width="24" height="18" alt="Indonesia" title="Indonesia"> <img
src="https://flagcdn.com/24x18/de.png" srcset="https://flagcdn.com/48x36/de.png 2x" width="24" height="18" alt="Germany" title="Germany"> <img
src="https://flagcdn.com/24x18/jp.png" srcset="https://flagcdn.com/48x36/jp.png 2x" width="24" height="18" alt="Japan" title="Japan"> <img
src="https://flagcdn.com/24x18/ke.png" srcset="https://flagcdn.com/48x36/ke.png 2x" width="24" height="18" alt="Kenya" title="Kenya"> <img
src="https://flagcdn.com/24x18/tr.png" srcset="https://flagcdn.com/48x36/tr.png 2x" width="24" height="18" alt="Türkiye" title="Türkiye"> <img
src="https://flagcdn.com/24x18/vn.png" srcset="https://flagcdn.com/48x36/vn.png 2x" width="24" height="18" alt="Vietnam" title="Vietnam"> <img
src="https://flagcdn.com/24x18/kr.png" srcset="https://flagcdn.com/48x36/kr.png 2x" width="24" height="18" alt="South Korea" title="South Korea"> <img
src="https://flagcdn.com/24x18/ir.png" srcset="https://flagcdn.com/48x36/ir.png 2x" width="24" height="18" alt="Iran" title="Iran"> <img
src="https://flagcdn.com/24x18/th.png" srcset="https://flagcdn.com/48x36/th.png 2x" width="24" height="18" alt="Thailand" title="Thailand"> <img
src="https://flagcdn.com/24x18/pl.png" srcset="https://flagcdn.com/48x36/pl.png 2x" width="24" height="18" alt="Poland" title="Poland"> <img
src="https://flagcdn.com/24x18/ua.png" srcset="https://flagcdn.com/48x36/ua.png 2x" width="24" height="18" alt="Ukraine" title="Ukraine"> <img
src="https://flagcdn.com/24x18/mm.png" srcset="https://flagcdn.com/48x36/mm.png 2x" width="24" height="18" alt="Myanmar" title="Myanmar"> <img
src="https://flagcdn.com/24x18/ro.png" srcset="https://flagcdn.com/48x36/ro.png 2x" width="24" height="18" alt="Romania" title="Romania"> <img
src="https://flagcdn.com/24x18/nl.png" srcset="https://flagcdn.com/48x36/nl.png 2x" width="24" height="18" alt="Netherlands" title="Netherlands"> <img
src="https://flagcdn.com/24x18/my.png" srcset="https://flagcdn.com/48x36/my.png 2x" width="24" height="18" alt="Malaysia" title="Malaysia"> <img
src="https://flagcdn.com/24x18/ph.png" srcset="https://flagcdn.com/48x36/ph.png 2x" width="24" height="18" alt="Philippines" title="Philippines"> <img
src="https://flagcdn.com/24x18/ng.png" srcset="https://flagcdn.com/48x36/ng.png 2x" width="24" height="18" alt="Nigeria" title="Nigeria"> <img
src="https://flagcdn.com/24x18/et.png" srcset="https://flagcdn.com/48x36/et.png 2x" width="24" height="18" alt="Ethiopia" title="Ethiopia"> <img
src="https://flagcdn.com/24x18/uz.png" srcset="https://flagcdn.com/48x36/uz.png 2x" width="24" height="18" alt="Uzbekistan" title="Uzbekistan"> <img
src="https://flagcdn.com/24x18/az.png" srcset="https://flagcdn.com/48x36/az.png 2x" width="24" height="18" alt="Azerbaijan" title="Azerbaijan"> <img
src="https://flagcdn.com/24x18/lk.png" srcset="https://flagcdn.com/48x36/lk.png 2x" width="24" height="18" alt="Sri Lanka" title="Sri Lanka"> <img
src="https://flagcdn.com/24x18/np.png" srcset="https://flagcdn.com/48x36/np.png 2x" width="24" height="18" alt="Nepal" title="Nepal"> <img
src="https://flagcdn.com/24x18/kh.png" srcset="https://flagcdn.com/48x36/kh.png 2x" width="24" height="18" alt="Cambodia" title="Cambodia"> <img
src="https://flagcdn.com/24x18/gr.png" srcset="https://flagcdn.com/48x36/gr.png 2x" width="24" height="18" alt="Greece" title="Greece"> <img
src="https://flagcdn.com/24x18/cz.png" srcset="https://flagcdn.com/48x36/cz.png 2x" width="24" height="18" alt="Czechia" title="Czechia"> <img
src="https://flagcdn.com/24x18/hu.png" srcset="https://flagcdn.com/48x36/hu.png 2x" width="24" height="18" alt="Hungary" title="Hungary"> <img
src="https://flagcdn.com/24x18/se.png" srcset="https://flagcdn.com/48x36/se.png 2x" width="24" height="18" alt="Sweden" title="Sweden"> <img
src="https://flagcdn.com/24x18/il.png" srcset="https://flagcdn.com/48x36/il.png 2x" width="24" height="18" alt="Israel" title="Israel"> <img
src="https://flagcdn.com/24x18/dk.png" srcset="https://flagcdn.com/48x36/dk.png 2x" width="24" height="18" alt="Denmark" title="Denmark"> <img
src="https://flagcdn.com/24x18/fi.png" srcset="https://flagcdn.com/48x36/fi.png 2x" width="24" height="18" alt="Finland" title="Finland"> <img
src="https://flagcdn.com/24x18/no.png" srcset="https://flagcdn.com/48x36/no.png 2x" width="24" height="18" alt="Norway" title="Norway"> <img
src="https://flagcdn.com/24x18/sk.png" srcset="https://flagcdn.com/48x36/sk.png 2x" width="24" height="18" alt="Slovakia" title="Slovakia"> <img
src="https://flagcdn.com/24x18/bg.png" srcset="https://flagcdn.com/48x36/bg.png 2x" width="24" height="18" alt="Bulgaria" title="Bulgaria"> <img
src="https://flagcdn.com/24x18/hr.png" srcset="https://flagcdn.com/48x36/hr.png 2x" width="24" height="18" alt="Croatia" title="Croatia"> <img
src="https://flagcdn.com/24x18/rs.png" srcset="https://flagcdn.com/48x36/rs.png 2x" width="24" height="18" alt="Serbia" title="Serbia"> <img
src="https://flagcdn.com/24x18/lt.png" srcset="https://flagcdn.com/48x36/lt.png 2x" width="24" height="18" alt="Lithuania" title="Lithuania"> <img
src="https://flagcdn.com/24x18/tw.png" srcset="https://flagcdn.com/48x36/tw.png 2x" width="24" height="18" alt="Taiwan" title="Taiwan"> <img
src="https://flagcdn.com/24x18/pt.png" srcset="https://flagcdn.com/48x36/pt.png 2x" width="24" height="18" alt="Portugal" title="Portugal"> <img
src="https://flagcdn.com/24x18/ge.png" srcset="https://flagcdn.com/48x36/ge.png 2x" width="24" height="18" alt="Georgia" title="Georgia">
The full list of locales lives in
client/src/i18n/locale-config.ts.
The original six locales are human-reviewed; the newer ones are machine- translated and improve as native speakers send corrections — a one-string PR is a great first contribution.
Translations live in client/src/i18n/locales/ as flat JSON files. To fix a string, edit the value in the locale's JSON
file. To add a language, copy en.json, translate the values, and register the locale in client/src/i18n/locale-config.ts (and
desktop/src/i18n.ts for the tray strings); npm test checks every locale for key/placeholder parity — PRs welcome.
Premium (live catalog)
The router keeps its model catalog fresh on its own: it pulls a signed catalog from freellmapi.co twice a day and applies new
models, quota changes, and provider quirk fixes to your local DB. Your own enable/disable choices and custom providers are never touched, and every
download is verified against a pinned Ed25519 key before it is applied.
The catalog currently tracks 34 providers, 474 model families, 635 free provider/model endpoints (584 chat, 41 embeddings, 7
transcription, 3 video), and roughly 7.4 billion tokens per month of listed free-tier capacity. Browse the full set at
Free installs pull the same signed catalog, but from the monthly snapshot: a model joins it 30 days after it lands in the live feed, so the free build
currently sits about 303 models behind. Nothing expires and nothing is crippled — it just arrives later.
Premium keeps that signed catalog live on every router you run. When a provider launches a strong free model, quietly tightens a quota, or breaks a
wire format, live-feed routers receive the update the same day we ship it.
- $19/year or $49 once, lifetime. Stripe checkout; cancel anytime, self-serve. - One
fla_key covers every router you run: desktop, homelab,
Raspberry Pi. - Activate in the dashboard under Premium; cancel or manage billing self-serve at
freellmapi.co/manage. - The router itself stays MIT-licensed and fully free, forever. Premium is only the live feed,
and it's what funds the daily model testing and catalog maintenance that keeps the catalog working.
The catalog server never sees your prompts, completions, or provider keys — the router stays fully self-hosted either way.
Using the API
```python from openai import OpenAI
client = OpenAI( base_url="http://localhost:3001/v1", api_key="freellmapi-your-unified-key", )
resp = client.chat.completions.create( model="auto", # let the router pick; or "auto:fast", "auto:smart", a profile, or a model id messages=[{"role":
"user", "content": "Summarise the fall of Rome in one sentence."}], ) print(resp.choices[0].message.content) print("Routed via:",
resp.headers.get("x-routed-via")) ```
Streaming, the auto:* routing strategies, tool calling, vision input, Gemini Google Search grounding, embeddings, and the Anthropic Messages surface
— with curl and Python examples for each — are all in docs/api.md. Every response carries an X-Routed-Via: <platform>/<model>
header so you can see which provider actually served it.
Screenshots
Models
Pick a routing strategy and watch the monthly token budget fill across the whole provider fleet. Every model shows live reliability, speed, and
intelligence scores — the order below is how requests route right now.

Keys
Manage provider credentials and grab the unified API key your apps connect with. Each key shows a status dot and when it was last health-checked.

Playground
Send a chat completion through the router and see which provider served it, with the model ID and latency printed right on the message. Attach files
by button, drag-and-drop, or paste: images (PNG/JPEG/WebP/GIF) are downscaled in the browser and sent as image content parts to a vision-capable
model, and text files (TXT/MD/CSV/JSON/LOG) are inlined into the prompt as fenced blocks.

Analytics
Request volume, success rate, tokens in and out, average

