# Free Claude Code (fcc-server) — local proxy reference

Working knowledge of the `fcc-server.exe` proxy from the [free-claude-code](https://github.com/Alishahryar1/free-claude-code) project. Captured after a 2026-07-16 session that brought one up on Rob's Windows laptop.

> **Status as of 2026-07-19: fcc-server is REDUNDANT for Claude-shaped traffic on this user's machine.** Rob upgraded to Claude Pro (claude.ai subscription). Claude Code (the official `@anthropic-ai/claude-code` npm CLI) supports **direct OAuth sign-in with a Pro/Max subscription** — first run of `claude` prompts "Sign in with Claude account" vs "API key", opens the browser for OAuth, and then runs against the real subscription with no proxy, no API key, no model-routing hacks. That is the right answer for "run Claude Code on Connie". fcc-server remains relevant ONLY as a generic multi-provider Anthropic-API-shaped proxy for other tools that expect that surface (e.g. the Agentic OS dashboard's "Free Claude" card) — do not propose it as the way to run Claude Code itself anymore. When the user asks about Claude Code on Windows, default to the official CLI + Pro OAuth path; the install-and-sign-in transcript is in `references/claude-code-pro-oauth-setup.md`.

## Locations on this user's machine

| Item | Path |
|------|------|
| Binary | `C:\Users\Rob\.local\bin\fcc-server.exe` |
| Config / env | `C:\Users\Rob\.fcc\.env` |
| Logs | `C:\Users\Rob\.fcc\logs\server.log` |
| Bundled Python | `C:\Users\Rob\AppData\Roaming\uv\tools\free-claude-code\Lib\site-packages\free_claude_code\` |
| Default port | `8082` (from `PORT=` in `.env`) |
| Default admin UI | `http://127.0.0.1:8082/admin` (local-only) |
| Bearer for clients | `ANTHROPIC_AUTH_TOKEN=` in `.env` (literal string, not an Anthropic key — clients send this as `Authorization: Bearer <value>`) |

## What it actually is

A **multi-provider LLM proxy** that exposes an Anthropic-compatible API surface (`/v1/messages`, `/v1/models`, etc.) on `localhost:8082` and translates requests to one of 22 upstream providers (OpenRouter, NVIDIA NIM, Gemini, DeepSeek, Mistral, Codestral, OpenCode, HuggingFace, Cohere, GitHub Models, Groq, SambaNova, Cerebras, Fireworks, Cloudflare, Zai, Kimi, MiniMax, Wafer, plus LM Studio/llama.cpp/Ollama for local).

Despite the name, "Free Claude Code" is not a free-Claude hack — it's a generic Anthropic-API-shaped proxy that can route to any supported upstream.

## Provider namespace — the gotcha

The valid `MODEL=` values use the **underscore-separated internal names**, NOT the external provider brand names. Full list as of pydantic-settings ValidationError on 2026-07-16:

```
nvidia_nim, open_router, gemini, deepseek, mistral, mistral_codestral,
opencode, opencode_go, vercel, huggingface, cohere, github_models,
wafer, kimi, minimax, cerebras, groq, sambanova, fireworks, cloudflare,
zai, lmstudio, llamacpp, ollama
```

**Wrong (silently crashes fcc-server on startup):**
```
MODEL=openrouter/meta-llama/llama-3.3-70b-instruct:free
```

**Right:**
```
MODEL=open_router/meta-llama/llama-3.3-70b-instruct:free
```

When the wrong prefix is used, fcc-server exits on startup with a `pydantic_core._pydantic_core.ValidationError: Value error, Invalid provider: 'openrouter'` traceback that prints the full valid list — read stderr, don't guess.

## Valid OpenRouter free models (`:free` suffix, no credit cost)

These worked as of 2026-07-16. OpenRouter's free tier rotates; re-check if any start returning 429:

```
meta-llama/llama-3.3-70b-instruct:free
qwen/qwen-2.5-72b-instruct:free
qwen/qwq-32b-preview:free
google/gemini-2.0-flash-exp:free
mistralai/mistral-small-3.1-24b-instruct:free
deepseek/deepseek-chat-v3-0324:free
nvidia/llama-3.1-nemotron-70b-instruct:free
microsoft/phi-3.5-mini-128k-instruct:free
```

Full form: `MODEL=open_router/<one of the above>`

## Required keys per provider

| Provider | Required env key |
|----------|------------------|
| `open_router` | `OPENROUTER_API_KEY` (sk-or-v1...) |
| `nvidia_nim` | `NVIDIA_NIM_API_KEY` |
| `gemini` | `GEMINI_API_KEY` |
| `ollama` | `OLLAMA_BASE_URL` (e.g. `http://localhost:11434`) |
| `lmstudio` | `LM_STUDIO_BASE_URL` |
| `llamacpp` | `LLAMACPP_BASE_URL` |

At startup, fcc-server runs a best-effort validation of `MODEL=`. If the provider key is missing, it logs a WARNING (`Configured provider model validation failed during startup; server will continue and requests will fail at provider resolution when config is incomplete.`) and starts anyway. Then the first chat request fails with a clean error.

## Default startup behavior

- Reads `~/.fcc/.env` and validates via pydantic-settings (any unknown provider name in `MODEL=` crashes startup)
- Initializes a `ProviderRateLimiter` (default `1 req / 3s, max_concurrency=5` — visible at startup as `ProviderRateLimiter initialized (1 req / 3s, max_concurrency=5)`)
- Discovers OpenRouter models on first request (`Provider model discovery cached: provider=open_router models=<N>`)
- Binds Uvicorn on `0.0.0.0:8082`
- Exposes `/admin` for the Admin UI

## Symptom: status card "Live" but chat returns `(no output)`

In Agentic OS's FCC tab, the status card polls `GET /health` every ~3s. As long as the process is alive, that returns 200 OK → card stays green "Live". **This proves nothing about the chat path.**

To actually verify chat works:
1. Watch `server.log` for `POST /v1/messages` entries. If you only see `GET /v1/models` and `GET /health`, the chat request never reached the proxy.
2. Hit `POST /v1/messages` directly with `Invoke-WebRequest`, using `Authorization: Bearer <ANTHROPIC_AUTH_TOKEN>` and `anthropic-version: 2023-06-01` headers. Bypasses the UI entirely.
3. Check the Admin UI at `http://127.0.0.1:8082/admin` for live request logs.

## Symptom: fcc-server exits after ~60 seconds under health-poll load

See `windows-launch-diagnostics` — the "stopped, not crashed" failure mode. The process starts, serves health polls + a chat attempt, then disappears. stderr ends with `Uvicorn running on http://0.0.0.0:8082 (Press CTRL+C to quit)` and nothing else — no traceback. Likely a watchdog, idle-exit, or parent-process-killed issue. Reliable fix is to run it as a Windows Service via NSSM or schedule it via Task Scheduler with `RestartOnFailure`.

## Launch pattern that captures everything

```powershell
$exe    = "$env:USERPROFILE\.local\bin\fcc-server.exe"
$outLog = "$env:USERPROFILE\Desktop\fcc-server-stdout.log"
$errLog = "$env:USERPROFILE\Desktop\fcc-server-stderr.log"
Remove-Item $outLog, $errLog -ErrorAction SilentlyContinue
Get-Process fcc-server -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep -Seconds 1
$proc = Start-Process $exe -PassThru -NoNewWindow `
    -WorkingDirectory (Split-Path $exe) `
    -RedirectStandardOutput $outLog -RedirectStandardError $errLog
Write-Host "PID = $($proc.Id)"

# Poll for bind, then verify chat path
$bound = $false
for ($i = 1; $i -le 15; $i++) {
    Start-Sleep -Seconds 1
    if (Get-NetTCPConnection -State Listen -LocalPort 8082 -ErrorAction SilentlyContinue) {
        $bound = $true; Write-Host "bound after ${i}s"; break
    }
}
if ($bound) {
    try {
        $r = Invoke-WebRequest -Uri "http://localhost:8082/v1/models" `
            -Headers @{Authorization = "Bearer freecc"} -UseBasicParsing -TimeoutSec 5
        Write-Host "GET /v1/models -> HTTP $($r.StatusCode)"
    } catch { Write-Host "models probe failed: $($_.Exception.Message)" }
}
```

## Direct chat test (bypasses any UI)

```powershell
$body = @{
    model = "open_router/meta-llama/llama-3.3-70b-instruct:free"
    max_tokens = 100
    messages = @(@{role="user"; content="say hello in one sentence"})
} | ConvertTo-Json -Depth 5

$r = Invoke-WebRequest -Uri "http://localhost:8082/v1/messages" `
    -Method POST -ContentType "application/json" `
    -Headers @{Authorization="Bearer freecc"; "anthropic-version"="2023-06-01"} `
    -Body $body -UseBasicParsing -TimeoutSec 30
Write-Host "HTTP $($r.StatusCode)"
Write-Host $r.Content
```