Imported from loonghao/rez-skills (
skills/rez-core-concepts/SKILL.md). Install upstream withnpx skills add loonghao/rez-skills --skill rez-core-concepts. Copyright stays with the author.
Rez core concepts
One-sentence summary: Rez takes a request (a list of package requests), runs a solver over packages found on a search path, and produces a resolve — a conflict-free list of concrete package versions.
Reference: Rez 3.4.0.
Skill scope: concepts only. For package.py authoring see rez-package-definition,
for commands() see rez-package-commands, for resolve mechanics see rez-resolve,
for resolve failures see rez-resolve-troubleshooting.
Mental model
request ──► solver ──► resolve ──► package commands concatenated ──► shell code ──► subshell
- A package is a versioned piece of software with a single definition file (
package.py). - A variant is a build flavor of one package version (e.g. one per Maya/Python version).
- A resolve never contains two versions of the same package — that is a conflict.
- Rez never mutates your current shell;
rez-envputs you in a subshell.
Versions
Version numbers are alphanumeric token lists separated by . or -.
Examples: 1, 1.0.0, 3.2.build_13, 4.rc1, 10a-5.
Ordering rules (tokens compared left to right):
| Order | Rule |
|---|---|
| 1 | letters before numbers (a < 1) |
| 2 | among letters: A–Z < _ < a–z (A < a, and _ sits between them) |
| 3 | zero-padded numbers before less-padded (02 < 2, 002 < 02) |
| 4 | mixed tokens split into letter/number groups and compared with the same rules |
Alpha sub-tokens are compared with Python's native string comparison, so ordering follows ASCII
code points: A–Z (65–90) < _ (95) < a–z (97–122). That makes the full ordering:
sorted(['_', 'A', 'Z', 'a', 'z', '0', '9'], key=Version)
-> ['A', 'Z', '_', 'a', 'z', '0', '9']
_ is not before everything — it comes after uppercase but before lowercase, so
1.0.rc_1 > 1.0.RC1 while 1.0.rc_1 < 1.0.rca.
Gotchas that matter in practice:
- The delimiter is ignored for comparison:
1.0.0==1-0.0. - Longer shared-prefix wins:
1.0.0>1.0. - No special meaning for
alpha/beta/rc. Semver is encouraged but not enforced, and semver ordering does not apply:foo-1.0.0 < foo-1.0.0-beta.1in Rez.
Trust the code over the docs here. The ordering table in Rez's own
basic_concepts.rsthas one error: it claimsa<A, butA<ain reality. Its other twelve rows — including13<043— are correct. The same mistake appears in theAlphanumericVersionTokendocstring insrc/rez/version/_version.py, which states alphas compare "_, then A-Z, then a-z". Since a source docstring gets this wrong too, treat the class itself as the only reliable benchmark and verify any ordering question that matters:python -c "from rez.version._version import Version; print(sorted(['_','A','a'], key=Version))"
Package requests
A request is a string matching a range of versions. Used in requires, variants and on the CLI.
| Request | Meaning |
|---|---|
foo |
any version |
foo-1 |
any foo-1[.x.x…] |
foo-1+ |
foo-1 or greater |
foo-1.2+<2 |
>=1.2, <2 |
foo<2 |
any version less than 2 |
foo==2.0.0 |
exactly 2.0.0 |
foo-1.3|5+ |
OR'd requests |
Two operators deserve special attention:
- Conflict
!—!maya-2015.6means nomayawithin2015.6(includes2015.6.1). - Weak reference
~— constrains the version if the package is present, but does not require it. Maya'spackage.pyuses~python-2.7.3so that any python-using package picks the python compatible with Maya, without Maya actually depending on python.
Quote requests on the shell — <, >, | and ! are shell metacharacters:
rez-env 'python-2.6+' 'my_py_utils-5.4+<6'
Repositories and the search path
Packages live in package repositories; Rez finds them via packages_path (a search path,
like PYTHONPATH). Inspect it with:
rez-config packages_path
Typical layout of the filesystem repository plugin:
/packages/inhouse/foo/1.1/package.py
/python/<FILES>
/bin/<EXECUTABLES>
/packages/inhouse/foo/1.2/
/packages/inhouse/foo/1.3/
Only the definition file location is fixed (root of the version dir); the rest is up to the build.
Shadowing rules — these cause most "wrong version" surprises:
- Earlier paths on
packages_pathwin, at version level: localfoo-1.0.0hides releasedfoo-1.0.0, but notfoo-1.2.0. - Rez does not merge variants of the same package version across repositories.
- Rez does not fall back to a later repository when the earlier package has no compatible
variant — a local Linux-only
foo-1.0.0hides a released Windows variant even on Windows. - Use
rez-env --no-localto exclude locally installed packages from a resolve.
Typical setup: local_packages_path (~/packages) first so developers can test before release,
then central released repositories later in the path.
Implicit packages
Every request automatically gets implicit_packages appended. The default:
implicit_packages = [
"~platform=={system.platform}",
"~arch=={system.arch}",
"~os=={system.os}",
]
Rez models platform/arch/OS as packages. These are weak requirements, so a
platform-dependent package is constrained to the current system without forcing those packages in.
rez-env and rez-context print the implicits that were used.
Variants
A variant is a sub-build of one package version that differs by dependencies.
Each variant entry's requirements are appended to requires:
name = "my_maya_plugin"
version = "1.0.0"
requires = ["openexr-2.2"]
variants = [["maya-2016.sp2"], ["maya-2017"]]
On disk, variants are subdirectories of the package version:
/rez/packages/my_maya_plugin/1.0.0/maya-2016.sp2/<PAYLOAD>
/maya-2017/<PAYLOAD>
root= root of the current variant;base= the directory containing variants. For a package without variants,root == base.hashed_variants = Trueinstalls variants under a hash instead, avoiding long paths and escaping problems with!/<.use_variant_shortlinksadds symlinks under_v/.- Only one variant of a package is ever used in a given environment.
Variant selection
Default variant_select_mode = "version_priority":
- Priority to packages that appear in the request list.
- Then priority to packages listed earlier in the variant.
- Prefer the higher version.
The other mode, intersection_priority, prefers the variant with the most packages present in
the request, with version priority secondary.
Undefined behavior: if variants are not mutually exclusive (e.g. [["maya-2016"], ["houdini-14"]])
and the discriminating package is not in the request, Rez gives no guarantee which variant is
chosen. It is deterministic, just not predictable. Add the discriminator to the request to make it
predictable.
You cannot add variants to a package that has none without bumping the version — so adding a single variant now is a common future-proofing move.
Ephemeral packages
Names starting with . are ephemerals: requests for packages that do not exist. They
participate in the solve (their ranges intersect, conflicts occur) but contribute no payload and
no commands(). Useful for passing resolved intent through an environment.
rez-env python .foo-1 .bah-2
echo $REZ_EPH_FOO_REQUEST # 1
echo $REZ_USED_EPH_RESOLVE # .foo-1 .bah-2
Environment variables set by Rez
| Variable | Meaning |
|---|---|
REZ_USED_RESOLVE |
full resolved package list |
REZ_USED_REQUEST |
the original request |
REZ_USED_LOCAL_RESOLVE |
subset resolved from the local repository |
REZ_USED_EPH_RESOLVE |
ephemerals in the resolve |
REZ_USED_IMPLICIT_PACKAGES |
implicits used |
REZ_USED_VERSION / REZ_USED_TIMESTAMP |
rez version / resolve time |
REZ_<PKG>_ROOT |
root of the current variant of <PKG> |
REZ_<PKG>_BASE |
base of <PKG> (parent of its variants) |
REZ_<PKG>_VERSION |
version of <PKG> |
REZ_RXT_FILE |
path to the context (.rxt) file when one was saved |
Package names are upper-cased and non-alphanumerics become _: my_utils → REZ_MY_UTILS_ROOT.
Reading a resolve
rez-env foo bah
Output lists requested packages (with (implicit) and (ephemeral) labels) and
resolved packages (with (local) for local installs). The > prompt prefix is the visual cue
that you are inside a Rez-configured environment.
Use rez-context for non-interactive inspection — see the rez-cli skill.
Agent workflow
- Inspect before guessing:
rez-config packages_path,rez-search <pkg>,rez-status. - Narrow the read —
rez-context --so,rez-search <pkg> --latest— instead of dumping everything. - Reproduce a resolve without entering a shell:
rez-env <reqs> --output context.rxt. - If a resolve fails, go to the
rez-resolveskill; do not guess at the cause.
