Repository navigation
Headless
Headless mode boots OmniRoute as a plain LLM proxy: the OpenAI-compatible API under /v1/*
keeps working, but the dashboard is switched off and the optional subsystems that only feed
the dashboard (or add opt-in features on top of the proxy) are not started at boot.
Use it for servers, containers and CI boxes where nobody opens the dashboard and you want a lighter, quieter process. Nothing is uninstalled or removed: unset the variable and restart to get the full server back.
Either set the environment variable:
OMNIROUTE_HEADLESS=1 omniroute serveor pass the CLI flag, which sets OMNIROUTE_HEADLESS=1 on the server process for you:
omniroute serve --headless
omniroute serve --headless --port 20128 --daemonAccepted truthy values are 1, true, yes and on (case-insensitive). Any other value,
or an unset variable, keeps the full server. The flag is implemented in
bin/cli/commands/serve.mjs; the single source of truth for the mode is
src/lib/system/headless.ts.
With --headless the CLI does not open a browser and the startup banner prints
Dashboard: disabled (headless). --headless cannot be combined with --tray (the tray menu
exists to open the dashboard).
| Surface | Headless |
|---|---|
/v1/* (chat completions, responses, models, embeddings, …) |
on |
/api/monitoring/health |
on |
/api/auth/* and the API-key / REQUIRE_API_KEY checks |
on |
Every other /api/* route (management API, used by the omniroute CLI) |
on |
| Proxy core at boot: DB, secrets, quota fetchers, settings hydration | on |
| Background proxy work: quota refresh, token auto-refresh, cooldown recovery | on |
| API bridge port, cleanup/VACUUM schedulers, backup schedule | on |
| Memory: configured memory backends + typed-memory decay sweep | on |
Authentication is unchanged: if /v1/* needs an API key on the full server, it needs one in
headless mode too.
Dashboard pages. /dashboard, /dashboard/*, /home and /home/* answer
404 with the JSON body {"error":"dashboard disabled (headless)"}. The gate runs in
src/proxy.ts before the authorization pipeline, so no other route is affected.
Optional boot subsystems. registerNodejs() in src/instrumentation-node.ts skips:
| Subsystem name | What it does on the full server |
|---|---|
free-proxy-sync |
Re-fetches free-proxy source lists on an interval |
cloud-sync |
Cloud / model sync background bootstrap |
embedded-services |
Auto-starts embedded services marked auto-start |
embed-ws-proxy |
WebSocket proxy for embedded service UIs |
conductor-bridge |
Mirrors OmniConductor hub tasks into A2A (opt-in, CONDUCTOR_HUB_URL) |
arena-elo-sync |
Arena ELO leaderboard sync for the Free Provider Rankings page |
radar-sync |
Radar daily feed sync (opt-in) |
pricing-sync |
External pricing data sync (opt-in, PRICING_SYNC_ENABLED) |
openrouter-provider-stats |
Provider directory / popularity enrichment for the dashboard |
models-dev-sync |
models.dev capability sync (opt-in in settings) |
live-dashboard-ws |
Real-time dashboard WebSocket daemon (port 20132) |
Each skip is logged once at startup, for example:
[STARTUP] Headless mode: skipping free-proxy-sync
[STARTUP] Headless mode: skipping cloud-sync
[STARTUP] Headless mode: skipping optional subsystems: embedded-services, embed-ws-proxy, …
# Health — 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:20128/api/monitoring/health
# Models — 200 (add -H "Authorization: Bearer $OMNIROUTE_KEY" when REQUIRE_API_KEY is on)
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:20128/v1/models
# Dashboard — 404 with the headless error body
curl -s -w "\n%{http_code}\n" http://localhost:20128/dashboard
# {"error":"dashboard disabled (headless)"}
# 404-
Set before start. The server process reads
OMNIROUTE_HEADLESSfrom its own environment; switching modes means restarting the server with the variable set or unset. -
Management API stays reachable. Headless mode only closes the dashboard pages. The
/api/*management routes keep their normal authorization tiers, so theomnirouteCLI (and remote mode) keep working. It is not a security boundary — keep usingREQUIRE_API_KEYand a loopback bind (OMNIROUTE_SERVER_HOST) where appropriate. - Route-loaded features still load on demand. MCP, A2A, evals, gamification, webhooks and cloud agents have no boot-time init; they start lazily when their routes are called, in both modes.
-
Memory stays on. Memory is cross-cutting to the request pipeline (
/v1injects and queries it), so the configured memory backends and the typed-memory decay sweep start at boot in headless mode exactly as on the full server. - Code still ships. This mode changes what runs, not what is installed — the package size and the build are identical.
-
ENVIRONMENT.md —
OMNIROUTE_HEADLESSandOMNIROUTE_DISABLE_BACKGROUND_SERVICES(a separate switch that stops background schedulers but keeps the dashboard). -
REMOTE-MODE.md — drive a remote (for example, headless) OmniRoute from
your laptop with the
omnirouteCLI.
OmniRoute · Website · npm · Docker Hub
- Setup Guide
- User Guide
- Features
- Quick Start (Docker)
- Electron Desktop App
- Termux (Android)
- PWA Guide
- MCP Server
- A2A Server
- Agent Protocols
- OpenCode Plugin
- Webhooks
- Cloud Agents
- Skills
- Memory
- Evals
- Gamification
- Guardrails
- Compliance
- Error Sanitization
- Public Credentials
- Route Guard Tiers
- Stealth Guide
- CLI Token Auth