Metadata-Version: 2.4
Name: free-coding-router
Version: 0.1.0
Summary: A local-first, quota-aware AI coding router with an OpenAI-compatible endpoint
Project-URL: Homepage, https://github.com/Habib-Rehmn/free-coding-router
Project-URL: Repository, https://github.com/Habib-Rehmn/free-coding-router
Project-URL: Issues, https://github.com/Habib-Rehmn/free-coding-router/issues
Author-email: Habib <habibrehmn2@gmail.com>
License: MIT
License-File: LICENSE
Keywords: ai,coding,llm,openai,proxy,router
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Requires-Dist: fastapi<1,>=0.115
Requires-Dist: httpx<1,>=0.27
Requires-Dist: keyring<27,>=25
Requires-Dist: pydantic<3,>=2.8
Requires-Dist: rich<15,>=13.8
Requires-Dist: typer<1,>=0.12
Requires-Dist: uvicorn<1,>=0.30
Provides-Extra: code
Requires-Dist: aider-chat==0.86.2; (python_version < '3.13') and extra == 'code'
Provides-Extra: dev
Requires-Dist: pytest-asyncio<1,>=0.24; extra == 'dev'
Requires-Dist: pytest-cov<7,>=5; extra == 'dev'
Requires-Dist: pytest<9,>=8.3; extra == 'dev'
Requires-Dist: ruff<1,>=0.7; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# 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.

[![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Project status: Alpha](https://img.shields.io/badge/Status-Alpha-orange.svg)](#project-status)
[![OpenAI compatible](https://img.shields.io/badge/API-OpenAI%20compatible-412991.svg)](#openai-compatible-api)

**Local-first · BYOK · Streaming · Quota-aware · Aider-powered**

</div>

> [!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](#quick-start)
- [How it works](#how-it-works)
- [Terminal coding with Aider](#terminal-coding-with-aider)
- [Providers](#providers)
- [Models and routing](#models-and-routing)
- [OpenAI-compatible API](#openai-compatible-api)
- [Command reference](#command-reference)
- [Configuration](#configuration)
- [Reliability and sessions](#reliability-and-sessions)
- [Security](#security)
- [Development](#development)
- [Roadmap](#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.

```bash
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:

```bash
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:

```bash
cd /path/to/free_router
uv tool install .

free-router init
free-router doctor
free-router serve
```

Then configure the client:

```text
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

```text
                         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`](https://pypi.org/project/aider-chat/)
package as an optional dependency. It does not copy or fork Aider's source.

Start in any repository:

```bash
free-router code /path/to/repository

# Short alias
free-code /path/to/repository
```

Choose how models should be selected:

```bash
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 `--`:

```bash
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:

1. verifies that Aider and at least one provider are usable;
2. reserves an available loopback port;
3. starts a dedicated router with one stable session ID;
4. configures Aider's main, weak, and editor models;
5. forwards terminal input, arguments, and the final exit status; and
6. 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](https://console.groq.com/docs/openai) | Cloud | `GROQ_API_KEY` | Exact rate-limit headers when available |
| [Mistral](https://docs.mistral.ai/api) | Cloud | `MISTRAL_API_KEY` | OpenAI-compatible chat and model discovery |
| [Gemini](https://ai.google.dev/gemini-api/docs/openai) | Cloud | `GEMINI_API_KEY` | Uses Google's OpenAI compatibility endpoint |
| [OpenRouter](https://openrouter.ai/docs/quickstart) | Cloud | `OPENROUTER_API_KEY` | Filters paid models when configured as free tier |
| [Ollama](https://docs.ollama.com/api/openai-compatibility) | Local | None | Local, private, and not quota limited |

Run the setup wizard again whenever providers change:

```bash
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:

```bash
free-router route "Refactor authentication and add migration tests"
```

## OpenAI-compatible API

The initial compatibility surface is deliberately small:

```text
GET  /v1/models
POST /v1/chat/completions
```

Both normal and streaming chat completions are supported.

```python
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`:

```python
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:

```text
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:

```text
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:

```text
~/.config/free-coding-router/config.toml
```

Local usage and session state:

```text
~/.local/share/free-coding-router/router.sqlite3
```

<details>
<summary>Example configuration</summary>

```toml
[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
```

</details>

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:

```bash
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.1` by 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/local`
  when repository content must remain on the machine.
- A model's `free` tag 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:

```bash
uv sync --extra dev --extra code
```

Run the quality checks:

```bash
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

```text
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

- [x] Five-provider MVP
- [x] OpenAI-compatible chat and streaming
- [x] Quota-aware failover and health cooldowns
- [x] Persistent sessions and structured handoff
- [x] 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](https://github.com/Aider-AI/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](THIRD_PARTY_NOTICES.md) for attribution details.

## License

Free Coding Router is released under the [MIT License](LICENSE).
