If you have tried several AI APIs, you already know the mess: one key per provider, different limits, and a different failure mode for every service. FreeLLMAPI tries to clean that up with a router that exposes an OpenAI-compatible API and an Anthropic-compatible surface as well.
The important word here is combine, not free. This project does not turn a paid API into an unlimited one, and it does not run large models on your laptop. It brings together the free quotas you configure, keeps track of them, and tries another provider when the current one is unavailable. We will run it with Docker and connect it to OpenCode and Claude Code without exposing the upstream keys.
What FreeLLMAPI Actually Does
FreeLLMAPI works as a local proxy and router. You add the provider keys you want in its dashboard, where the service stores them encrypted in SQLite. Your clients then use a single freellmapi-... key, while the router chooses an available model for each request.
The OpenAI-compatible API includes routes such as GET /v1/models and POST /v1/chat/completions. It also provides POST /v1/responses, /v1/completions for autocomplete clients, embeddings, and an Anthropic API at POST /v1/messages. The model catalogue changes regularly, so check the current FreeLLMAPI model catalogue instead of copying a fixed list into a tutorial.
When a provider returns a 429, a 5xx, or takes too long to respond, the router can move to the next model in the fallback chain. The X-Routed-Via header tells you which provider actually served the response. The virtual fusion mode sends the prompt to several models and asks another one to synthesize the drafts. It is useful for comparison, but one question now consumes several calls and burns through quotas much faster.
Install It with Docker
The project’s Docker documentation recommends Docker, Docker Compose, and OpenSSL. On macOS or Linux, the manual setup looks like this:
git clone https://github.com/tashfeenahmed/freellmapi.git
cd freellmapi
ENCRYPTION_KEY="$(openssl rand -hex 32)"
printf "ENCRYPTION_KEY=%s\nPORT=3001\n" "$ENCRYPTION_KEY" > .env
docker compose up -d
The official image is ghcr.io/tashfeenahmed/freellmapi:latest. Compose publishes the service on port 3001 and stores SQLite in the freellmapi-data volume. By default, it binds to 127.0.0.1, which is the sensible choice for a personal tool.
Check that the container is running and follow its logs:
docker compose ps
docker compose logs -f freellmapi
Open http://localhost:3001, create the dashboard account, and add provider keys under Keys. The key your clients need is the unified key shown there, not the Google, Groq, OpenRouter, or other upstream key.
If you prefer the quickest installation path, the project’s official install script prepares ~/freellmapi, generates the encryption key, and starts the container. I would still read the script before running it, and keep the manual setup if you need to know exactly what is being launched.
Running It on Another Machine
On a VPS or Raspberry Pi, you can start Compose with HOST_BIND=0.0.0.0 when you need access from a trusted network:
HOST_BIND=0.0.0.0 docker compose up -d
That only changes where Docker listens; it does not add security. The project is designed for a single user, and its documentation warns against exposing it directly to the internet. For remote access, use a private network, a tunnel, or a reverse proxy with HTTPS and authentication, and restrict the firewall. A local http://127.0.0.1:3001 only works on the machine running FreeLLMAPI.
Make Your First API Request
Keep the unified key in a shell variable so you do not paste it into every command or leave it in a repository file:
export FREELLMAPI_KEY="freellmapi-your-unified-key"
curl http://localhost:3001/v1/models \
-H "Authorization: Bearer $FREELLMAPI_KEY"
Then try a simple conversation. auto lets the router choose from the enabled models; you can also use an exact identifier returned by /v1/models.
curl http://localhost:3001/v1/chat/completions \
-H "Authorization: Bearer $FREELLMAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [
{"role": "user", "content": "Explain what Docker does in three sentences."}
]
}'
Do not make fusion your default model. The project’s Anthropic and Claude client documentation makes it clear that this mode makes several calls, and each one counts against the normal quotas.
OpenCode: Local or Remote
OpenCode can use an OpenAI-compatible provider. In opencode.json, the base URL should end in /v1, because the SDK appends the OpenAI routes to that prefix:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"freellmapi": {
"npm": "@ai-sdk/openai-compatible",
"name": "FreeLLMAPI",
"options": {
"baseURL": "http://127.0.0.1:3001/v1"
},
"models": {
"auto": {
"name": "FreeLLMAPI Auto"
}
}
}
}
}
Set the unified key through the credential mechanism supported by your OpenCode version. Do not put it in opencode.json if that file is committed. The OpenCode provider documentation describes the custom provider format, which can change between versions.
When OpenCode and FreeLLMAPI run on the same computer, 127.0.0.1 is correct. If OpenCode is on another machine, replace it with a private IP or a hostname on a trusted network. That is no longer a local integration: traffic crosses the network, so the endpoint needs proper protection.
Claude Code: Use the Anthropic Surface
This distinction matters. Claude Code does not expect an OpenAI API; it uses the Anthropic Messages format. FreeLLMAPI implements /v1/messages, so ANTHROPIC_BASE_URL should be the server origin without /v1/messages. Claude Code builds that path itself.
With Claude Code and FreeLLMAPI on the same machine, start by testing from the terminal where you will run claude:
export ANTHROPIC_BASE_URL=http://127.0.0.1:3001
export ANTHROPIC_AUTH_TOKEN="$FREELLMAPI_KEY"
claude
FreeLLMAPI recommends ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY: the former is sent as Authorization: Bearer. The current Claude Code gateway documentation confirms these variables and also supports storing them in env inside ~/.claude/settings.json, or in .claude/settings.local.json for one project. The latter should be ignored by Git if you create it manually.
You can test the Anthropic endpoint directly before opening Claude Code:
curl "$ANTHROPIC_BASE_URL/v1/messages" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 64,
"messages": [{"role": "user", "content": "Reply with: it works"}]
}'
The claude-sonnet-4-5 value is only an example of the Anthropic layer. The Keys -> Anthropic tab in FreeLLMAPI determines how the default, opus, sonnet, and haiku families map to the free catalogue you have enabled. If the model does not exist, check the dashboard mapping and the current catalogue; a Claude-shaped name does not mean an Anthropic model is running underneath.
For a remote server, use an accessible https:// URL from the machine running Claude Code and protect that server. Your laptop’s localhost does not point to the VPS, and opening the port without HTTPS is not a real fix.
Cursor: Compatibility Is Not Official Support
The FreeLLMAPI README lists Cursor among the clients that can use its OpenAI-compatible endpoint and explains that Cursor requests are checked and sent from Cursor’s servers. A localhost instance therefore will not work for it: you would need a remotely reachable endpoint with HTTPS and access controls.
The current Cursor Bring Your Own API Key documentation, however, documents custom keys for OpenAI, Anthropic, Google, Azure, and AWS Bedrock. It does not present an arbitrary third-party OpenAI URL as a stable configuration, nor does it promise that every compatible proxy will work. Cursor also says requests pass through its servers to build the final prompt, so its retention and behaviour are not equivalent to a direct local call.
That is why I am not going to invent a universal “paste this variable into Cursor” step. If your Cursor version exposes a custom base URL or OpenAI provider field, you can try https://your-domain/v1, the unified key, and auto, following the interface you actually have. If that field is absent, Cursor does not offer a documented direct integration for that installation. In that case, use FreeLLMAPI locally with OpenCode or Claude Code, or publish a properly protected gateway and accept that Cursor will still process the request through its own infrastructure.
Free Quotas Do Not Last Forever
FreeLLMAPI does not remove provider limits. A quota may be measured per minute, per day, or by tokens; a model can disappear, change its capacity, or stop being free; and a provider may return 429, take too long, or require a card later. Fallback keeps a request moving, but it may send it to a slower or less capable model. Availability also changes with time and with the keys you have configured.
The fusion mode multiplies usage because it calls several models and a judge. When providers are mixed, latency, context windows, tool support, and answer quality change too. That is perfectly useful for learning, experiments, personal automation, and a test environment.
I would not use it as the foundation for a critical service, a multi-user product, customer support with an SLA, or any workflow that cannot tolerate a 429. The project presents itself as local-first, single-user software without multi-tenant authentication. If you need guaranteed availability, support, and predictable limits, use a paid provider with the right contract.
Security Still Matters
ENCRYPTION_KEY encrypts provider keys at rest. Generate a new one during installation, keep it out of the repository, and preserve the same value alongside the volume when upgrading. If you lose it, encrypted credentials may no longer be recoverable even if the SQLite volume still exists.
Do not commit .env, the unified key, or upstream keys. Use environment variables or a secrets manager, check which files are ignored, and rotate keys if the host, dashboard, or a log may have been exposed. The unified key should have the smallest practical scope and must never end up in frontend code, screenshots, or shared configuration.
For an important installation, pin an image tag instead of relying on latest, upgrade deliberately, and make encrypted backups of the volume. Keep the dashboard off the public internet, put HTTPS in front of a remote service, and restrict network access. SQLite encryption does not protect a compromised machine, nor does it stop FreeLLMAPI from decrypting a key in memory when it calls a provider.
Conclusion
FreeLLMAPI is a practical way to put several free quotas behind familiar interfaces. Docker makes it easy to run, and the /v1 endpoint lets OpenCode and other OpenAI-compatible clients talk to the router without integrating every provider separately. Claude Code needs the Anthropic surface at /v1/messages; Cursor depends on whether your version allows a custom base URL and whether you can expose the service safely.
Start locally with one provider, a curl request, and an OpenCode configuration. Watch what happens when limits and fallbacks kick in before adding more keys or moving the service to a VPS. The real benefit is not unlimited free AI, because that does not exist; it is experimenting through one endpoint while staying aware of who controls your data, quotas, and keys.



What do you think?
Leave your opinion, question or suggestion. Comments are synced with GitHub Discussions .