One model can drive thousands of CPU simulations
mjbatch takes one MjModel, copies it into a batch, and steps those simulations through a C++ thread pool. The Python GIL is released during native work. A caller sees arrays whose first dimension is the simulation count, so policy code can read positions, write controls, and advance the whole batch without a Python loop for each environment. The README's example creates 4,096 copies, though our lab did not measure simulation throughput or scaling.
The useful detail is that these are live views. bind("qpos") and bind("ctrl") expose simulation data as NumPy arrays, while named accessors cover joints, actuators, bodies, sites, and sensors. expand turns a model field such as geometry friction into per-simulation data, and set_const recomputes derived constants after edits. That is a good fit for parameter sweeps, randomized training, system identification, and hardware co-design using one shared topology.
The four core operations keep the API small
The public idea is mostly bind, expand, step, and reset. Version 0.1.2 also pins NumPy plus MuJoCo 3.13.0 rather than building a framework around environments, rewards, policies, or distributed workers. Researchers retain ordinary MuJoCo models and write the surrounding algorithm themselves. Seven examples cover cart-pole control, locomotion, a humanoid flip, throwing-arm design, and inertial identification. Some add PyTorch and model assets through an optional examples group.
A small API also means omissions surface quickly. Issue 2 asks for batched site Jacobians and heightfield sampling because a robot-learning framework needs those calls on its hot path. Neither operation appears in v0.1.2. The batch starts from one template model, so the natural unit is many parameterized copies rather than unrelated robot structures. Check every MuJoCo query your controller uses before replacing an existing vectorized backend.
What happened when we ran it
Our sandbox installed commit 713f5cf in 117 seconds, pulling 44 packages and occupying 169 MB. The native build finished in 6 seconds. Pytest then passed all 43 tests in 8 seconds, with 0 failures, and pip-audit reported 0 known vulnerabilities. The fresh Debian container had 3 CPUs, 8 GB of RAM, Python 3.12, no secrets, and no elevated privileges. The repository also supplied one CI workflow and a tests directory.
Those results cover compilation and correctness checks, not the performance claims in the README. We did not time simulation steps, compare thread counts, train a controller, or open the graphical examples. The 19.4 MB checkout also contains several GIFs and model assets, so repository size does not describe runtime memory. What we can say is narrower and useful: installation completed, the extension built, and every one of the 43 supplied tests passed on our CPU-only box.
MuJoCo 3.13.0 is an exact dependency
The v0.1.2 project configuration requires Python 3.10 or newer and pins MuJoCo exactly to 3.13.0 for both building and runtime. CMake 4.1 or newer and nanobind build the extension. Published-wheel automation targets CPython 3.10 through 3.14, including free-threaded 3.14, across glibc Linux and macOS runners. Windows, musllinux, and 32-bit targets are skipped.
That exact pin is the largest integration question for an existing robotics stack. Open pull request 6 proposes separate wheels for MuJoCo 3.10 through 3.13, but it is not part of the current release. A project with plugins or environments pinned to another MuJoCo version must either move them together or wait. Docker is not provided, so teams that want a frozen compiler and library environment must write and maintain their own image.
The 0.1.2 release fixed a state-write bug
Release v0.1.2 shipped September 30, 2026. It fixed writes being discarded after a bind("state") row write when reset was called. That is a consequential correctness fix in the library's central promise, and a reminder that this is early software. The repository was created September 10, only 20 days before that release. Pin the exact version and rerun project-level trajectory checks when upgrading.
Maintenance signals are current. GitHub showed 581 stars, two open issues, and three open pull requests on October 2; the API's combined count was five. The last push and latest release both landed September 30. CI tests Ubuntu and macOS on three Python variants, then builds release artifacts with provenance attestations. That is thoughtful release plumbing for a three-week-old project, though time and external adoption still have more to prove.
CPU batching is the reason to choose it
Brax and Isaac Lab make more sense when accelerator execution or a larger robot-learning platform is the requirement. Direct MuJoCo is simpler when you need one environment or broad access to every native query. mjbatch occupies the middle: familiar MuJoCo dynamics, many same-shaped simulations, CPU threads, and NumPy-facing state. Its 43 passing tests make that narrow proposition worth trying.
Start with one representative model and the queries used by your controller. Confirm that bound fields, reset behavior, model expansion, and thread counts reproduce your serial baseline before scaling the batch. If those checks pass, mjbatch removes a lot of Python-side repetition with little conceptual overhead. If you immediately need a missing batched native call, the library's clean core will not compensate for the operation your algorithm cannot express.

