Skip to content

Installation

StableTested and in active use. Breaking changes will be called out.

noeira uses pixi for dependency management. pixi installs the Mojo compiler, the MAX runtime, the native libraries the I/O layer links (libcurl, libhdf5, qhull, ffmpeg), the Python packages used as reference oracles, and the CUDA toolchain where relevant. You do not install Mojo separately.

Platformslinux-64 (CUDA 12) · linux-aarch64 (CUDA 12, Jetson Orin) · osx-arm64 (macOS 15.0+)
ToolchainMojo 1.1.0 and MAX 26.6.0, pinned exactly in pixi.toml
Python3.13 (the environments pin it; see below)
GPU (optional)NVIDIA via CUDA, Apple Silicon via Metal, Jetson Orin via JetPack’s CUDA
Rendering (optional)SDL3 — installed by pixi, not needed for training
Terminal window
# macOS / Linux
curl -fsSL https://pixi.sh/install.sh | bash
# or with Homebrew
brew install pixi
Terminal window
git clone https://github.com/noeira/noeira.git
cd noeira
pixi install

The first solve downloads the full dependency set and takes a while. Subsequent commands reuse the cached environment.

Every command runs from the repository root, and the -I . flag puts the repository on Mojo’s module search path. Without it, import noeira fails.

Terminal window
pixi run mojo run -I . examples/solve_gridworld.mojo

If that prints Q-Learning, SARSA and SARSA(λ) training progress and a rendered grid, you are set. Walk through what it does in Quickstart: tabular.

pixi.toml declares six named environments plus default. They differ in the packages they install and in their activation scripts, not in the Mojo source they build.

EnvironmentForWhat it adds
defaultwhatever pixi run picks with no -ethe nvidia feature — not a CPU-only environment
nvidiaLinux x86-64 with an NVIDIA GPUcuda-toolkit 12.9, cudnn, cuda-gdb, nsight-compute; points MAX at the system ptxas and preloads the CUDA interceptor
jetsonJetson Orin (linux-aarch64, sm_87)no CUDA packages at all — uses the CUDA that JetPack installed in /usr/local/cuda; adds run-jetson / build-jetson
appleApple Silicon (Metal)nothing beyond the base set
amdAMD GPUsnothing beyond the base set; no AMD-specific tasks exist yet
cpuCI and headless runsthe Python pin, without the CUDA toolchain
act-refreference gates onlyPyTorch, torchvision, safetensors, transformers

Pick the environment with -e:

Terminal window
pixi run -e apple mojo run -I . examples/half_cheetah/sac_half_cheetah_training_gpu.mojo
pixi run -e nvidia mojo run -I . examples/half_cheetah/sac_half_cheetah_training_gpu.mojo

A few things are worth knowing about these:

  • default is nvidia. On a Mac, pass -e apple for anything that touches the GPU; plain pixi run still works for CPU examples.
  • The nvidia environment expects a CUDA install at /usr/local/cuda. Its activation sets MODULAR_NVPTX_COMPILER_PATH=/usr/local/cuda/bin/ptxas, bypassing the PTX compiler bundled with MAX (which is tied to CUDA 13 and a driver ≥ 580). A CUDA 12.x or 13.x container on driver ≥ 570 works. The activation also builds and preloads noeira/cuda/cuda_intercept.c, which the legacy CUDA-graph path needs (see CPU and GPU paths).
  • cpu exists so CI runners do not pull gigabytes of cuda-toolkit and cudnn they will never use.
  • act-ref is for dumping reference activations from PyTorch and HuggingFace implementations. Nothing under noeira/ imports torch; this environment only exists so the ports can be checked against someone else’s code.

The base dependency set allows Python 3.12 or 3.13, but every environment’s activation sets MOJO_PYTHON_LIBRARY to libpython3.13 in the active environment, and the nvidia, jetson and cpu features pin python >=3.13.14,<3.14 to match. The training path no longer imports Python — metrics go out over native HTTP — but the Gymnasium wrappers and a few reference tools still use Mojo’s Python interop.

The Orin needs --target-accelerator sm_87 on every compile: MAX picks the kernel target by asking NVML, Tegra’s NVML answers wrongly, and a binary built for the wrong target is refused by the driver at the first kernel load. The jetson environment wraps the flag in two tasks, and its activation preloads the same CUDA interceptor as nvidia, which on a Tegra board also answers NVML’s device queries from CUDA so MAX can find the integrated GPU at all:

Terminal window
pixi run -e jetson run-jetson examples/nn/mlp/mlp_mnist_training_storage_gpu.mojo
pixi run -e jetson build-jetson -o /tmp/out examples/nn/mlp/mlp_mnist_training_storage_gpu.mojo

Board setup and deployment are covered on the Jetson Orin page.

A few C libraries cannot be called directly from Mojo’s FFI — mostly because their entry points are C-variadic (ioctl, curl_easy_setopt) or C++-only (OpenCV, Dear ImGui). Each is wrapped by a small shim you build once. None of the built libraries is tracked in git, so a fresh checkout has to build the ones its features use.

TaskWrapsNeeded for
pixi run build-httplibcurl (+ zlib) for noeira/io/http.mojoevery network call: RemoteLogger, noeira cloud (projects, datasets, asset packs), the HuggingFace downloader, the MNIST and TinyShakespeare loaders
pixi run build-qhullqhull for noeira/physics3d/collision/any model with mesh geoms
pixi run build-serialioctl for noeira/io/serial/the SO-101 servo bus — anything under noeira/robot/
pixi run build-opencvOpenCV (C++) for noeira/vision/opencv/camera capture
pixi run build-imguiDear ImGui (cloned into third_party/ on first run)the ImGui viewers under noeira/render/imgui/

Tasks that need a shim declare it, so for those pixi builds it first. For example, soarm-record depends on build-serial and build-opencv, camera-studio on build-imgui and build-opencv, and soarm-tower-viewer on build-imgui. Nothing declares build-http or build-qhull: run those by hand before the first training run that logs remotely or the first mesh model.

Required to open a window: environment renderers, the 3D viewer, the ImGui tools. Not required for training. Video encoding goes through ffmpeg.

Nothing to install. pixi install brings SDL3 — the library and its headers — into the environment on macOS and Linux alike, and noeira loads it from there. A system SDL3 is neither needed nor used. That matters on Ubuntu 24.04 LTS, which ships no SDL3 package: libsdl3-dev only exists from Ubuntu 25.04 and Debian 13.

On a headless machine SDL3 is installed but has no display to open a window on: training runs, the viewers need a desktop session or X forwarding.

To use a different build of SDL3, point SDL3_LIB at it:

Terminal window
SDL3_LIB=/path/to/libSDL3.so pixi run mojo run -I . examples/cartpole/cartpole_demo.mojo

ale-py ships without ROMs. This task downloads the canonical Farama bundle and symlinks roms/:

Terminal window
pixi run setup-roms

Only needed for the Atari 2600 emulator. The native arcade engines (Pong, Breakout, Space Invaders) are independent of it and need no ROMs.

Terminal window
pixi run test-smoke # fast curated CPU test tier (what CI runs)
pixi run test-cpu # every non-GPU test — takes hours
pixi run -e apple test-gpu # GPU tests on Metal
pixi run -e nvidia test-gpu # GPU tests on CUDA

Every mojo run from source pays a per-build import cost that grows with the symbols a driver references. When you are iterating on a driver, a config or an example rather than on noeira/ itself, build the package once and compile against it:

Terminal window
pixi run build-pkg # precompile noeira into build/pkg/ (~3 min)
pixi run run-pkg examples/cartpole/cartpole_dqn_training.mojo # build against it, then run
pixi run compile-pkg examples/cartpole/cartpole_dqn_training.mojo -o /tmp/dqn

On the SAC HalfCheetah driver this took a warm rebuild from 38 s to 8 s. The wrapper (scripts/pkg.sh) compiles from inside build/pkg/, because the source tree shadows the package whenever the working directory contains noeira/, and it runs the binary from the repository root so the shims and assets resolve. run-pkg warns when files under noeira/ are newer than the package — rebuild it then.