Skip to main content

Omnitron

Omnitron is opt-in. Titan apps run perfectly well without it as plain Node processes — see Titan vs Omnitron for the precise boundary. This page describes what you gain by adding the Omnitron supervisor on top.

Omnitron is the supervisor, control plane, and operator surface for Titan applications. One long-running daemon manages many processes across many apps across many projects, exposes a typed RPC plane for inspection, ships a CLI and a web console, and provisions the infrastructure your apps need.

It's itself a Titan app — supervising other Titan apps. Built on the same primitives the apps it supervises use.

pnpm add -g @omnitron-dev/omnitron
omnitron up # start daemon + all configured apps
omnitron status # see what's running
omnitron logs --grep error # tail filtered logs
omnitron webapp open # open the web console

What you get

LayerResponsibility
CLIOne binary (omnitron) with 13 command groups covering every operator task — start/stop/status/logs/scale/secrets/backup/deploy/cluster/k8s/etc.
DaemonLong-running supervisor that owns the process tree, exposes a typed Netron RPC surface, and persists state under ~/.omnitron/
OrchestratorPer-app launch pipeline: TS compile / module load / fork process / wire DI / start lifecycle / watch files in dev
Process treeOne OS process per IProcessEntry you declare; ≥ 1 instances per process; auto-restart with exponential backoff
ServicesNineteen built-in RPC services (auth, deploy, fleet, secrets, k8s, …) exposed from the daemon
WebappReact + Vite single-page console — same RPC surface; lives at apps/omnitron/webapp/
InfrastructureProvisions Postgres / Redis / S3-compatible / custom containers via Docker (dev) or bare-metal hooks (prod)
MCPBuilt-in Model Context Protocol surface — let agents (IDE assistants, CI bots) read state and trigger operations

When you reach for Omnitron

  • You have ≥ 2 Titan apps and want one place to start, watch, inspect, and shut them down together.
  • You need a typed control plane, not bash scripts. Every operator action goes through Netron RPC with auth, RBAC, and audit.
  • You want dev / staging / prod parity with declarative infra — the same omnitron.config.ts boots Docker locally and bare-metal remote, with secrets resolved per environment.
  • You operate a fleet — multiple nodes, leader election, remote daemons addressed by alias, cross-node health and metrics.
  • You want the console UI for freeomnitron webapp open serves the React console talking to the same daemon.

If you only ever run one Titan app on one machine, node my-app.js may be enough. Omnitron starts to pay back at two apps or two machines.

The mental model

The daemon is the only thing always running. Apps come and go; the daemon stays. CLI invocations are short-lived RPC clients talking to the daemon — they exit immediately after the RPC returns.

Filesystem layout

Omnitron owns a single directory:

~/.omnitron/
├── daemon.sock # Unix socket for the management plane
├── daemon.pid # Daemon PID file
├── state.json # Persisted app state (last-known status)
├── secrets.enc # Encrypted secret store (file provider)
└── logs/
├── daemon.log
├── api.log
├── api.log.1.gz
└── ...

By default everything else is project-local — the daemon never writes outside ~/.omnitron/ unless you point it at custom paths.

Default endpoints

PlaneEndpointPurpose
Managementunix://~/.omnitron/daemon.sock (mode 0o600, owner-only)CLI ↔ daemon — OmnitronDaemon service + 19 others
Public TCPtcp://0.0.0.0:9700 (opt-in)Remote daemons + fleet operations
Web/HTTPhttp://0.0.0.0:9800 (opt-in)Webapp + REST gateway

The Unix socket is the trust boundary — owner-only file permissions make local CLI calls implicit-auth. TCP and HTTP require JWT.

A minimal omnitron.config.ts

The single configuration file at the repo root:

import { defineEcosystem } from '@omnitron-dev/omnitron';
import { fileURLToPath } from 'node:url';
import path from 'node:path';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default defineEcosystem({
apps: [
{
name: 'api',
bootstrap: path.join(__dirname, 'apps/api/dist/bootstrap.js'),
cwd: path.join(__dirname, 'apps/api'),
env: { NODE_ENV: 'production' },
watch: { enabled: true, paths: ['src/**/*.ts'] },
},
{
name: 'worker',
bootstrap: path.join(__dirname, 'apps/worker/dist/bootstrap.js'),
cwd: path.join(__dirname, 'apps/worker'),
},
],
supervision: {
strategy: 'one_for_one',
maxRestarts: 5,
window: 60_000,
backoff: { type: 'exponential', initial: 1_000, max: 30_000, factor: 2 },
},
});

Each app's bootstrap.ts exports a defineSystem(...) that declares the processes (one OS process per IProcessEntry).

How an app launches

Each IProcessEntry declared in defineSystem(...) becomes exactly one fork (or a pool when instances > 1). The child imports only that module's file — no full bootstrap re-load — so dependencies stay process-isolated.

Multi-project / multi-stack

Omnitron groups apps into projects and projects into stacks:

project: monorepo-A
├── stack: dev → apps: api, worker
├── stack: staging → apps: api, worker, batch
└── stack: prod → apps: api, worker, batch, scheduler

project: monorepo-B
└── stack: prod → apps: gateway, events

Stack-aware commands (omnitron stack status <project> <stack>) operate on the named subset. Use stacks to keep development / staging / production boots side-by-side on one daemon.

Built-in observability

Every supervised process gets, for free:

SignalWhere
Structured logs (pino JSON)~/.omnitron/logs/{app}.log with size-based rotation
Per-process metricsaggregated by daemon, exposed via RPC + Prometheus text
Health probesLiveCheck / Ready from titan-health, surfaced by daemon
Crash trackingRestart count, last error, backoff state
Distributed tracesOTel-compatible via the telemetry transport

Both the CLI and webapp read these through the daemon — there's no separate metrics agent to deploy.

Webapp (Omnitron Console)

The console is a React + Vite SPA that lives at apps/omnitron/webapp/ and talks to the daemon via @omnitron-dev/netron-browser. It gives you:

  • Project + stack view with per-app status cards
  • Live log streams with filtering
  • Metric charts (CPU / RSS / event-loop lag / RPC latency)
  • Health probes and restart history
  • Infrastructure inventory (Docker containers)
  • Secret editor (against the daemon's encrypted store)
  • Fleet view across remote daemons

Launch via omnitron webapp open — runs Vite dev server with HMR, opens the browser.

→ Full webapp reference: console.

Compatibility

ComponentRequirement
Node.js22.x or 23.x (test matrix runs both)
OSmacOS, Linux. Windows works for CLI + non-supervisor commands; daemon assumes Unix sockets
DockerRequired for infra commands (provisioning Postgres / Redis / etc.)
Bun / DenoApps may run on Bun/Deno individually, but the daemon expects Node

Where to go next

  • Architecture deep-dive: Architecture — every component, every plane, every data flow.
  • CLI reference: CLI — every command, every flag.
  • Daemon internals: Daemon — PID, state-store, scheduler, lifecycle.
  • Orchestrator: Orchestrator — bootstrap, file watcher, dependency resolver.
  • RPC services: Services reference — all 19 services and their methods.
  • Console UI: Console.