Rez core concepts — packages, versions, requests, repositories, the package search path, implicit packages and variants. Use when the user asks what Rez is, how package versions or requests work, where Rez finds packages, why a resolve picked a certain version, or when a project contains package.py files. Covers Rez 3.4.0.
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.
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-env puts 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:
_ 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.1 in Rez.
Trust the code over the docs here. The ordering table in Rez's own basic_concepts.rst has
one error: it claims a < A, but A < a in reality. Its other twelve rows — including
13 < 043 — are correct. The same mistake appears in the AlphanumericVersionToken docstring
in src/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:
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.6 means nomaya within 2015.6 (includes 2015.6.1).
Weak reference ~ — constrains the version if the package is present, but does not
require it. Maya's package.py uses ~python-2.7.3 so 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:
bash
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:
bash
rez-config packages_path
Typical layout of the filesystem repository plugin:
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_path win, at version level: local foo-1.0.0 hides released
foo-1.0.0, but not foo-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.0 hides a released Windows variant even on Windows.
Use rez-env --no-local to 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:
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 torequires:
python
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:
root = root of the current variant; base = the directory containing variants.
For a package without variants, root == base.
hashed_variants = True installs variants under a hash instead, avoiding long paths and
escaping problems with !/<. use_variant_shortlinks adds 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.
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
bash
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-resolve skill; do not guess at the cause.