Skip to content

Quickstart

Install OmniLoop, bring up the dashboard, and drag sliders that control a running process — in under 5 minutes.

Terminal window
pip install omniloop

Pull in only the framework extras you need:

Terminal window
pip install omniloop[sb3] # Stable-Baselines3
pip install omniloop[tensorboard] # TensorBoard mirror
pip install omniloop[rerun] # Rerun sink
pip install omniloop[all-integrations] # everything
  1. Start the visualizer — one command replaces the old two-terminal dance:

    Terminal window
    omniloop up

    This launches the FastAPI telemetry server on :8000 and the Vite dashboard on :5173.

  2. Run a target loop — in a second terminal, start the demo:

    Terminal window
    python examples/mock_rl_training.py
  3. Open the dashboard — navigate to http://localhost:5173 in your browser.

The dashboard’s Interactive State Matrix shows sliders for every tunable parameter. Drag learning_rate — you’ll see the mock training loop’s reward_mean react in real time.

That’s it. The loop is running, and you’re editing its live state without restarting it.

┌──────────────┐ shared memory ┌──────────────┐ websocket ┌──────────────┐
│ Your Loop │ ◄──────────────────── │ OmniLoop │ ◄───────────────► │ Dashboard │
│ (Python) │ telemetry + commands │ Server │ telemetry + │ (React) │
│ │ ────────────────────► │ (FastAPI) │ mutations │ │
└──────────────┘ └──────────────┘ └──────────────┘
  1. Your loop registers variables and publishes telemetry through shared memory (Rust IPC, no sockets in the hot path).
  2. The server polls the shared-memory channel and rebroadcasts over a WebSocket.
  3. The dashboard renders the state and sends mutation commands back.
  4. Mutations arrive in the loop’s next tick() / wait_if_halted() call — applied instantly.

The fastest path is TrainingLoop — it derives the dashboard schema from your existing config dataclass:

from omniloop import TrainingLoop
loop = TrainingLoop.from_dataclass(
cfg.ppo,
tunable=["learning_rate", "entropy_coef", "clip_param"],
bind={"learning_rate": optimizer},
journal="run.omni",
)
for it in range(num_iterations):
with loop.tick():
train_one_iteration(...)
loop.log(reward_mean=r, policy_loss=pl)

If your framework already has a loop you can’t restructure, use a framework adapter instead:

Framework Integration
Stable-Baselines3 OmniLoopCallback
Isaac Lab (rsl_rl) instrument_rsl_rl()
TensorBoard OmniLoopSummaryWriter
ROS 2 OmniLoopRosBridge
MuJoCo Built-in MujocoAdapter
Rerun / MCAP RerunSink + mcap_to_journal()
Terminal window
omniloop up # start server + dashboard
omniloop up --no-dashboard # server only
omniloop up --session my_run # isolated session
omniloop doctor # diagnose channel health