Current version: 0.5.0
Standalone OpenAI-compatible HTTP proxy that bridges local AI sessions (Grok, Claude, Gemini, ChatGPT) via persistent headless browser contexts, plus direct API providers (Anthropic, Google, OpenAI Codex), OpenAI-compatible aggregators (OpenRouter, Perplexity), and local backends (LM Studio, Grok CLI).
No OpenClaw required. Works on any machine with Node.js 24+ and Chromium.
Part of the Conduit ecosystem, powers the conduit-vscode VS Code extension.
conduit-bridge exposes a single local OpenAI-compatible API and routes each request to the right backend by its model id. Backends fall into four families: browser sessions driven by Playwright (Grok/Claude/Gemini/ChatGPT), direct provider APIs (Anthropic, Google, OpenAI Codex, plus the OpenRouter and Perplexity aggregators), and local backends (LM Studio's server and the Grok CLI). Browser sessions are persisted to disk so you only log in once; API providers use a key; local providers need neither.
Your app / VS Code extension
│ OpenAI API (HTTP, 127.0.0.1:31338)
▼
conduit-bridge ──► route by model id
├─ web-* Playwright headless Chromium → Grok / Claude / Gemini / ChatGPT
├─ api-* provider SDK / REST → Anthropic · Google · OpenAI Codex · OpenRouter · Perplexity
├─ lmstudio/* local OpenAI-compatible server (LM Studio, live model discovery)
└─ cli-grok/* local Grok CLI subprocess (--prompt-file headless)
Web providers use browser session cookies (no API key). API providers resolve a key in priority order — config (conduit-bridge config apiKeys.<provider> <key>), then auto-detected credentials from the provider's own CLI tool (~/.claude, ~/.gemini, ~/.codex), then the standard environment variable. Local providers (LM Studio, Grok CLI) need no key. See Usage for setup.
| Model ID | Provider | Description |
|---|---|---|
web-grok/grok-fast |
Grok | Grok Fast |
web-grok/grok-expert |
Grok | Grok Expert |
web-grok/grok-heavy |
Grok | Grok Heavy |
web-grok/grok-auto |
Grok | Grok Auto |
web-claude/claude-fable |
Claude | Claude Fable 5 |
web-claude/claude-opus |
Claude | Claude Opus 5 |
web-claude/claude-sonnet |
Claude | Claude Sonnet 5 |
web-claude/claude-haiku |
Claude | Claude Haiku 4.5 |
web-gemini/gemini-3.6-flash |
Gemini | Gemini 3.6 Flash |
web-gemini/gemini-3.5-flash |
Gemini | Gemini 3.5 Flash |
web-gemini/gemini-3.1-pro |
Gemini | Gemini 3.1 Pro |
web-chatgpt/gpt-5.6-sol |
ChatGPT | GPT-5.6 Sol |
web-chatgpt/gpt-5.6-terra |
ChatGPT | GPT-5.6 Terra |
web-chatgpt/gpt-5.6-luna |
ChatGPT | GPT-5.6 Luna |
| Model ID | Provider | Description |
|---|---|---|
api-claude/claude-fable-5 |
Claude API | Claude Fable 5 |
api-claude/claude-opus-5 |
Claude API | Claude Opus 5 |
api-claude/claude-sonnet-5 |
Claude API | Claude Sonnet 5 |
api-claude/claude-haiku-4-5 |
Claude API | Claude Haiku 4.5 |
api-gemini/gemini-3.6-flash |
Gemini API | Gemini 3.6 Flash |
api-gemini/gemini-3.5-flash |
Gemini API | Gemini 3.5 Flash |
api-gemini/gemini-3.5-flash-lite |
Gemini API | Gemini 3.5 Flash-Lite |
api-gemini/gemini-3.1-flash-lite |
Gemini API | Gemini 3.1 Flash-Lite |
api-gemini/gemini-3.1-pro |
Gemini API | Gemini 3.1 Pro |
api-codex/gpt-5.6-sol |
Codex API | GPT-5.6 Sol |
api-codex/gpt-5.6-terra |
Codex API | GPT-5.6 Terra |
api-codex/gpt-5.6-luna |
Codex API | GPT-5.6 Luna |
api-codex/gpt-5.5 |
Codex API | GPT-5.5 |
api-codex/gpt-5.5-pro |
Codex API | GPT-5.5 Pro |
One API key each; any <prefix>/<model> is accepted (passthrough), so you're never limited to the curated list below. Keys are read from config (conduit-bridge config apiKeys.<provider> <key>) or the corresponding env var.
| Model ID (example) | Provider | Key |
|---|---|---|
api-openrouter/anthropic/claude-opus-5 |
OpenRouter | OPENROUTER_API_KEY |
api-openrouter/openai/gpt-5.6-sol |
OpenRouter | OPENROUTER_API_KEY |
api-openrouter/google/gemini-3.6-flash |
OpenRouter | OPENROUTER_API_KEY |
api-perplexity/sonar-pro |
Perplexity | PERPLEXITY_API_KEY |
api-perplexity/sonar-reasoning-pro |
Perplexity | PERPLEXITY_API_KEY |
api-perplexity/anthropic/claude-opus-5 |
Perplexity | PERPLEXITY_API_KEY |
| Model ID | Provider | Notes |
|---|---|---|
lmstudio/auto |
LM Studio | Uses whichever model is loaded in LM Studio |
lmstudio/<model> |
LM Studio | Any model reported by LM Studio's /v1/models (discovered live; embedding ids filtered). Set LM_STUDIO_URL to override http://127.0.0.1:1234 |
cli-grok/grok-4.5 |
Grok CLI | Local grok binary (x.ai/build). Install + grok login |
cli-grok/grok-4.3 / grok-4 |
Grok CLI | Additional Grok CLI models |
cli-codex/gpt-5.6-sol |
Codex CLI | Local codex from @openai/codex. npm i -g @openai/codex && codex login |
cli-codex/gpt-5.6-terra / luna / gpt-5.5* |
Codex CLI | Other curated Codex CLI models (passthrough: any cli-codex/*) |
cli-claude/claude-opus-5 |
Claude Code CLI | Local claude from @anthropic-ai/claude-code |
cli-claude/claude-sonnet-5 / claude-haiku-4-5 / claude-fable-5 |
Claude Code CLI | Curated Claude Code models (passthrough: any cli-claude/*) |
cli-gemini/gemini-3.6-flash-high |
Gemini CLI | Local agy binary (Antigravity CLI). Install from antigravity.google |
cli-gemini/gemini-3.6-flash-* / 3.5-flash-* / 3.1-pro-* |
Gemini CLI | Effort-tier ids from agy models (passthrough: any cli-gemini/*) |
Coding CLIs must be installed on the machine and on PATH. conduit-bridge shells out to them in headless/print mode; it does not bundle the CLIs as npm dependencies.
The live model list is always available at GET /v1/models.
# From source (conduit-bridge is run from source, not published to npm)
git clone https://github.com/elvatis/conduit-bridge
cd conduit-bridge
npm install
npm run buildnode dist/cli.js start
# or after npm install -g:
conduit-bridge startOptions:
--port=31338 Port to listen on (default: 31338)
--host=127.0.0.1 Host to bind to
--log-level=info Log level: silent | info | debug
--auth-token=<token> Require 'Authorization: Bearer <token>' on /v1/* (see Security)
--no-sandbox=true Launch Chromium with --no-sandbox (off by default; see Security)
conduit-bridge login grok
conduit-bridge login claude
conduit-bridge login gemini
conduit-bridge login chatgptA browser window opens. Log in as you normally would. The session is saved to ~/.conduit/profiles/ and restored automatically on next start.
Direct-API providers use a key instead of a browser login. A key is resolved in priority order: config → the provider's CLI credentials → environment variable (which can come from a .env file).
# 1. Store a key in ~/.conduit/config.json
conduit-bridge config apiKeys.openrouter-api sk-or-v1-...
conduit-bridge config apiKeys.perplexity-api pplx-...
conduit-bridge config apiKeys.claude-api sk-ant-...
conduit-bridge config apiKeys.gemini-api <GOOGLE_AI_API_KEY>
conduit-bridge config apiKeys.codex-api <OPENAI_API_KEY>If you already use the provider's CLI, its credentials are auto-detected (~/.claude/.credentials.json, ~/.gemini/oauth_creds.json, ~/.codex/auth.json). Failing that, the standard env vars are read: ANTHROPIC_API_KEY, GEMINI_API_KEY / GOOGLE_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, PERPLEXITY_API_KEY (and LM_STUDIO_URL).
These variables can be real environment variables or lines in a .env file — loaded from the directory you run the bridge from, then from ~/.conduit/.env. Real environment variables always take precedence. Copy .env.example to .env to get started:
OPENROUTER_API_KEY=sk-or-v1-...
PERPLEXITY_API_KEY=pplx-...- LM Studio — start LM Studio's local server; its loaded models are discovered live and exposed as
lmstudio/*(uselmstudio/autofor whatever is loaded). Point at a non-default host withLM_STUDIO_URL(defaulthttp://127.0.0.1:1234). - Grok CLI — install the
grokCLI and rungrok login; models are exposed ascli-grok/*.
conduit-bridge statusThe proxy implements the OpenAI API:
{ "status": "ok", "service": "conduit-bridge", "version": "0.5.0" }Returns all available models in OpenAI format.
Returns rich provider status:
{
"running": true,
"port": 31338,
"version": "0.5.0",
"uptime": 3600,
"providers": [
{
"name": "grok",
"connected": true,
"hasProfile": true,
"sessionValid": true,
"loginType": "browser",
"session": { "loggedIn": true, "lastVerified": 1750000000000, "status": "active" },
"models": ["web-grok/grok-expert", "web-grok/grok-auto", "..."]
}
]
}loginType is "browser" for web providers and "api-key" for everyone else; API/local providers report session.status: "not_applicable".
Standard OpenAI chat completions. Supports stream: true.
{
"model": "web-grok/grok-3",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": true
}For a web provider (grok, claude, gemini, chatgpt) this opens the headful login browser. For an API or local provider it returns a 400 with setup guidance (use a key / start the local server) instead — there is no browser login.
POST /v1/login/grok
POST /v1/login/claude
POST /v1/login/gemini
POST /v1/login/chatgpt
Closes the browser context for that provider.
conduit-bridge is secure by default and binds to 127.0.0.1 only. The options
below are opt-in and backward compatible: leaving them unset behaves exactly as
before.
- Chromium sandbox stays ON. The OS-level Chromium sandbox is no longer
disabled by default (the old
--no-sandboxdefault was removed). - Site isolation stays ON. The flag that disabled site isolation
(
--disable-features=IsolateOrigins,site-per-process) was removed from the defaults. - CORS is restricted to localhost. The proxy no longer returns a wildcard
Access-Control-Allow-Origin: *. It reflects the requestOriginheader only when the origin is in the allowlist; otherwise no CORS origin is sent. Requests without anOriginheader (curl, server-side OpenAI clients) are unaffected and keep working.
| Option | Config key | CLI / env | Default | Effect |
|---|---|---|---|---|
| Local API auth | authToken |
--auth-token=<token> |
"" (off) |
When set, all /v1/* endpoints require Authorization: Bearer <token> (401 otherwise). /health stays open. |
| CORS allowlist | allowedOrigins |
config file | ["http://localhost","http://127.0.0.1"] |
Origins allowed to receive a reflected CORS header. The server's own host:port loopback origins are always included. |
| Chromium sandbox opt-out | chromiumNoSandbox |
--no-sandbox=true / CONDUIT_NO_SANDBOX=1 |
false |
When true, launches Chromium with --no-sandbox. Only enable for environments that require it (e.g. running as root inside a container). |
# Persist a token in ~/.conduit/config.json
conduit-bridge config authToken my-secret-token
# Or set it per-invocation
conduit-bridge start --auth-token=my-secret-tokenThen call the API with the token:
curl http://127.0.0.1:31338/v1/models \
-H "Authorization: Bearer my-secret-token"Only if your environment genuinely needs it (for example root inside a container):
CONDUIT_NO_SANDBOX=1 conduit-bridge start
# or
conduit-bridge start --no-sandbox=true
# or set "chromiumNoSandbox": true in ~/.conduit/config.jsonimport { BridgeServer, loadConfig } from '@elvatis/conduit-bridge';
const cfg = loadConfig({ port: 31338 });
const server = new BridgeServer(cfg);
await server.start();
// Later:
const status = await server.registry.getStatus();| Path | Description |
|---|---|
~/.conduit/config.json |
Bridge configuration (port, host, apiKeys, security options) |
~/.conduit/profiles/<provider>-profile/ |
Playwright persistent browser profiles (cookies) |
Per-provider session status and expiry are reported live at GET /v1/status (tracked in memory, not persisted to disk).
POST /v1/chat/completions accepts either effort or OpenAI-compatible reasoning_effort:
{
"model": "api-claude/claude-opus-5",
"messages": [{ "role": "user", "content": "Plan a migration" }],
"effort": "high"
}| Level | Notes |
|---|---|
none / minimal / low / medium / high / xhigh / max |
OpenAI ladder; providers with fewer levels map down |
Provider support
| Backend | How effort is applied |
|---|---|
| Claude API | output_config.effort (Claude ladder; none/minimal -> low) |
| Codex API / OpenRouter / Perplexity | reasoning_effort on chat completions |
Claude Code CLI (cli-claude) |
--effort |
Codex CLI (cli-codex) |
-c model_reasoning_effort=... |
Antigravity CLI (cli-gemini / agy) |
--effort low|medium|high |
Grok CLI (cli-grok) |
--reasoning-effort |
| Gemini API SDK | not exposed by current SDK surface (no-op) |
| Web browser providers | not applicable (UI session; no-op) |
| LM Studio | no-op |
- Coding CLI providers: shell out to local CLIs in headless mode
cli-codex/*via@openai/codex(codex exec)cli-claude/*via@anthropic-ai/claude-code(claude -p)cli-gemini/*via Antigravity CLI binaryagy(fallback:gemini/antigravity)- existing
cli-grok/*unchanged
- Model catalog refresh (official docs, 2026-08): GPT-5.6 Sol/Terra/Luna; Claude Fable 5 / Opus 5 / Sonnet 5 / Haiku 4.5; Gemini 3.6 Flash (+ 3.5 Flash-Lite); Grok 4.5 line; OpenRouter/Perplexity curated lists updated
- Reasoning effort: request field
effortorreasoning_effortwired through Claude API, Codex/OpenRouter/Perplexity, and coding CLIs - Node engines floor:
>=24.0.0(CI +.nvmrc);openaibumped to ^7.4.0 - AAHP exact-pin 3.9.2; supply-chain-guard stays on floating
@v5with Dependabot ignore - Secret-scan gate (
npm run scan:secrets, CI workflow) + hardened credential gitignores - Login/logout routes cover all CLI provider names with install guidance
- Docs:
docs/RELEASING.mdagent release process; rootCHANGELOG.md
- (none)
- Web providers now capture responses via network-layer interception (Playwright
page.on('response')) as the primary path, replacing brittle DOM-selector polling. DOM polling is kept as an automatic fallback so behaviour never regresses. Newsrc/providers/interception.ts+BaseProvider.startNetworkCapture, per-provider stream parsers, and 15 unit tests. (#62, closes #35)- The Claude/Grok/Gemini backend endpoint patterns are still being validated against the live sites; until then those providers fall back to DOM polling.
- Toolchain/dependency updates: TypeScript 6 → 7, openai 6.48,
@anthropic-ai/sdk0.111,@types/node26.1.1, vitest 4.1.10,actions/setup-node7 - Docs: refreshed the README for the full provider + security surface (How It Works, API/local provider setup,
/v1/status); added the supply-chain-guard badge - Tests: run co-located
src/**/*.test.ts(wastest/**only)
- Add four new providers, ported from the
openclaw-cli-bridge-elvatisproject:- OpenRouter (
api-openrouter/*) — OpenAI-compatible aggregator (Anthropic, OpenAI, Google, xAI, DeepSeek, Meta, …) behindOPENROUTER_API_KEY - Perplexity (
api-perplexity/*) — OpenAI-compatible; nativesonar*web-search models plus proxied upstreams, behindPERPLEXITY_API_KEY - LM Studio (
lmstudio/*) — local OpenAI-compatible server with live model discovery; no key. Override the endpoint withLM_STUDIO_URL - Grok CLI (
cli-grok/*) — drives the localgrokCLI in--prompt-fileheadless mode; requires the CLI installed
- OpenRouter (
- Passthrough routing: any
api-openrouter/…,api-perplexity/…,lmstudio/…, orcli-grok/…model id routes to its provider even when not in the curated/v1/modelslist (via a new optionalownsModel()hook) - Security hardening (secure-by-default): the Chromium sandbox now stays ON (opt out via
chromiumNoSandboxorCONDUIT_NO_SANDBOX=1), site isolation is kept on, wildcard CORS is replaced with an origin allowlist (allowedOrigins), and optional bearer-token auth guards/v1/*(authToken) - Per-provider session expiry tracking surfaced through
/v1/status(session+loginType) - Added the project's first vitest unit-test suite; stopped the failing npm auto-publish and reconciled the version drift (README/DASHBOARD/package.json)
- No new runtime dependencies for the new providers (reuses the
openaiSDK,fetch, andnode:child_process)
- Refresh the non-Claude providers to their mid-2026 lineups (model IDs verified against official vendor docs on 2026-07-01):
- Gemini API: add
gemini-3.5-flash(GA) andgemini-3.1-flash-lite; drop the fabricatedgemini-3.0-flash/gemini-3.0-thinkingIDs (not real Gemini API models); pointgemini-3.1-proatgemini-3.1-pro-preview - OpenAI/Codex API: add
gpt-5.5andgpt-5.5-pro(GA); dropcodex-mini(removed from the API 2026-02-12),o3, and the-thinking/-instantnames that are ChatGPT effort labels rather than API model IDs - Web labels refreshed: Grok Fast/Expert/Heavy/Auto, Gemini 3.5 Flash / 3.5 Pro, ChatGPT GPT-5.5 Instant/Thinking/Pro
- Gemini API: add
- Web selection remains advisory (the browser providers do not switch the model in the UI)
- Add Claude Fable 5 (
api-claude/claude-fable-5) and Claude Opus 4.7 (api-claude/claude-opus-4-7) to the Claude API provider
- Add Claude Opus 4.8 (
api-claude/claude-opus-4-8) and Claude Sonnet 5 (api-claude/claude-sonnet-5) to the Claude API provider - Refresh the web Claude labels to the current claude.ai tiers (Opus 4.8, Sonnet 5)
- Fix stale Claude API model strings:
claude-sonnet-4-6,claude-opus-4-6, andclaude-sonnet-4-5were mapped to non-existent date-suffixed snapshots (would 404); now use the bare aliases
- Bump @anthropic-ai/sdk to ^0.95.1
- Bump openai to ^6.37.0
- Bump vitest to ^4.1.5 and @types/node to ^25.6.2
- Closes Dependabot PRs #19, #20, #21, #22
- Bump @anthropic-ai/sdk to ^0.94.0
- Bump typescript to ^6.0.2 (typecheck still clean, no API changes)
- Closes Dependabot PRs #8 and #15
- Security: bump @anthropic-ai/sdk to ^0.91.1 (GHSA-p7fg-763f-g4gf, insecure default file permissions in BetaLocalFilesystemMemoryTool)
- Security: bump vite (transitive via vitest) to 8.0.5 (GHSA-4w7w-66w2-5vf9 path traversal in .map handling)
- Bump playwright to ^1.59.1, esbuild to ^0.28.0, @types/node to ^25.6.0
- Added direct API providers:
claude-api,gemini-api,codex-api - Refreshed web model lineup: Grok Expert/Fast/Heavy/4.20 Beta, Claude 4.5/4.6, Gemini 3.x, GPT-5.x
- Switched to
tsc --noEmittypecheck plus esbuild bundling fordist/ - Provider keepalive plus session expiry tracking
- Hardened URL parsing in proxy router
- Initial release
- HTTP proxy server with OpenAI-compatible API
- 4 web providers: Grok, Claude, Gemini, ChatGPT (15 models total)
- Persistent browser profiles with automatic session restore
- CLI:
conduit-bridge start|status|login|config - Library API for embedding in other tools (conduit-vscode)