Quickstart
Install OmniLoop, bring up the dashboard, and drag sliders that control a running process — in under 5 minutes.
Install
Section titled “Install”pip install omniloopPull in only the framework extras you need:
pip install omniloop[sb3] # Stable-Baselines3pip install omniloop[tensorboard] # TensorBoard mirrorpip install omniloop[rerun] # Rerun sinkpip install omniloop[all-integrations] # everything# Requires a Rust toolchain + maturinpip install maturincd omniloop-sdk-python && maturin developBring up the dashboard
Section titled “Bring up the dashboard”-
Start the visualizer — one command replaces the old two-terminal dance:
Terminal window omniloop upThis launches the FastAPI telemetry server on
:8000and the Vite dashboard on:5173. -
Run a target loop — in a second terminal, start the demo:
Terminal window python examples/mock_rl_training.py -
Open the dashboard — navigate to http://localhost:5173 in your browser.
Drag a slider
Section titled “Drag a slider”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.
What just happened
Section titled “What just happened”┌──────────────┐ shared memory ┌──────────────┐ websocket ┌──────────────┐│ Your Loop │ ◄──────────────────── │ OmniLoop │ ◄───────────────► │ Dashboard ││ (Python) │ telemetry + commands │ Server │ telemetry + │ (React) ││ │ ────────────────────► │ (FastAPI) │ mutations │ │└──────────────┘ └──────────────┘ └──────────────┘- Your loop registers variables and publishes telemetry through shared memory (Rust IPC, no sockets in the hot path).
- The server polls the shared-memory channel and rebroadcasts over a WebSocket.
- The dashboard renders the state and sends mutation commands back.
- Mutations arrive in the loop’s next
tick()/wait_if_halted()call — applied instantly.
Plug in your own code
Section titled “Plug in your own code”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() |
Useful commands
Section titled “Useful commands”omniloop up # start server + dashboardomniloop up --no-dashboard # server onlyomniloop up --session my_run # isolated sessionomniloop doctor # diagnose channel health