mujoco_playground
AGENTS.md2.3k starsChanged 6 days agoApache-2.0View on GitHub
- Always use uv run, not bare python. Pass explicit --extra flags (e.g. --extra rl, --extra so101, --extra yam) to uv run rather than --no-sync; pyproject.toml (Python 3.12–3.13) configures PyPI as the default index, CMAKE_CXX_STANDARD=17 for reaf, and cross-platform override-dependencies (evdev on Linux only, ruckig>=0.15.3). - Always use absl (from absl import app, flags, logging) for scripts, tools, and entrypoints. NEVER use argparse. - Dependencies are managed with uv. Default make sync installs --extra rl --group dev with CUDA 13…
Adopted by
Steady: 0 new projects took it in the last 4 weeks, none the 4 weeks before.thin data
Who's talking about google-deepmind/mujoco_playground
- mujocolab/mjlab“SB3/SBX Integration”GitHub · Mar 9, 2026 · 3 reactions
- @mujoco.bsky.social“You can get started today 🌐 Project page: playground.mujoco.org 📂 Code: github.com/google-deepm... 📝 …”Bluesky · Jan 16, 2025 · 2 likes
- sail-sg/envpool“Survey candidate RL environment suites not yet covered by EnvPool”GitHub · Apr 8, 2026 · 1 reactions
- stainSTORM/smart_arkitekt“Create initial Workflow based on SVG description”GitHub · Aug 15, 2025 · 1 reactions
- ATR-Lab/getting-started-atr-lab“Weekly software version check”GitHub · Nov 9, 2026
The biggest 5 of 25 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 25
Talked about on GitHub and Bluesky (25 times).
On GitHub · 24
- Mar 9, 2026SB3/SBX Integration — mujocolab/mjlab3 reactions · 4 comments
- Apr 8, 2026Survey candidate RL environment suites not yet covered by EnvPool — sail-sg/envpool1 reaction · 3 comments
- Aug 15, 2025Create initial Workflow based on SVG description — stainSTORM/smart_arkitekt1 reaction
- Nov 9, 2026Weekly software version check — ATR-Lab/getting-started-atr-lab0 reactions
- Nov 6, 2026LOCO-PLATFORM-001: cross-engine biomechanics and sim-to-real evidence benchmark — Luminous-Dynamics/symtropysays it tested it0 reactions · 5 comments
19 more on GitHub
- Sep 16, 2026Update playground requirement from >=0.0.4 to >=0.2.0 in /services/api — backblaze-b2-samples/mujoco-rollout-dataset0 reactions
- Jun 29, 2026[Simulator] MuJoCo Playground — PyTorchKR/Awesome-Physical-AI0 reactions · 2 comments
- Nov 13, 2025height fields: limit to maximum 4 contacts — google-deepmind/mujoco_warp0 reactions
- Nov 5, 2025Difference with kscalelabs/ksim-gym — kscalelabs/mujoco_playground0 reactions
- Sep 9, 2025[Proposal] Sim2Sim deployment scripts to MuJoCo Playground — MuammerBay/isaac_so_arm1010 reactions
- Sep 9, 2025Video recording in evaluation while training — google/brax0 reactions · 2 comments
- Sep 4, 2025Rodent imitation reimplementation — talmolab/vnl-playground0 reactions · 4 comments
- Sep 1, 2025Merging the RL branch — usclaser/smallsat-sim0 reactions
- Aug 26, 2025Freeze at the first fram — Andrew-Luo1/rscope0 reactions · 3 comments
- Aug 25, 2025Collision failures frequent among primitives: box-box, box-capsule, capsule-capsule, etc — google/brax0 reactions · 4 comments
- Aug 25, 2025Collision failures frequent among primitives: box-box, box-capsule, capsule-capsule, etc — google-deepmind/mujoco0 reactions · 1 comment
- Aug 15, 2025[WIP] Create initial Workflow based on SVG description — stainSTORM/smart_arkitekt0 reactions
- Jun 30, 2025Feat/go1_feet_only config — RoboVerseOrg/RoboVerse0 reactions
- Jun 27, 2025generalize BC file loading — google/brax0 reactions
- Apr 29, 2025Add Contextual Heinrich Env — automl/CARL0 reactions
- Apr 24, 2025Add project: MuJoCo Playground — knmcguire/best-of-robot-simulators0 reactions
- Mar 27, 2025[Notes] MJX Support — hello-robot/stretch_mujoco0 reactions
- Mar 24, 2025NaNs during motor control — vincekurtz/hydrax0 reactions · 2 comments
- Jan 17, 2025Add recipe for playground PyPI package — conda-forge/staged-recipes0 reactions · 4 comments
On Bluesky · 1
- Jan 16, 2025You can get started today 🌐 Project page: playground.mujoco.org 📂 Code: github.com/google-deepm... 📝 Paper:… — @mujoco.bsky.social2 likes and reposts · 1 reply
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,843 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
The file
We split this AGENTS.md into the rules it gives an agent
12 rules. About 0 are common, 3 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 3
Always use uv run, not bare python.
- Very specific: line 4
Always use absl (from absl import app, flags, logging) for scripts, tools, and entrypoints.
- Very specific: line 8
Run pyink and isort against only the specific paths you changed, not a parent directory: uv run --group dev pyink <path> and uv run --group …
- Very specific: line 11
Prefer running individual tests rather than the full test suite to improve iteration speed: MUJOCO_GL=osmesa uv run --extra rl --group dev …
- Distinctive: line 33
Do not add AI assistants (e.g.
- Distinctive: line 35
When responding to PR review comments:
- Distinctive: line 38
Add a summary comment on the PR after responding, covering what was applied and what was intentionally skipped.
- Very specific: line 42
CLI / Entrypoints: Always use absl.flags and absl.app.run(main).
- Very specific: line 43
Path Handling: Prefer etils (from etils import epath) over pathlib for file and directory paths (note that recursive ` globs are not …
- Very specific: line 46
Type Annotations: Use modern union syntax (T | None), standard collections (list[str], dict[str, Any]), and explicit return types.
- Very specific: line 61
Every public module is a thin re-export shim over _src/.
- Very specific: line 110
Hardware SDKs are optional extras, imported lazily: Never import a driver at module scope — put a plain import inside the function that …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Development Workflow
- Always use
uv run, not barepython. Pass explicit--extraflags (e.g.--extra rl,--extra so101,--extra yam) touv runrather than--no-sync;pyproject.toml(Python 3.12–3.13) configures PyPI as the default index,CMAKE_CXX_STANDARD=17forreaf, and cross-platformoverride-dependencies(evdevon Linux only,ruckig>=0.15.3). - Always use
absl(from absl import app, flags, logging) for scripts, tools, and entrypoints. NEVER useargparse. - Dependencies are managed with
uv. Defaultmake syncinstalls--extra rl --group devwith CUDA 13 PyTorch (<2.14) and CUDA 13 Warp on Linux, and native wheels on macOS. - On Linux machines with CUDA 12 drivers (
< 580, e.g. CUDA 12.4), runmake sync-cu12and pass--group cu12to everyuv runcommand (ormake sync-cpuand--group cpufor CPU-only Linux); omitting--group cu12onuv runoverlays PyPI's CUDA 13nvidia-*sub-packages onto.venvand breaks cuDNN (CUDNN_STATUS_NOT_INITIALIZED). - Real-robot SDKs (
--extra so101for Feetech,--extra yamfor I2RT SocketCAN on Linux orgs-usb/pyusb+libusbon macOS) are optional extras and do not conflict withcu12orcpu. - Run pyink and isort against only the specific paths you changed, not a parent directory:
uv run --group dev pyink <path>anduv run --group dev isort <path>. - For headless rendering / tests on Linux, set
MUJOCO_GL=osmesa. Omit on macOS. - Prefer running individual tests rather than the full test suite to improve iteration speed:
MUJOCO_GL=osmesa uv run --extra rl --group dev pytest <path/to/test.py> -v.
Quick Commands
make sync # For GPU, good for RL training (CUDA 13 on Linux)
make sync-cu12 # For CUDA 12 on Linux (NVIDIA driver < 580)
make sync-cpu # Or for CPU only, (i.e. on macOS, or CPU-only on Linux)
make format # pyink + isort over the repo
make typecheck # pyrefly type check
make test # pytest over mujoco_playground/
make check-imports # verify optional extras are not imported at module scope
make docs # build HTML docs (or `make serve-docs` to preview locally)
uv run --group dev pre-commit run -aCommits and PRs
- PR body should be plain, concise prose. Describe the problem, what the change does, and any non-obvious tradeoffs. Bullet points listing changes are fine, but avoid section headers, structured templates, and emojis. A good PR description reads like a short paragraph to a colleague, not a form.
- PR and commit messages are rendered on GitHub, so don't hard-wrap them at 88 columns. Let each sentence flow on one line.
- Push branches to your own fork, not to the main repo directly.
- Do not add AI assistants (e.g. Claude, Antigravity) as commit co-authors. The CLA check requires all commit authors to have signed the CLA, and AI tools cannot sign it.
- Amending commits is fine before a PR has reviewers looking at it. Once a PR is under review, use new commits so reviewers can see what changed.
- When responding to PR review comments:
- Reply to each comment individually confirming what you did (or why you didn't).
- Resolve comment threads that are addressed.
- Add a summary comment on the PR after responding, covering what was applied and what was intentionally skipped.
Code Style
- CLI / Entrypoints: Always use
absl.flagsandabsl.app.run(main). Never useargparse. - Path Handling: Prefer
etils(from etils import epath) overpathlibfor file and directory paths (note that recursive**globs are not supported byepath.Path.glob(), so useglob.globwhen matching glob patterns). - Formatting:
pyinkwith 2-space indentation and an 80-column limit;isortwithforce_single_line = true. Run pyink and isort against modified files. - Docstrings & Comments: Preserve all existing docstrings, TODOs, and comments when editing.
- Type Annotations: Use modern union syntax (
T | None), standard collections (list[str],dict[str, Any]), and explicit return types. - Error Handling: Fail gracefully with informative error messages.
Excluded Directories
third_party/ and rss2025/ are excluded from formatting
(pyink), import sorting (isort), and pre-commit. Do not reformat them.
Architecture
The environment stack is reaf and reaf-sim (reaf.simulation.torch,
vendored under third_party/reaf_sim).
_src/ is the implementation; the top level is the public API
Every public module is a thin re-export shim over _src/. In
reaf.simulation.torch, reaf/simulation/torch/__init__.py re-exports core,
common, builders, and viewer simulation components from
reaf/simulation/torch/_src/{core,common,builders,viewer}/.
Consequence: code under tasks/ and robots/ should import from the public
paths (from reaf.simulation import torch as reaf_sim,
from reaf.simulation.torch import flat_scene), while
code inside _src/ imports its siblings directly.
Layered environment (reaf.simulation.torch)
environment.py composes the layers, from hardware upward:
device_layer.py— devices bound to the physics model (joints, actuators, cameras, sites, contact sensors)task_layer.py— features, rewards, terminations, discountstorch_wrapper.py— tensor/device handling
Supporting protocols (feature_producer.py, reward_provider.py, termination_checker.py, discount_provider.py) define what a task plugs in. EnvironmentReset in environment.py is the privileged-access escape hatch: on_startup / on_reset / on_step / check_termination, with direct model and data access, used for domain randomization and NaN/limit detection.
Environments are built from config, not subclassed
reaf.simulation.torch.flat_scene.build_env takes a
reaf.simulation.torch.flat_scene.Environment dataclass and
assembles the layered Environment. A config declares device_layer.devices,
feature producers, rewards, terminations, and resetters as flat_scene.Component
entries (Component(Cls, **kwargs).configure_spec(...).attach(...).mark_privileged()), plus
flat_scene.Obs, flat_scene.ObsGroup, flat_scene.Reward, and flat_scene.Term.
So adding a task means writing a function that returns a config, not implementing an env class. See tasks/manipulation/pick_cube/so101/task.py for the shape: a shared pick_cube/task.py base config, mutated by a robot-specific _configure_*_robot function.
reaf.simulation.torch.flat_scene.Sim holds the simulation knobs —
nworld (batch size), xpu_device, impl ("warp" on CUDA, "cpp" on CPU),
and the two timesteps.
robots/ vs tasks/
robots/<name>/sim/scene.py— loads theMjSpecfor the robotrobots/<name>/sim/device.py— joint names, home qpos/ctrl, stiffness, damping, force ranges, armaturetasks/<task>/— the MDP (mdp.py), reset logic (reset.py), and config assembly (task.py)
A task/robot pair lives at tasks/<task>/<robot>/task.py and combines the two.
Real hardware (robots/<name>/real/)
Mirrors sim/ alongside it. The real robot is the source of truth: real/constant.py defines the canonical joint ordering, home pose, and hardware constants, and sim/device.py re-exports them — sim depends on real, not the other way around. Sim and real silently disagreeing on joint order corrupts everything downstream, so verify the correspondence for a new robot rather than assuming it. For the SO101 the order matches lerobot's motor order.
Three conventions hold here:
- Hardware SDKs are optional extras, imported lazily. Never import a driver at module scope — put a plain
importinside the function that uses it, with a comment naming the extra that installs it. - Machine-local config is generated, never checked in. Values that identify one person's hardware (USB serial numbers, calibration) live under
paths.local_dir(). - Missing config raises with the command that generates it. See
get_ports.load_port_config.
RL registry
_src/rl/env_registry.py maps a string env id to (env_builder, runner_cfg, env_cfg_fn). Registrations are at the bottom of that file — SO101PickCube, TrossenPickCube, CartpoleBalance, G1WholeBodyTracking, and their *Vision variants. env_cfg_fn is called lazily, deliberately: config functions touch the filesystem to load assets, and that must not happen at import time.
Adding an env to the registry means importing its task module there, so a broken task config breaks registry import for everything.
Training entry points are rl/rsl_rl/train.py (--env, --seed, --overrides, --env_overrides as JSON dicts with dotted keys) and rl/rsl_rl/play.py (--env, --env_overrides, --resume_path, --nworld). RSL-RL is an optional dependency under the rl extra.
Assets
asset.get("github:google-deepmind/mujoco_menagerie/<path>.xml") resolves URIs through _src/paths.py, which maps URI prefixes to local checkout directories. Robot scenes call this rather than hardcoding paths.
Bringing up an SO101
Two READMEs take a user from an unopened box to logged teleop episodes, in this order:
mujoco_playground/robots/so101/real/README.md— sync theso101driver extra, identify the two arms by USB serial and the wrist camera by sight (real.get_ports --identify,real.get_cameras --identify), then calibrate both arms (real.get_calibration;--rolesre-does just one).mujoco_playground/tasks/teleop/so101/README.md— teleop in sim first, then on hardware; foot-pedal gating, MCAP episode logs, andview_logto replay an episode in rerun.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

