Skip to content
OmniRoute source

📖 Setup Guide — OmniRoute

Complete setup reference for OmniRoute. For the quick version, see the Quick Start in README.


Terminal window
npm install -g omniroute
omniroute

Dashboard opens at http://localhost:20128 and API base URL is http://localhost:20128/v1.

Terminal window
pnpm add -g omniroute@latest --allow-build=better-sqlite3 --allow-build=@swc/core
omniroute

pnpm users: the --allow-build flag is required to enable native build scripts for better-sqlite3 and @swc/core. The pnpm approve-builds -g command is not supported for global installs on pnpm v11.

Terminal window
yay -S omniroute-bin
systemctl --user enable --now omniroute.service

The AUR package installs OmniRoute and provides a systemd user service.

Terminal window
npm install
PORT=20128 DASHBOARD_PORT=20129 NEXT_PUBLIC_BASE_URL=http://localhost:20129 npm run dev

Windows note: By default, OmniRoute uses %APPDATA%\omniroute when the legacy %USERPROFILE%\.omniroute directory is not present. Set DATA_DIR to choose a different data-directory location.

Note: npm install auto-generates .env from .env.example on first run. Subsequent installs will not overwrite an existing .env, so customizations are preserved. To re-seed, delete .env before re-running.

See the Docker Guide for complete Docker setup including Compose profiles and Caddy HTTPS.

OmniRoute ships a desktop wrapper built on Electron 41 + electron-builder 26.10. Available scripts (workspace root):

Terminal window
npm run electron:dev # Run desktop with hot-reload
npm run electron:build # Build for current OS (auto-detected)
npm run electron:build:win # Windows installer (NSIS + portable)
npm run electron:build:mac # macOS (dmg + zip, arm64+x64)
npm run electron:build:linux # Linux (AppImage + deb + rpm)
npm run electron:smoke:packaged # Smoke-test packaged build

Releases of the desktop installers are attached to GitHub Releases. For the full Electron deep-dive (signing, IPC bridge, distros), see ELECTRON_GUIDE.md (criado em fase posterior).

For unattended setups (Docker, Kubernetes, CI), use:

Terminal window
omniroute setup --non-interactive
omniroute providers test-batch

Combined with env vars (INITIAL_PASSWORD, OMNIROUTE_WS_BRIDGE_SECRET, etc.), this lets you spin up an OmniRoute instance fully scriptable.

Command Description
omniroute Start server (PORT=20128, API and dashboard on same port)
omniroute setup Guided CLI onboarding for password and first provider
omniroute doctor Run local health checks without starting the server
omniroute providers Discover, list, validate, and test providers from CLI
omniroute config CLI tool configuration — list, get, set, validate configs
omniroute status Offline status dashboard — version, DB, tools, config
omniroute logs Stream usage logs from the API (supports --follow)
omniroute update Check for or apply OmniRoute updates
omniroute provider Manage provider connections — add, list, remove, test, default
omniroute --port 3000 Set canonical/API port to 3000
omniroute --mcp Start MCP server (stdio transport)
omniroute --no-open Don’t auto-open browser
omniroute --help Show help

Headless setup can be scripted with flags or environment variables:

Terminal window
omniroute setup --non-interactive --password "$OMNIROUTE_PASSWORD"
omniroute setup --non-interactive --add-provider --provider openai --api-key "$OPENAI_API_KEY"
omniroute setup --non-interactive --add-provider --provider openai --api-key "$OPENAI_API_KEY" --test-provider

Run local diagnostics without opening the dashboard:

Terminal window
omniroute doctor
omniroute doctor --json
omniroute doctor --no-liveness

Manage providers from SSH or scripts without opening the dashboard:

Terminal window
omniroute providers available
omniroute providers available --search openai
omniroute providers available --category api-key
omniroute providers list
omniroute providers test <id-or-name>
omniroute providers test-all
omniroute providers validate

  1. Open Dashboard → Providers and connect at least one provider (OAuth or API key).
  2. Open Dashboard → Endpoints and create an API key.
  3. (Optional) Open Dashboard → Combos and set your fallback chain.
Base URL: http://localhost:20128/v1
API Key: [copy from Endpoint page]
Model: if/qwen3.8-max-preview (or any provider/model prefix)

If your editor cannot send Authorization: Bearer ..., use the tokenized compatibility base instead:

Base URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/
Models URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/models
Chat URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/chat/completions
Ollama Tags URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/api/tags

Works with Claude Code, Codex CLI, Cursor, Cline, OpenClaw, OpenCode, and OpenAI-compatible SDKs.

Instead of pasting the base URL and key by hand, let OmniRoute write each tool’s own config from the live model catalog. One command per tool:

Terminal window
omniroute setup-codex # ~/.codex/<name>.config.toml profiles
omniroute setup-claude # ~/.claude/profiles/<name>/settings.json
omniroute setup-opencode # ~/.config/opencode/opencode.json (openai-compatible)
omniroute setup-cline # Cline CLI + VS Code extension settings
omniroute setup-kilo # Kilo Code
omniroute setup-continue # ~/.continue/config.yaml (Continue / cn)
omniroute setup-cursor # prints Cursor's in-app steps
omniroute setup-roo # Roo Code import + autoImport pointer
omniroute setup-crush # ~/.config/crush/crush.json
omniroute setup-goose # ~/.config/goose/config.yaml
omniroute setup-aider # ~/.aider.conf.yml
omniroute setup-qwen # ~/.qwen/settings.json + ~/.qwen/.env

Each accepts --remote <url> --api-key <key> to configure a local tool against a remote OmniRoute, plus --dry-run to preview. To launch a CLI with the right env injected and no config written at all, use the generic launcher omniroute run <target> (claude, codex, aider, goose, opencode, qwen, gemini); the legacy per-tool launchers omniroute launch (Claude Code) and omniroute launch-codex (Codex) remain available.

For the full table (what each command writes, every flag, local vs remote, base-URL /v1 conventions), see CLI Integrations.

For detailed per-tool configuration (Claude Code, Codex CLI, Cursor, Cline, OpenClaw, Kilo Code, Copilot, and more), see the dedicated CLI Tools Guide.


Start MCP transport in stdio mode:

Terminal window
omniroute --mcp

Recommended validation flow:

Terminal window
# 1. Start MCP server
omniroute --mcp
# 2. From your MCP client, call:
omniroute_get_health # Should return system health
omniroute_list_combos # Should return active combos
# 3. Or run the full E2E suite:
npm run test:protocols:e2e

Claude Code:

Terminal window
claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp/stream

Cursor / Cline:

Add to your MCP settings:

{
"mcpServers": {
"omniroute": {
"command": "omniroute",
"args": ["--mcp"],
"env": {}
}
}
}

Full MCP documentation: MCP Server README — 110 tools, IDE configs, Python/TS/Go clients.

Verify the Agent Card:

Terminal window
curl http://localhost:20128/.well-known/agent.json

Send a task:

Terminal window
curl -X POST http://localhost:20128/a2a \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":"quickstart","method":"message/send","params":{"skill":"quota-management","messages":[{"role":"user","content":"Give me a short quota summary."}]}}'

Full A2A documentation: A2A Server README — JSON-RPC 2.0, skills, streaming, task lifecycle.


For most deployments, you only need these two variables:

Variable Default Purpose
REQUEST_TIMEOUT_MS 600000 Shared baseline for upstream response-start timeout, hidden Undici timeouts, TLS fingerprint requests, and API bridge request/proxy timeouts
STREAM_IDLE_TIMEOUT_MS inherits REQUEST_TIMEOUT_MS Maximum gap between streaming chunks before OmniRoute aborts the SSE stream

Backward compatibility is preserved: existing FETCH_TIMEOUT_MS, API_BRIDGE_PROXY_TIMEOUT_MS, and other per-layer timeout vars still work and override the shared baseline.

For Claude Code-compatible upstreams (anthropic-compatible-cc-*), OmniRoute derives the outbound X-Stainless-Timeout header from the resolved fetch timeout so provider-side read timeouts stay aligned with your env configuration.

For third-party Claude Code-compatible reverse proxies, OmniRoute keeps the default anthropic-beta set conservative and, when Client Cache Control is left on Auto, only forwards client-provided cache_control markers. Enable the per-connection “Enable redact-thinking beta” toggle only when the upstream specifically requires redacted Claude thinking streams.

Variable Default Purpose
FETCH_TIMEOUT_MS inherits REQUEST_TIMEOUT_MS Upstream response-start timeout used until response headers arrive
FETCH_HEADERS_TIMEOUT_MS inherits FETCH_TIMEOUT_MS Undici time limit for receiving upstream response headers
FETCH_BODY_TIMEOUT_MS inherits FETCH_TIMEOUT_MS Undici time limit between upstream body chunks (0 disables it)
FETCH_CONNECT_TIMEOUT_MS 30000 Undici TCP connect timeout
FETCH_KEEPALIVE_TIMEOUT_MS 4000 Undici idle keep-alive socket timeout
TLS_CLIENT_TIMEOUT_MS inherits FETCH_TIMEOUT_MS Timeout for TLS fingerprint requests made through wreq-js
API_BRIDGE_PROXY_TIMEOUT_MS inherits REQUEST_TIMEOUT_MS or 600000 Timeout for /v1 proxy forwarding from API port to dashboard port
API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS max(API_BRIDGE_PROXY_TIMEOUT_MS, 300000) Incoming request timeout on the API bridge server
API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS 60000 Incoming header timeout on the API bridge server
API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS 5000 Keep-alive timeout on the API bridge server
API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS 0 Socket inactivity timeout on the API bridge server (0 disables it)

Note: For streaming requests, FETCH_TIMEOUT_MS only covers connection setup / waiting for the first upstream response. Once the stream is active, OmniRoute will only abort on an actual stall (STREAM_IDLE_TIMEOUT_MS) or Undici body inactivity (FETCH_BODY_TIMEOUT_MS).

If you run OmniRoute behind Nginx, Caddy, Cloudflare, or another reverse proxy, make sure the proxy timeouts are also higher than your OmniRoute stream/fetch timeouts.


Run API and Dashboard on separate ports for advanced scenarios (reverse proxy, container networking):

20128/v1
PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129

For Void Linux users, you can build a native package using xbps-src. Save this block as srcpkgs/omniroute/template:

Terminal window
# Template file for 'omniroute'
pkgname=omniroute
version=3.8.0
revision=1
hostmakedepends="nodejs python3 make"
depends="openssl"
short_desc="Universal AI gateway with smart routing for multiple LLM providers"
maintainer="zenobit <zenobit@disroot.org>"
license="MIT"
homepage="https://github.com/diegosouzapw/OmniRoute"
distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
# Regenerate the checksum for each release with:
# curl -L -o /tmp/omniroute.tar.gz "https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz" && sha256sum /tmp/omniroute.tar.gz
checksum=PLACEHOLDER_REGENERATE_PER_RELEASE
system_accounts="_omniroute"
omniroute_homedir="/var/lib/omniroute"
export NODE_ENV=production
export npm_config_engine_strict=false
export npm_config_loglevel=error
export npm_config_fund=false
export npm_config_audit=false
do_build() {
local _gyp_arch
case "$XBPS_TARGET_MACHINE" in
aarch64*) _gyp_arch=arm64 ;;
armv7*|armv6*) _gyp_arch=arm ;;
i686*) _gyp_arch=ia32 ;;
*) _gyp_arch=x64 ;;
esac
NODE_ENV=development npm ci --ignore-scripts
npm run build
cp -r .next/static .next/standalone/.next/static
[ -d public ] && cp -r public .next/standalone/public || true
local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
(cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
mkdir -p "$_bs3_release"
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
rm -rf .next/standalone/node_modules/@img
for _mod in pino-abstract-transport split2 process-warning; do
cp -r "node_modules/$_mod" .next/standalone/node_modules/
done
}
do_check() {
npm run test:unit
}
do_install() {
vmkdir usr/lib/omniroute/.next
vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
for _d in \
.next/standalone/.next/server/app/dashboard \
.next/standalone/.next/server/app/dashboard/settings \
.next/standalone/.next/server/app/dashboard/providers; do
touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
done
cat > "${WRKDIR}/omniroute" <<'EOF'
#!/bin/sh
export PORT="${PORT:-20128}"
export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}"
mkdir -p "${DATA_DIR}"
exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
EOF
vbin "${WRKDIR}/omniroute"
}
post_install() {
vlicense LICENSE
}

Command Action
npm run uninstall Removes the system app but keeps your DB and configurations in ~/.omniroute.
npm run uninstall:full Removes the app AND permanently erases all configurations, keys, and databases.

For detailed uninstall instructions across all methods, see UNINSTALL.md.


OmniRoute source repository (a58000c7685f)

HagiCode

HagiCode is an agentic coding workspace: structured workflows, multi-agent execution, and Hero Dungeon views turn ideas into shipped software.

Turn ideas into polished, usable software with a smarter, faster, and more enjoyable agentic coding workflow.

HagiCode light theme main interface screenshot
  • SmartStructured workflows turn intent into an executable path from idea to shipped change.
  • EfficientMulti-agent workflows keep research, implementation, and review moving in parallel.
  • FunHero Dungeon interfaces make long coding sessions visual, collaborative, and rewarding.
Visit HagiCode