- Breaking changes require a deprecation first. Do not remove or rename public API symbols without deprecating them in a prior release.
- Group by common prefix for discoverability (autocomplete).
- Classes: group by domain concept —
ActuatorNetLSTM,ActuatorNetMLP(notLSTMActuatorNet,MLPActuatorNet). - Methods: group by noun before modifier —
set_joint_position_target()(notset_target_joint_position()).
- Classes: group by domain concept —
- Method names are
snake_case. - CLI arguments are
snake_case. - Prefer nested classes when self-contained.
- If a helper type or an enum is only meaningful inside one parent class and doesn't need a public identity, define it as a nested class instead of creating a new top-level class/module.
- Follow PEP 8 for Python code.
- Use modern Python type-hint syntax.
- Prefer PEP 604 unions:
x | y,x | None. Do not usetyping.Unionortyping.Optional.
- Prefer PEP 604 unions:
- Use specific type hints for public interfaces.
- For torch tensors, annotate with
torch.Tensor. For Warp arrays, annotate concrete dtypes (e.g.,wp.array(dtype=wp.vec3)) rather than genericobject. - Prefer consistent parameter names across base/override APIs (e.g.,
xforms,scales,colors,materials).
- For torch tensors, annotate with
- Use Google-style docstrings.
- Write clear, concise docstrings that explain what the function does, its parameters, and its return value.
- Keep argument/return types in function annotations, not inline in docstrings.
- In
Args:entries, usename: description(notname (Type): description). - Use Sphinx cross-reference roles for symbol references (e.g.
:class:,:meth:,:attr:,:paramref:), but keep targets as short as possible. - Within the same class/module, prefer short local references (e.g.
:meth:\set_joint_position_target`,:attr:`num_joints``) over fully qualified paths. - If qualification is needed, prefer public API paths (e.g.
isaaclab.assets.Articulation) and do not use internal_srcor private module paths in Sphinx role targets.
- State SI units for all physical quantities in docstrings.
- Use inline
[unit]notation, e.g."""Particle positions [m], shape [particle_count, 3], float.""". - For joint-type-dependent quantities use
[m or rad, depending on joint type]. - For spatial vectors annotate both components, e.g.
[N, N·m]. - For compound arrays list per-component units, e.g.
[0] k_mu [Pa], [1] k_lambda [Pa], .... - When a parameter's interpretation varies across solvers, document each solver's convention instead of a single unit.
- Skip non-physical fields (indices, keys, counts, flags).
- This rule applies to public API docstrings only, not test docstrings.
- Use inline
- Keep the documentation up-to-date.
- When adding new files or symbols that are part of the public-facing API, make sure to keep the auto-generated documentation updated by running
./isaaclab.sh -d.
- When adding new files or symbols that are part of the public-facing API, make sure to keep the auto-generated documentation updated by running
- Avoid adding new required dependencies. IsaacLab's core should remain lightweight and minimize external requirements.
- Strongly prefer not adding new optional dependencies. If additional functionality requires a new package, carefully consider whether the benefit justifies the added complexity and maintenance burden. When possible, implement functionality using existing dependencies, including Warp functions and kernels, NumPy, or the standard library.
We use a wrapped python call within ./isaaclab.sh.
- Use
./isaaclab.sh -p -cfor inline Python: When running one-off Python commands, use./isaaclab.sh -p -c "..."instead ofpython3 -c "...". - Use
./isaaclab.sh -pto run standalone Python scripts without apyproject.toml(e.g., in CI after switching to a branch with no project files).
# run all tests (extremely heavy, should be avoided).
./isaaclab.sh -t
# run a specific test file by name
./isaaclab.sh -p -m pytest PATH_TO_TEST
# run a specific example test
./isaaclab.sh -p -m pytest PATH_TO_TEST::METHODCRITICAL: Always run pre-commit hooks BEFORE committing and BEFORE pushing.
Proper workflow:
- Make your code changes
- Run
./isaaclab.sh -fto check ALL files - If pre-commit modifies any files (e.g., formatting), review the changes
- Stage the modified files with
git add - Run
./isaaclab.sh -fagain to ensure all checks pass - Only then create your commit with
git commit - Verify pre-commit still passes before pushing — never push commits that haven't been checked
# Run pre-commit checks on all files
./isaaclab.sh -fCommon mistakes to avoid:
- Don't commit first and then run pre-commit (requires amending commits)
- Don't push before running pre-commit (pushes broken code to the remote)
- Do run pre-commit before committing and before pushing (clean workflow)
When reviewing code (e.g. via a code-reviewer agent), always run ./isaaclab.sh -f as part of the review to catch formatting or lint issues early.
-
Do not edit
CHANGELOG.rstorconfig/extension.tomldirectly. Each PR adds a fragment file undersource/<package>/changelog.d/; the changelog and version are compiled by the nightly CI workflow. -
Add one fragment per touched package. Pick any short, unique slug for the filename — your branch name (with
/replaced by-) is a good default. The filename suffix declares the bump tier; within a batch the highest tier wins for the package.Filename Effect source/<pkg>/changelog.d/<slug>.rstpatch bump source/<pkg>/changelog.d/<slug>.minor.rstminor bump source/<pkg>/changelog.d/<slug>.major.rstmajor bump source/<pkg>/changelog.d/<slug>.skipno entry, no bump (CI / docs / test-only) -
Use past tense matching the section header: "Added X", "Fixed Y", "Changed Z".
-
Place entries under the correct category:
Added,Changed,Deprecated,Removed, orFixed. -
Avoid internal implementation details users wouldn't understand.
-
For
Deprecated,Changed, andRemovedentries, include migration guidance.- Example: "Deprecated
Articulation.Ain favor ofArticulation.B."
- Example: "Deprecated
-
Breaking changes belong in
Changed, prefixed with**Breaking:**. -
Use Sphinx cross-reference roles for class/method/module names.
Added
^^^^^
* Added :class:`~package.ClassName` to support feature X.
Fixed
^^^^^
* Fixed edge case in :meth:`~package.ClassName.method` where input was
not validated, causing ``AttributeError`` at runtime.
Key formatting rules:
- Category heading: underline with
^(carets), at least as long as the heading text. - Entries:
*prefix, continuation lines indented by 2 spaces.
See tools/changelog/test/integration/ for worked examples that double as integration-test fixtures.
Follow conventional commit message practices.
- Use feature branches: All development work should be on branches named
<username>/feature-desc(e.g.,jdoe/docs-versioning). Do not commit directly tomain. - Keep commits focused and atomic—one logical change per commit.
- Reference related issues in commit messages when applicable.
- When iterating on PR feedback, prefer adding new commits over amending existing ones. This avoids force-pushing and lets the reviewer easily verify each change request was addressed.
- Do not include AI attribution or co-authorship lines (e.g., "Co-Authored-By: Claude...") in commit messages. Commits should represent human contributions without explicit AI attribution.
- Commit message format:
- Separate subject from body with a blank line
- Subject: imperative mood, capitalized, ~50 chars, no trailing period
- Write as a command: "Fix bug" not "Fixed bug" or "Fixes bug"
- Test: "If applied, this commit will [your subject]"
- Body: wrap at 72 chars, explain what and why (not how—the diff shows that)
- New files must use the current year (2026) in the SPDX copyright header:
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause - Do not change the year in existing file headers.
- Network access (e.g.,
git push) is blocked by the sandbox. UsedangerouslyDisableSandbox: trueso the user gets an approval prompt — don't ask them to run it manually. - Never push to
origin(isaac-sim/IsaacLab). Theoriginremote is the public upstream repository. Push to your own fork remote (e.g.,antoine,alex) or to the remote of the PR you are working on. If the correct remote is unclear, ask the user before pushing.
- Pin actions by major version tag (e.g.
actions/checkout@v6). Use the same major version that other workflows in.github/workflows/already use — don't introduce a new major version without checking how it's used elsewhere.
- Always verify regression tests fail without the fix. When writing a regression test for a bug fix, temporarily revert the fix and run the test to confirm it fails. Then reapply the fix and verify the test passes. This ensures the test actually covers the bug.
Do not add wp.printf to kernels in production code. Debug prints in Warp kernels affect performance and can produce noisy test output. Use them only in standalone reproduction scripts during development, and always remove them before committing.
To debug Warp kernel behavior:
- Write a standalone reproduction script and run it directly with
./isaaclab.sh -p -c "..."or./isaaclab.sh -p script.py. This keeps stdout visible and avoids the test framework entirely. - Use high-precision format strings for floating-point debugging (e.g.,
wp.printf("val=%.15e\n", x)) — the default%fformat hides values smaller than ~1e-6 that can still affect control flow. - Remove all
wp.printfcalls before committing.