The Problem Sixteen different free‑tier LLM providers each require their own SDK, rate‑limit handling, and error‑mapping. Managing keys, fall‑over, and per‑provider budgets is tedious and error‑prone. FreeLLMAPI collapses all of them behind a single OpenAI‑compatible /v1/chat/completions endpoint so any client library can speak one URL.

What This Does FreeLLMAPI is a proxy built on Express (server) and React/Vite (client). It stores provider keys encrypted in a SQLite database (server/src/db/index.ts) and uses a router (server/src/services/router.ts) to pick the best available model per request, fall‑over on rate‑limit, and track usage against each provider’s free‑tier cap. The router consults the hub module server/src/db/index.ts (45 importers, instability 0.02) for key lookup and usage stats. An oversized proxy handler lives in server/src/routes/proxy.ts (708 lines) and the migration script in server/src/db/migrations.ts (708 lines) – both are high‑churn, high‑blast‑radius files that would benefit from splitting into smaller units. The call graph shows cn (43 call sites), getDb (38), and apply (23) as the most‑touched functions; a change to the database schema ripples through many modules.

How It Is Wired

  • Entry point: main in server/src/index.ts:12 reaches 87 functions, called from 1 place.
  • Database hub: initDbmigrateDbSchemacreateTables (server/src/db/index.ts) sets up the SQLite schema and performs crypto‑key initialization (server/src/lib/crypto.ts).
  • Routing flow: routeRequestisGatedApiPathgetSessionKeygetStickyModel → provider‑specific HTTP call (fetchWithTimeout).
  • Key operations: getUnifiedApiKey, regenerateUnifiedKey, decrypt all touch the DB (server/src/db/index.ts) and crypto (server/src/lib/crypto.ts).
  • Blast‑radius modules: server/src/db/index.ts (45 dependents), server/src/app.ts (20 dependents, instability 0.39), and server/src/lib/crypto.ts (13 dependents, instability 0).
  • External touches: 60 functions read/write the DB; 1 function calls a model for inference; 8 perform crypto/secret ops. No model inference occurs inside the repo; calls exit the process via the provider HTTP layer.

How To Use It

StepCommand / File
Clonegit clone https://github.com/moses-y/freellmapi
Installcd freellmapi && npm ci (lockfile‑driven install)
EnvCopy .env.example.env; set UNIFIED_DB_PATH, provider API keys (e.g., GOOGLE_API_KEY, GROQ_API_KEY). The unified key is stored encrypted in server/src/db/index.ts.
Build/Dockerdocker build -t freellmapi . (Dockerfile present) or docker-compose up --build
Start servernpm run start (runs server/src/index.tsmain)
Start clientnpm run dev in client/ (Vite dev server, connects to http://localhost:3000 by default)
Desktopnpm run build then npm run start in desktop/ (Electron, entry desktop/src/main.ts)

Real‑World Use A team wants to prototype a chatbot using multiple free models without managing sixteen SDKs. They add keys for Google Gemini, Groq Llama 3, and OpenRouter, point their OpenAI‑compatible client (openai npm package) at http://localhost:3000/v1/chat/completions, and the router automatically selects the cheapest‑available model, falls back on the next provider when rate‑limited, and logs per‑key token usage to stay under each free‑tier cap.

Code Health & Issues (measured findings, not opinion)

  • [HIGH] Pin GitHub Actions to commit SHAs.github/workflows/ci.yml uses @v3/@v5 tags for docker/setup-buildx-action, docker/login-action, docker/metadata-action, docker/build-push-action. Tags can move, risking secret exposure. Fix: replace with 40‑character SHAs and let Dependabot bump them.
  • [MEDIUM] Declare least‑privilege GITHUB_TOKEN permissions – one workflow declares no permissions. Fix: add permissions: contents: read at top and widen per‑job as needed.
  • [MEDIUM] Enable Dependabot or Renovate – 5 manifests, no update bot configured. Fix: commit .github/dependabot.yml covering npm and GitHub Actions.
  • [MEDIUM] Install from lockfile in CInpm install without --ci. Fix: use npm ci (or yarn install --immutable).
  • [MEDIUM] Gate PRs on dependency vulnerability scan – no scan in CI. Fix: add dependency-review-action on pull_request or osv-scanner on push.
  • [MEDIUM] Gate checkout on persist-credentials: false – token remains in .git/config for later steps. Fix: add with: persist-credentials: false and pass explicit token only to push steps.
  • [LOW] Set timeout-minutes on workflow jobs – 2 jobs have no timeout. Fix: add realistic timeout-minutes per job.
  • [LOW] Add convention files – missing .editorconfig, .gitattributes, formatter config. Fix: add those files per project conventions.

The Bottom Line FreeLLMAPI delivers a pragmatic solution for experimenting with many free LLM tiers behind a single OpenAI‑compatible API. The architecture is clear: a hub DB module, a router, and encrypted key storage. However, the codebase shows several high‑impact maintainability risks—oversized proxy/migration files, untagged GitHub Actions, and missing Dependabot. It’s well‑suited for personal or small‑team prototyping where the free‑tier aggregation outweighs the need for rock‑solid production hardening; for larger deployments, invest in the listed hygiene fixes and consider splitting the proxy and migration logic into smaller, testable units.