Free Coding Router
One terminal coding tool. Five providers. One local endpoint.
Free Coding Router joins your provider accounts behind one local, OpenAI-compatible endpoint. It watches quota, selects a suitable coding model, preserves session state, and moves to the next provider when the current one slows down or reaches its limit.
Local-first · BYOK · Streaming · Quota-aware · Aider-powered
[!IMPORTANT] Free Coding Router is a legitimate API router, not a rate-limit bypass. It never creates accounts, rotates identities, scrapes consumer websites, or sends your provider credentials to a Free Coding Router service.
Why Free Coding Router?
Coding sessions should not end because one provider returns 429 Too Many Requests. Free Coding Router gives coding clients one stable endpoint while it
handles the unstable parts underneath:
- One command for terminal coding. Open any repository through the bundled Aider integration.
- One endpoint for existing tools. Connect any OpenAI-compatible client to
http://127.0.0.1:4141/v1. - Automatic failover. Retry transient failures, cool down unhealthy providers, and route around exhausted quota.
- Deliberate model selection. Choose sticky, balanced, preserve-best, or local-first routing.
- Local state. Credentials, usage, health, sessions, and checkpoints stay on your machine.
- Visible decisions. Inspect the selected provider, model, score, quota, and fallback reason.
Contents
- Quick start
- How it works
- Terminal coding with Aider
- Providers
- Models and routing
- OpenAI-compatible API
- Command reference
- Configuration
- Reliability and sessions
- Security
- Development
- Roadmap
Quick start
Complete terminal coding experience
Install from this source checkout with Python 3.12. The code extra installs
the pinned, compatible Aider release alongside the router.
cd /path/to/free_router
uv tool install ".[code]" --python 3.12
free-router init
free-router doctor
free-code /path/to/your/project
For the example project used during development:
free-code /home/habib-tlc/Desktop/vibe_app
That single command starts a private router, opens the repository in Aider, and stops the router when the coding session ends.
Standalone proxy
Install without Aider when another editor or client will connect to the API:
cd /path/to/free_router
uv tool install .
free-router init
free-router doctor
free-router serve
Then configure the client:
Base URL http://127.0.0.1:4141/v1
API key local
Model free-router/coder
local is only a placeholder required by some OpenAI clients. Real provider
credentials remain inside the router.
How it works
free-code /path/to/repo
│
▼
┌─────────────────┐
│ Aider │
│ repo map + edits│
└────────┬────────┘
│ OpenAI API
▼
┌──────────────────────────┐
│ Free Coding Router │
│ │
│ session context quota │
│ health scoring │
└────────────┬─────────────┘
│
┌──────────┬───────┼────────┬────────────┐
▼ ▼ ▼ ▼ ▼
Groq Mistral Gemini OpenRouter Ollama
│ │ │ │ │
└──────────┴───────┴────────┴────────────┘
│
▼
local SQLite ledger
Every provider implements the same internal contract: discover models, send a chat request, stream a response, report health, and normalize quota metadata. Provider-specific headers and errors never leak into the routing engine.
Terminal coding with Aider
Free Coding Router uses the official aider-chat
package as an optional dependency. It does not copy or fork Aider's source.
Start in any repository:
free-router code /path/to/repository
# Short alias
free-code /path/to/repository
Choose how models should be selected:
free-code . --model free-router/coder
free-code . --model free-router/best
free-code . --model free-router/free
free-code . --model free-router/local
Pass native Aider arguments after --:
free-code . -- --architect
free-code . -- --no-auto-commits README.md src/app.py
free-code . -- --message "Add parser tests" src/parser.py
The launcher performs six jobs:
- verifies that Aider and at least one provider are usable;
- reserves an available loopback port;
- starts a dedicated router with one stable session ID;
- configures Aider's main, weak, and editor models;
- forwards terminal input, arguments, and the final exit status; and
- stops the router on normal exit or
Ctrl+C.
Provider environment keys are removed from the Aider process. Only the router
receives them. Integrated mode also disables Aider analytics and update checks
for that run. When free-router/local is selected, main, weak, and editor roles
all remain local.
Providers
| Provider | Type | Credential | Notes |
|---|---|---|---|
| Groq | Cloud | GROQ_API_KEY |
Exact rate-limit headers when available |
| Mistral | Cloud | MISTRAL_API_KEY |
OpenAI-compatible chat and model discovery |
| Gemini | Cloud | GEMINI_API_KEY |
Uses Google's OpenAI compatibility endpoint |
| OpenRouter | Cloud | OPENROUTER_API_KEY |
Filters paid models when configured as free tier |
| Ollama | Local | None | Local, private, and not quota limited |
Run the setup wizard again whenever providers change:
free-router init
free-router doctor
free-router models --refresh
Secrets are stored in the operating-system keyring. Environment variables are supported as a read-only fallback and take precedence over keyring entries.
Models and routing
Clients can request a router alias instead of tracking provider model names.
| Alias | Purpose |
|---|---|
free-router/coder |
General coding route; the recommended default |
free-router/fast |
Favors lower response latency |
free-router/best |
Favors coding quality over speed |
free-router/free |
Admits only models tagged as free |
free-router/local |
Admits only local Ollama models |
Exact discovered models are also addressable with qualified IDs such as
groq/<model-id> or openrouter/<author>/<model-id>.
Routing strategies
| Strategy | Behavior | Best for |
|---|---|---|
sticky |
Keeps a session on one provider until it becomes unsuitable | Long coding sessions |
balanced |
Favors providers with less recorded use | Spreading quota consumption |
preserve-best |
Saves stronger models for requests that appear complex | Mixed workloads |
local-first |
Strongly prefers Ollama, then uses eligible cloud models | Privacy-conscious work |
Before scoring, the router rejects models that fail hard requirements: disabled provider, wrong requested model, insufficient context, missing tool support, active cooldown, or reserved quota. Eligible routes are scored by coding suitability, quota, context fit, tool support, reliability, latency, and configured priority.
Explain a decision before sending real work:
free-router route "Refactor authentication and add migration tests"
OpenAI-compatible API
The initial compatibility surface is deliberately small:
GET /v1/models
POST /v1/chat/completions
Both normal and streaming chat completions are supported.
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:4141/v1",
api_key="local",
)
response = client.chat.completions.create(
model="free-router/coder",
messages=[
{"role": "user", "content": "Explain this traceback and propose a fix."}
],
)
print(response.choices[0].message.content)
Streaming requires only stream=True:
stream = client.chat.completions.create(
model="free-router/coder",
messages=[{"role": "user", "content": "Refactor this function."}],
stream=True,
)
for event in stream:
print(event.choices[0].delta.content or "", end="")
Every successful response identifies its route:
X-Free-Router-Provider
X-Free-Router-Model
X-Free-Router-Session
X-Free-Router-Attempts
Clients that send X-Free-Router-Session retain sticky routing and router-side
checkpoints across requests. Integrated Aider sessions receive this identity
automatically.
Additional diagnostic endpoints:
GET /healthz
GET /router/status
POST /router/route/explain
Command reference
| Command | Description |
|---|---|
free-router init |
Configure providers and store credentials |
free-router code PATH |
Open a repository in integrated Aider mode |
free-code PATH |
Short alias for integrated coding mode |
free-router serve |
Start the standalone proxy |
free-router doctor |
Test credentials and provider connectivity |
free-router status |
Show local usage, health, and quota state |
free-router providers |
List provider settings and credential sources |
free-router models --refresh |
Refresh and list available models |
free-router route "TASK" |
Explain the ranking for a representative task |
free-router sessions |
List persisted coding sessions |
free-router config |
Show non-sensitive paths and settings |
Use free-router COMMAND --help for complete options.
Configuration
Non-sensitive configuration:
~/.config/free-coding-router/config.toml
Local usage and session state:
~/.local/share/free-coding-router/router.sqlite3
Example configuration
[server]
host = "127.0.0.1"
port = 4141
log_level = "info"
[routing]
strategy = "sticky"
quota_reserve_percent = 10.0
quota_request_reserve = 5
retry_attempts = 1
cooldown_seconds = 60
[context]
checkpoint_every = 5
recent_messages = 12
inject_on_provider_switch = true
[providers.groq]
enabled = true
priority = 100
tier = "free"
timeout_seconds = 90.0
[providers.ollama]
enabled = true
priority = 10
tier = "local"
base_url = "http://127.0.0.1:11434/v1"
timeout_seconds = 90.0
Set default_model on a provider to retain a known route if its model-list
endpoint is temporarily unavailable. Override base_url to use a compatible
gateway.
For isolated installations and tests:
export FREE_ROUTER_CONFIG_DIR=/custom/config/path
export FREE_ROUTER_DATA_DIR=/custom/data/path
Reliability and sessions
| Event | Router response |
|---|---|
| Quota approaches reserve | Exclude the provider before it reaches zero |
HTTP 429 |
Mark quota exhausted, start cooldown, switch provider |
Timeout or HTTP 5xx |
Retry according to policy, then switch provider |
| Provider switch | Inject the structured local session checkpoint |
| All cloud routes fail | Use eligible Ollama models |
| No routes remain | Return a structured OpenAI-style error |
Streaming can fail over until an upstream provider accepts the request. Once bytes have reached the client, replaying on another provider could duplicate or contradict output. An interrupted stream therefore ends with a structured SSE error instead.
SQLite records usage events, quota snapshots, provider health, route decisions, and session checkpoints. It never stores API keys.
Security
- The server binds to
127.0.0.1by default. - The proxy has no inbound authentication in v0.1. Never expose it directly to an untrusted network.
- API keys live in the OS keyring or the router process environment—not in TOML or SQLite.
- Integrated mode strips provider environment keys before starting Aider.
- Cloud prompts leave your computer by definition. Select
free-router/localwhen repository content must remain on the machine. - A model's
freetag is a routing hint, not a billing guarantee. Confirm plan limits and spending controls with each provider. - The project uses official APIs only. It does not scrape browser sessions or circumvent provider limits.
Never include live credentials, private prompts, or sensitive logs in public bug reports.
Project status
Free Coding Router is alpha software. Its v0.1 API focuses on chat completions, routing reliability, and the integrated terminal workflow. Expect configuration and internal adapter interfaces to evolve before v1.0.
Development
Create the development environment:
uv sync --extra dev --extra code
Run the quality checks:
uv run ruff check .
uv run pytest
uv build
Current validation covers configuration, quota parsing, model filtering, provider failover, streaming, session handoff, OpenAI response shapes, launcher process cleanup, credential isolation, CLI argument forwarding, and package metadata.
Project layout
src/free_coding_router/
├── cli.py commands and terminal presentation
├── launcher.py integrated Aider lifecycle
├── providers/ normalized provider adapters
├── routing/ filters, policies, and scoring
├── quota/ header parsing and reserve logic
├── context/ sessions and provider handoff
├── proxy/ FastAPI compatibility layer
└── storage/ keyring and SQLite persistence
Contributions should include focused tests and pass both Ruff and pytest. Keep provider-specific behavior inside its adapter; the router must operate only on normalized models, health, and quota state.
Roadmap
- Five-provider MVP
- OpenAI-compatible chat and streaming
- Quota-aware failover and health cooldowns
- Persistent sessions and structured handoff
- Integrated Aider terminal workflow
- Installable third-party provider SDK
- Remote model-capability registry with local overrides
- Predictive quota planning and richer usage reports
- Repository-aware context service for non-Aider clients
- Additional OpenAI-compatible endpoints
Acknowledgements
- Aider supplies the open-source terminal coding experience under Apache License 2.0.
- Groq, Mistral, Google, OpenRouter, and Ollama publish the official APIs used by the adapters.
See THIRD_PARTY_NOTICES.md for attribution details.
License
Free Coding Router is released under the MIT License.
Release files for free-coding-router 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| free_coding_router-0.1.0.tar.gz | 245.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| free_coding_router-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 285.7 kB
Release files / free_coding_router-0.1.0.tar.gz
| Download URL | free_coding_router-0.1.0.tar.gz |
|---|---|
| Size | 245.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cb8fb653522c5dd85c5f7934491cd460660a5171943d8bae7b0b4a69d309b5ca
|
|
BLAKE2b-256 checksum How to use checksums |
a506ad9ec3b1ecf3dbfc44240b67406e600f97d92338d5f76224a8b8dcb85d30
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.14
|
Release files / free_coding_router-0.1.0-py3-none-any.whl
| Download URL | free_coding_router-0.1.0-py3-none-any.whl |
|---|---|
| Size | 40.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b25f505bcc2bc04e5ad3305e8359d15ff8a128dc25395bb534930b6d80df46b1
|
|
BLAKE2b-256 checksum How to use checksums |
60b9bd6e6536edf1ffae114e67aa412cb8d52c60d2e153d38c8952e8d2ee9c94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.14
|