📖 Setup Guide — OmniRoute
Complete setup reference for OmniRoute. For the quick version, see the Quick Start in README.
Table of Contents
Section titled “Table of Contents”- Install Methods
- CLI Tool Configuration
- Protocol Setup (MCP + A2A)
- Timeout Configuration
- Split-Port Mode
- Void Linux (xbps-src)
- Uninstalling
Install Methods
Section titled “Install Methods”npm (recommended)
Section titled “npm (recommended)”npm install -g omnirouteomnirouteDashboard opens at http://localhost:20128 and API base URL is http://localhost:20128/v1.
pnpm add -g omniroute@latest --allow-build=better-sqlite3 --allow-build=@swc/coreomniroutepnpm users: the
--allow-buildflag is required to enable native build scripts forbetter-sqlite3and@swc/core. Thepnpm approve-builds -gcommand is not supported for global installs on pnpm v11.
Arch Linux (AUR)
Section titled “Arch Linux (AUR)”yay -S omniroute-binsystemctl --user enable --now omniroute.serviceThe AUR package installs OmniRoute and provides a systemd user service.
From Source
Section titled “From Source”npm installPORT=20128 DASHBOARD_PORT=20129 NEXT_PUBLIC_BASE_URL=http://localhost:20129 npm run devWindows note: By default, OmniRoute uses
%APPDATA%\omniroutewhen the legacy%USERPROFILE%\.omniroutedirectory is not present. SetDATA_DIRto choose a different data-directory location.
Note:
npm installauto-generates.envfrom.env.exampleon first run. Subsequent installs will not overwrite an existing.env, so customizations are preserved. To re-seed, delete.envbefore re-running.
Docker
Section titled “Docker”See the Docker Guide for complete Docker setup including Compose profiles and Caddy HTTPS.
Desktop App (Electron)
Section titled “Desktop App (Electron)”OmniRoute ships a desktop wrapper built on Electron 41 + electron-builder 26.10. Available scripts (workspace root):
npm run electron:dev # Run desktop with hot-reloadnpm 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 buildReleases 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).
Headless server (CI/automation)
Section titled “Headless server (CI/automation)”For unattended setups (Docker, Kubernetes, CI), use:
omniroute setup --non-interactiveomniroute providers test-batchCombined with env vars (INITIAL_PASSWORD, OMNIROUTE_WS_BRIDGE_SECRET, etc.), this lets you spin up an OmniRoute instance fully scriptable.
CLI Options
Section titled “CLI Options”| 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:
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-providerRun local diagnostics without opening the dashboard:
omniroute doctoromniroute doctor --jsonomniroute doctor --no-livenessManage providers from SSH or scripts without opening the dashboard:
omniroute providers availableomniroute providers available --search openaiomniroute providers available --category api-keyomniroute providers listomniroute providers test <id-or-name>omniroute providers test-allomniroute providers validateCLI Tool Configuration
Section titled “CLI Tool Configuration”1) Connect Providers and Create API Key
Section titled “1) Connect Providers and Create API Key”- Open Dashboard →
Providersand connect at least one provider (OAuth or API key). - Open Dashboard →
Endpointsand create an API key. - (Optional) Open Dashboard →
Combosand set your fallback chain.
2) Point Your Coding Tool
Section titled “2) Point Your Coding Tool”Base URL: http://localhost:20128/v1API 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/modelsChat URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/chat/completionsOllama Tags URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/api/tagsWorks with Claude Code, Codex CLI, Cursor, Cline, OpenClaw, OpenCode, and OpenAI-compatible SDKs.
Auto-configure with setup-*
Section titled “Auto-configure with setup-*”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:
omniroute setup-codex # ~/.codex/<name>.config.toml profilesomniroute setup-claude # ~/.claude/profiles/<name>/settings.jsonomniroute setup-opencode # ~/.config/opencode/opencode.json (openai-compatible)omniroute setup-cline # Cline CLI + VS Code extension settingsomniroute setup-kilo # Kilo Codeomniroute setup-continue # ~/.continue/config.yaml (Continue / cn)omniroute setup-cursor # prints Cursor's in-app stepsomniroute setup-roo # Roo Code import + autoImport pointeromniroute setup-crush # ~/.config/crush/crush.jsonomniroute setup-goose # ~/.config/goose/config.yamlomniroute setup-aider # ~/.aider.conf.ymlomniroute setup-qwen # ~/.qwen/settings.json + ~/.qwen/.envEach 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.
Protocol Setup (MCP + A2A)
Section titled “Protocol Setup (MCP + A2A)”MCP Setup (Model Context Protocol)
Section titled “MCP Setup (Model Context Protocol)”Start MCP transport in stdio mode:
omniroute --mcpRecommended validation flow:
# 1. Start MCP serveromniroute --mcp
# 2. From your MCP client, call:omniroute_get_health # Should return system healthomniroute_list_combos # Should return active combos
# 3. Or run the full E2E suite:npm run test:protocols:e2eMCP Client Configuration
Section titled “MCP Client Configuration”Claude Code:
claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp/streamCursor / 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.
A2A Setup (Agent-to-Agent Protocol)
Section titled “A2A Setup (Agent-to-Agent Protocol)”Verify the Agent Card:
curl http://localhost:20128/.well-known/agent.jsonSend a task:
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.
Timeout Configuration
Section titled “Timeout Configuration”Basic Timeouts
Section titled “Basic Timeouts”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.
Provider-Specific Notes
Section titled “Provider-Specific Notes”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.
Advanced Timeout Overrides
Section titled “Advanced Timeout Overrides”| 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_MSonly 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).
Reverse Proxy Compatibility
Section titled “Reverse Proxy Compatibility”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.
Split-Port Mode
Section titled “Split-Port Mode”Run API and Dashboard on separate ports for advanced scenarios (reverse proxy, container networking):
PORT=20128 DASHBOARD_PORT=20129 omniroute# Dashboard: http://localhost:20129Void Linux (xbps-src) Template
Section titled “Void Linux (xbps-src) Template”For Void Linux users, you can build a native package using xbps-src. Save this block as srcpkgs/omniroute/template:
# Template file for 'omniroute'pkgname=omnirouteversion=3.8.0revision=1hostmakedepends="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.gzchecksum=PLACEHOLDER_REGENERATE_PER_RELEASEsystem_accounts="_omniroute"omniroute_homedir="/var/lib/omniroute"export NODE_ENV=productionexport npm_config_engine_strict=falseexport npm_config_loglevel=errorexport npm_config_fund=falseexport 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/shexport 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}Uninstalling
Section titled “Uninstalling”| 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.
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.

- 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.