Open source · MIT · Self-hosted AI gateway
Speak, friend, and enter.
One guarded gateway for every AI provider. Add credentials once, point every OpenAI-compatible tool at a single local endpoint.
npm install -g durindoorOne door, every provider
Not just chat. Every kind of model call.
The same key and base URL reach chat, embeddings, speech, images, video and the web. Whatever the modality, it walks through the same door.
- 195 providers
Chat & code
/v1/chat/completions - 14 providers
Embeddings
/v1/embeddings - 13 providers
Text to speech
/v1/audio/speech - 6 providers
Speech to text
/v1/audio/transcriptions - 20 providers
Image generation
/v1/images/generations - 12 providers
Vision
image input - 4 providers
Video
/v1/video/generations - 16 providers
Web search
/v1/search - 6 providers
Web fetch
/v1/web/fetch
Provider counts come from the DurinDoor provider registry. Support for each modality depends on the provider.
How it works
Every request passes one door
Your tools speak OpenAI. Your providers speak whatever they like. DurinDoor stands between them, holds the keys, and keeps the ledger.
- 01
Knock
A tool sends a /v1 request with a DurinDoor key and a model string.
- 02
Resolve
The key is checked, the model resolved, and a healthy connection chosen.
- 03
Translate
Formats are bridged both ways; the upstream call uses stored credentials.
- 04
Record
Usage, latency and outcome land in local SQLite as the response streams back.
"model": "
- resolve provider model
- provider openai
- upstream gpt-4.1
- 200 OK stream · 412 ms
Three tiers of fallback
When one door is shut, try the next.
Put a subscription first, a cheap API second and a free or local model last. A combo keeps one stable model name; when a member fails, DurinDoor retries other accounts for it, then falls through to the next member.
try 1 cc/claude-sonnet
Sticky round-robin rotate after 3 uses, or pin a session to one account
- Account A
- Account B
- Account C
- Tier IIstanding by

Cheap API
Low-cost API keys and compatible endpoints take over when the subscription is rate limited.
openrouter/qwen3-coder - Tier IIIstanding by

Free & local
Free tiers or a local model keep the request alive when everything upstream says no.
ollama-local/qwen3
The fellowship
Every provider, bound to one ring
Connect OAuth subscriptions, API keys, web cookies, OpenAI- or Anthropic-compatible endpoints and local runtimes. Tools never learn which one answered.
- Registry
- 237 providers
- Custom nodes
- Any compatible URL
- Local
- No remote account
Compatible tools
If it speaks OpenAI, it walks through
Coding agents, editors and CLIs connect with one base URL and one DurinDoor key.
Claude Code
OpenAI Codex
Cursor
Cline
Kilo Code
Droid
OpenCode
GitHub Copilot
Hermes
Continue
Roo Code
Gemini CLI
Antigravity
Kiro
Amp
OpenClaw
Token savers
Say less. Mean the same.
Opt-in compression trims prompts after translation and before they leave your machine. It fails open: if an engine errors, the original request goes through untouched.
./open-sse/providers/registry/9router.js
./open-sse/providers/registry/agentrouter.js
./open-sse/providers/registry/aihorde.js
./open-sse/providers/registry/alibaba.js
./open-sse/providers/registry/anthropic.js
./open-sse/providers/registry/antigravity.js
./open-sse/providers/registry/assemblyai.js
./open-sse/providers/registry/azure.js
./open-sse/providers/registry/baidu.js
./open-sse/providers/registry/bedrock.js
./open-sse/providers/registry/black-forest-labs.js
./open-sse/providers/registry/brave-search.js
./open-sse/providers/registry/cartesia.js
./open-sse/providers/registry/cerebras.js
./open-sse/providers/registry/claude.js
./open-sse/providers/registry/cline.js
./open-sse/providers/registry/codex.js
./open-sse/providers/registry/cohere.js
./open-sse/providers/registry/copilot-web.js
./open-sse/providers/registry/cursor.js
./open-sse/providers/registry/deepgram.js
./open-sse/providers/registry/deepseek.js
./open-sse/providers/registry/elevenlabs.js
./open-sse/providers/registry/exa.js
./open-sse/providers/registry/firecrawl.js
./open-sse/providers/registry/fireworks.js
./open-sse/providers/registry/gemini.js
./open-sse/providers/registry/github.js
./open-sse/providers/registry/glm.js
./open-sse/providers/registry/groq.js
./open-sse/providers/registry/huggingface.js
./open-sse/providers/registry/kimi.js
./open-sse/providers/registry/kiro.js
./open-sse/providers/registry/minimax.js
./open-sse/providers/registry/mistral.js
./open-sse/providers/registry/nvidia.js
./open-sse/providers/registry/ollama.js
./open-sse/providers/registry/ollama-local.js
./open-sse/providers/registry/openai.js
./open-sse/providers/registry/openrouter.js
./open-sse/providers/registry/perplexity.js
./open-sse/providers/registry/qwen.js
./open-sse/providers/registry/together.js
./open-sse/providers/registry/vertex.js
./open-sse/providers/registry/xai.js
./open-sse/translator/index.js
./open-sse/translator/validate.js
./open-sse/translator/webTools.js
./open-sse/translator/formats.js
./open-sse/translator/formats/claude.js
./open-sse/translator/formats/gemini.js
./open-sse/translator/formats/responsesApi.js
./open-sse/translator/formats/openai.js
./open-sse/translator/formats/maxTokens.js54 files in 3 dirs:
./open-sse/providers/registry/ (45)
9router.js
agentrouter.js
aihorde.js
alibaba.js
anthropic.js
antigravity.js
assemblyai.js
azure.js
baidu.js
bedrock.js
+35
./open-sse/translator/ (4)
index.js
validate.js
webTools.js
formats.js
./open-sse/translator/formats/ (5)
claude.js
gemini.js
responsesApi.js
openai.js
maxTokens.js
Real output of DurinDoor's RTK find filter, using the sample file list.
RTK filters
Condense tool output such as git status, git diff, ls, grep, find and build logs.
Caveman
Rule-based prose compression with lite, full and ultra intensities.
Session dedup
Drops blocks repeated across turns of the same conversation.
Headroom
Optional adapter that only applies when it saves more than five percent.
X-DurinDoor-Token-Saver: offThe ledger
Know which account still has room
DurinDoor records every call in local SQLite and tracks provider limits and reset windows, so you can see which account still has headroom before a tool hits a wall.
- 82%used
- 46%used
- 27%used
In the dashboard
- Provider, model, tokens, cost estimate and latency for every request
- Which model served each request, and the fallback outcome
- Provider limits and reset windows side by side
What the door guards
Everything between your tools and your providers
Credentials, routing, fallbacks, translation and the ledger of every call, all on hardware you control.
- 01
Combos
Stack models behind one stable name. A failed member falls through to the next, so tools never change their config.
- 02
Format translator
Send OpenAI-shaped requests; Claude, Gemini, Kiro, Cursor, Ollama and Vertex formats are handled upstream.
- 03
Multi-account
Several connections per provider. Locked or expired accounts are skipped and OAuth tokens refresh.
- 04
Tunnels
Reach your gateway from another network over HTTPS. Keep dashboard auth on, turn it off when unused.
- 05
Proxy pools
Route upstream traffic through configured proxies for regional routing or egress control.
- 06
MITM bridge
Optional local interception for supported IDE traffic, behind explicit setup and trust changes.
- 07
MCP gateway
Expose multiple MCP servers behind managed keys and routes from the same dashboard.
- 08
One dashboard
Providers, API keys, combos, usage, request logs, endpoint setup, CLI tools, tunnels, MITM and MCP in one browser UI.
- 09
CLI tool setup
Copy ready integration settings for Claude Code, Codex, Cursor, Cline and more.
- 10
Self-hosted state
Storage, credentials and logs live in your DATA_DIR. You decide who can reach it.
Before and after
Wiring every tool by hand, or one door
What changes when your tools stop talking to providers directly.
| When you need | Per-tool setup | DurinDoor |
|---|---|---|
| Base URL your tools point at | A different one per provider | One: localhost:20128/v1 |
| Where provider credentials live | Copied into every tool's config | Your DATA_DIR, added once |
| A provider returns 429 | The request fails | Next account, then next combo member |
| Claude, Gemini or Kiro formats | A separate SDK or adapter each | Translated from OpenAI shape |
| Tokens, cost and latency | Scattered across provider consoles | One request log and usage view |
| Plan limits and reset windows | Checked by hand | Quota tracker in the dashboard |
| Several MCP servers | Wired into each client | One MCP gateway with managed keys |
| Source and hosting | Depends on the vendor | MIT, runs on hardware you choose |
Quick start
Three steps to the other side
Install, start, and point any OpenAI-compatible client at one base URL.
$ npm install -g durindoor$ durindoor ✓ dashboard http://localhost:20128/dashboard ✓ api base http://localhost:20128/v1curl http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer YOUR_DURINDOOR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MODEL_ID", "messages": [ {"role": "user", "content": "Reply with one short sentence."} ], "max_tokens": 32 }'
Connect your tools
- Base URL
http://localhost:20128/v1- API key
your DurinDoor API key- Model
model ID, alias, or combo
Other ways through
$ npm install -g durindoor
$ durindoor
Live demo
Walk through the dashboard, no install
The demo runs the real DurinDoor interface against mocked data, so you can click every page before you run it yourself.
Pedo mellon a minno
Speak, friend, and enter.
Install it on your machine in a minute, or walk through the live demo first. The word is on the door.