Scoped client keys
Create revocable llmharbor-* keys for apps and agents, each with its own route, provider, and model allow/block policy.
Self-hosted, local-first, OpenAI compatible
LLMHarbor exposes one OpenAI-compatible endpoint, then handles provider credentials, browser accounts, limits, fallback, and per-key access policy.
curl -fsSL https://raw.githubusercontent.com/PLASMA-FR/LLMHarbor/main/install.sh | bash
A small local control plane routes requests to healthy provider keys and OAuth-backed accounts, applies per-client access policy, and falls back without changing your client code.
Why it exists
Most AI tools want one base URL and one API key. Real life is different: API providers use different formats, browser subscriptions expose different model inventories, Cloudflare needs account-scoped keys, local servers move around, and free tiers get rate-limited.
LLMHarbor gives you one stable local endpoint while it handles encrypted credentials, OAuth-backed accounts, model registration, per-client access policy, fallback order, health checks, and request analytics behind the scenes.
Create revocable llmharbor-* keys for apps and agents, each with its own route, provider, and model allow/block policy.
Add Google, Groq, Mistral, OpenRouter, Cloudflare, NVIDIA, HuggingFace, and custom OpenAI-compatible endpoints.
Connect ChatGPT/OpenAI and Antigravity through loopback OAuth, or Freebuff through its browser device flow, then discover routeable models.
Order models by preference. The router skips unhealthy, disabled, rate-limited, reconnect-required, and incompatible routes.
Drop a text file with one key per line and import an entire batch into the provider target you choose.
See model usage, latency, error reasons, token use, and traffic patterns from a local dashboard.
Account access, without raw token paste
Connect supported browser accounts from OAuth. LLMHarbor handles PKCE loopback callbacks or device verification as required, encrypted storage, refresh, provider-reported limits, and inventory cleanup so stale models do not leak into /v1/models. A remote Tailscale/VPN dashboard can securely submit the provider-returned localhost callback URL when that fixed redirect lands on the browser device instead of the server.
Create one local API key per app, device, or agent. Keep the same /v1 base URL, then restrict that key to specific local routes, providers, or models before an upstream call is attempted.
Client key
POST /api/client-keys
{
"label": "editor agent"
}
OAuth accounts
POST /api/oauth/connect/openai/start
POST /api/oauth/connect/antigravity/start
POST /api/oauth/connect/:provider/callback
GET /api/oauth/accounts/:id/models
Access policy
GET /api/client-keys/:id/access-policy
PATCH /api/client-keys/:id/access-policy
{
"platforms": [{ "platform": "groq", "enabled": false }],
"models": [{ "modelDbId": 42, "enabled": false }]
}
Provider operations
Open Providers, pick a target from the current provider list, upload a .txt file, and LLMHarbor creates one stored credential per non-empty, non-comment line. The dashboard submits the stable provider platform returned by GET /api/provider-keys/providers; legacy numeric positions are accepted only for older clients.
keys.txt
AIzaSy...one
AIzaSy...two
# comments are ignored
AIzaSy...three
API shape
POST /api/provider-keys/import
{
"platform": "google",
"contents": "key-one\nkey-two",
"labelPrefix": "Google batch"
}
Full docs
llmharbor start or run from the repo with npm run dev.http://127.0.0.1:3001/v1.curl http://127.0.0.1:3001/v1/chat/completions \
-H "Authorization: Bearer YOUR_LLMHARBOR_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"auto","messages":[{"role":"user","content":"hello"}]}'
model: auto, omitted model fields, and retryable upstream failures.Built-in providers appear first in Providers and Models. Custom OpenAI-compatible endpoints can be added under Providers and then populated from Models. Resolve the stable bulk-import platform from the current UI or GET /api/provider-keys/providers.
The OAuth page starts PKCE loopback login for OpenAI/ChatGPT and Antigravity, or browser device verification for Freebuff, and stores account tokens encrypted. On a remote Tailscale/VPN dashboard, paste the complete returned localhost callback URL into the short-lived fallback field; the server verifies the exact loopback route and consumes the original state and PKCE verifier once. Discovery refreshes account models and provider-reported usage windows; accounts that need reconnect are hidden from routing until fixed. Antigravity includes its native desktop client configuration; the server environment values are overrides.
Local API keys keep a single OpenAI-compatible /v1 base URL while Settings scopes each key independently. Block /v1/models, an upstream provider family, or an individual model row for a selected key without changing other apps.
LLMHarbor routes requests through enabled models with eligible credentials. Routing shows priority, health, quota/cooldown state, and why a row is skipped. Retryable failures skip that credential for the current request; only rate-limit and quota failures create a persistent cooldown. A stream can fall back before response data starts, but never after partial output has reached the client. Analytics summaries count final client outcomes, while the recent-error feed retains failed fallback attempts for diagnosis.
GET /api/pingPublic liveness check.GET /api/provider-keysList masked provider credentials.POST /api/provider-keysAdd one provider credential.GET /api/provider-keys/providersList stable provider targets for bulk import.POST /api/provider-keys/importImport provider credentials from text lines.GET /api/client-keysList local client keys.POST /api/client-keysCreate local client keys for apps and agents.GET /api/client-keys/:id/access-policyInspect routes, providers, and models scoped to one local key.PATCH /api/client-keys/:id/access-policyAllow or block local routes, provider endpoints, and model rows.GET /api/oauth/accountsList connected OAuth-backed accounts.GET /api/providersList built-in and custom endpoints.GET /v1/modelsList the models eligible for the authenticated client key.POST /v1/chat/completionsOpenAI-compatible chat completions proxy.GitHub Actions installs from the lockfile, validates Bash, PowerShell, and static-site JavaScript syntax, runs ShellCheck and dashboard lint, executes the server tests, builds the server and dashboard, and audits production dependencies. Release candidates should also be exercised through the real CLI lifecycle and API-backed browser workflows on their target operating systems.
The dashboard/control-plane API is loopback-only by default. Trusted-network mode permits every client that can reach its private listener; it does not add dashboard login. Provider keys and OAuth tokens are encrypted with AES-256-GCM and a fresh nonce per write, while local llmharbor-* client keys are stored as one-way hashes and shown only when created or regenerated. Listing endpoints return only masked credential metadata. Custom endpoints allow local/private HTTP(S) targets but block credential-bearing URLs, metadata/link-local destinations, unsafe DNS resolution, and redirects. Per-client access policies and CORS are guardrails, not substitutes for a private network boundary. Do not expose the control plane directly to the public internet; keep it on loopback or a private VPN address.
^22.12.0 or ^24.0.0.HOST=127.0.0.1 for local-only operation.PORT=3001 or another valid port between 1 and 65535.npm run check and npm audit before deploying changes..env. If no environment key is configured, also preserve the database .key sidecar; streamed database backups intentionally exclude it. Imports are validated and staged, require a restart to activate, and must use the matching credential-encryption key.