# How to Use the OmniRoute CLI for Integration: A Complete Developer's Guide

> Integrate OmniRoute LLM routing into your tools and CI pipelines using the OmniRoute CLI. Learn to leverage commands like serve and chat for seamless integration. This guide covers programmatic HTTP and stdio integration.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-27

---

**The OmniRoute CLI provides a unified command-line interface for embedding OmniRoute's LLM routing, combo-routing, and resilience layers into your tooling and CI pipelines through commands like `serve`, `chat`, and `--mcp` for programmatic HTTP and stdio-based integration.**

The diegosouzapw/OmniRoute repository exposes a comprehensive command-line interface designed for developers who need to integrate unified LLM routing capabilities into external applications. Whether spawning a local API server for microservices or executing chat completions directly from shell scripts, the OmniRoute CLI for integration handles environment preparation, process supervision, and standard protocol compatibility automatically.

## CLI Architecture and Fast-Path Initialization

### Version Detection Without Overhead

The CLI implements a fast-path version handler to ensure `omniroute --version` responds instantly without loading heavy dependencies. In `bin/omniroute.mjs` (lines 47-51), the script checks `isVersionFastPath` from `bin/cli/utils/versionFastPath.mjs` before importing Next.js or other large modules. This optimization allows integration scripts to verify installation status quickly without incurring startup penalties.

### Command Registration Structure

The CLI uses the Commander library to build a tree of sub-commands. The `createProgram()` function in `bin/cli/program.mjs` (lines 11-38) initializes the program, while `registerCommands` in `bin/cli/commands/registry.mjs` dynamically loads command modules. Adding custom integration points involves creating a new `*.mjs` file under `bin/cli/commands/` and exporting a `registerX(program)` function.

## Environment Preparation and Security

### Layered Environment Loading

Before executing commands, `bin/omniroute.mjs` invokes `loadEnvFile()` (lines 101-106) to merge configuration from the repository root, current working directory, and custom `DATA_DIR` locations. The CLI also migrates legacy Electron secrets automatically and generates a `STORAGE_ENCRYPTION_KEY` via `shouldProvisionStorageKey()` (lines 200-254) when running write-enabled commands like `serve` or `chat`.

### Storage Encryption Provisioning

The first execution of a write-enabled command creates a `STORAGE_ENCRYPTION_KEY` in `~/.omniroute/.env` via `bin/cli/utils/storageKeyProvision.mjs`, ensuring encrypted SQLite databases remain accessible across upgrades. This guarantees persistent storage decryption across application updates.

## Starting the OmniRoute Server for Integration

### The serve Command

The `omniroute serve` command spawns a Next.js-based API server in a child process with configurable heap sizes based on available RAM. Implemented in `bin/cli/commands/serve.mjs` (lines 99-160, 177-274), the `runServe` function handles TLS validation, port configuration, and process supervision through the `ServerSupervisor` class.

Start the server with a custom port:

```bash
omniroute serve --port 20200 --no-open

```

### Daemon and Tray Modes

For production deployments, run the server as a background daemon:

```bash
omniroute serve --daemon --log

```

The CLI writes a PID file to `~/.omniroute/server.pid` and captures logs. For desktop environments, use `--tray` to enable system-tray supervision, which monitors crashes and automatically restarts the server up to `--max-restarts` while detecting MITM proxy crashes.

## HTTP API Integration

### OpenAI-Compatible Endpoints

Once running, the server exposes standard endpoints at `/v1/chat/completions` and `/v1/responses` through [`src/app/api/v1/chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/chat/completions/route.ts). The default port is **20128**, configurable via `--port` or environment variables (`OMNIROUTE_PORT`, `API_PORT`, `DASHBOARD_PORT`) exported by `onReady` in `serve.mjs` (lines 552-562).

### Making Requests via cURL

Test your integration using standard HTTP clients:

```bash
curl -X POST http://localhost:20128/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
        "model":"gpt-4o-mini",
        "messages":[{"role":"user","content":"Hello"}]
      }'

```

Requests flow through the routing pipeline defined in `open-sse/services/`, including combo selection, provider circuit breakers, and connection cooldowns.

## CLI-Driven Chat for Quick Integration

### The chat Command

For immediate testing without external HTTP clients, use `omniroute chat`. The `runChatCommand` function in `bin/cli/commands/chat.mjs` (lines 32-99) builds JSON payloads, sends them to the local or remote server via `apiFetch` (lines 45-64), and handles streaming responses.

Example with streaming:

```bash
omniroute chat "Summarize the latest release notes" \
  --model gpt-4o-mini \
  --stream

```

The command writes status lines to `stderr` and records conversation history automatically.

## MCP stdio Transport for Tool Integration

### Pipe-Based Communication

For integration scenarios requiring low-overhead stdio communication, invoke `omniroute --mcp`. This flag redirects `console.log` and `console.warn` to `stderr` and starts a JSON-RPC MCP server via `bin/mcp-server.mjs`, enabling tool-to-tool piping without HTTP overhead.

Example usage:

```bash
omniroute --mcp

```

This mode supports the Model Context Protocol for lightweight integration with editors and scriptable tools that communicate over stdin/stdout pipes.

## Programmatic Integration Examples

### Node.js Client Implementation

```javascript
import fetch from 'node-fetch';

async function chat(prompt) {
  const resp = await fetch('http://localhost:20128/v1/chat/completions', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: 'gpt-4o-mini',
      messages: [{ role: 'user', content: prompt }],
    }),
  });

  if (!resp.ok) throw new Error(`❌ ${resp.status} ${resp.statusText}`);
  const data = await resp.json();
  console.log(data.choices[0].message.content);
}

chat('Explain the combo routing strategy');

```

### Background Service Management

Start and verify a background instance:

```bash
omniroute serve --daemon --log
cat ~/.omniroute/server.pid  # Verify PID written by writePidFile()

```

## Summary

- The **OmniRoute CLI** provides fast-path version detection via `isVersionFastPath` in `bin/cli/utils/versionFastPath.mjs` to minimize startup overhead for version checks.
- Environment preparation in `bin/omniroute.mjs` handles layered `.env` loading, legacy secret migration, and automatic `STORAGE_ENCRYPTION_KEY` provisioning via `shouldProvisionStorageKey`.
- The `serve` command in `bin/cli/commands/serve.mjs` manages a child Next.js process with automatic restart supervision, supporting `--daemon` for servers and `--tray` for desktop environments.
- HTTP integration uses OpenAI-compatible endpoints exposed through [`src/app/api/v1/chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/chat/completions/route.ts), accessible via standard HTTP clients or the built-in `chat` command.
- The `--mcp` flag enables JSON-RPC stdio transport via `bin/mcp-server.mjs` for lightweight tool integration without HTTP stack requirements.
- All configuration persists in `.env` files with automatic reloading on server restart, ensuring flexible CI/CD integration.

## Frequently Asked Questions

### How do I check the OmniRoute CLI version without starting the server?

Use `omniroute --version` or `omniroute -V`. The CLI detects this bare version flag in `isVersionFastPath` (located in `bin/cli/utils/versionFastPath.mjs`) and returns the version immediately without importing heavy modules like Next.js, making it ideal for integration scripts that verify installation status.

### What port does OmniRoute use by default and how do I change it?

The default port is **20128**. Change it using the `--port` flag (e.g., `omniroute serve --port 20200`) or by setting the `OMNIROUTE_PORT` environment variable. The `serve` command in `bin/cli/commands/serve.mjs` exports `OMNIROUTE_PORT`, `API_PORT`, and `DASHBOARD_PORT` to the child process environment.

### How does the CLI handle encrypted storage across updates?

The first time you run a write-enabled command like `serve` or `chat`, the CLI checks `shouldProvisionStorageKey()` in `bin/omniroute.mjs` (lines 200-254). If no `STORAGE_ENCRYPTION_KEY` exists in `~/.omniroute/.env`, it generates one via `bin/cli/utils/storageKeyProvision.mjs`, ensuring the SQLite database remains decryptable after application updates.

### Can I integrate OmniRoute into existing MCP (Model Context Protocol) workflows?

Yes. Launch the CLI with the `--mcp` flag to start the JSON-RPC server over stdio via `bin/mcp-server.mjs`. This mode redirects console output to stderr and provides a pipe-based interface for MCP clients, allowing OmniRoute to serve as a routed backend for any MCP-compatible tool without HTTP overhead.