Install
openclaw skills install @loonghao/rez-windows-platformRunning rez on Windows — why only cmd, gitbash, powershell and pwsh are registered there and how the default is picked, the path-separator trap where cmd and pwsh join with ';' while gitbash joins with ':', backslash versus forward slash in generated shell code, the 260-character MAX_PATH limit and why variant install paths exceed it, the platform/arch/os implicit packages, using rez-interpret as a cross-shell oracle without launching a shell, install and config-file layout, and CI differences. Use when a package or resolve behaves differently on Windows, when porting a package across operating systems, when a deep path fails to read or write, or when a one-liner works in bash and fails in cmd. Covers Rez 3.4.0.
openclaw skills install @loonghao/rez-windows-platformOne-sentence summary: on Windows rez registers only
cmd,gitbash,powershellandpwshas shells, and those shells disagree about the path separator —cmdandpwshjoin lists with;whilegitbashjoins them with:— which is why the samepackage.pycan produce a workingPATHin one shell and a broken one in another.
Skill scope: the Windows-specific differences. For the commands() body and the rex API in
general see rez-package-commands; for package.py attributes see rez-package-definition; for
config layering and plugin discovery see rez-config-plugins; for a resolve that fails on any
platform see rez-resolve-troubleshooting.
Platform note. Every fenced block in this skill is tagged with the shell it belongs to (
powershell,bat, ```bash). Commands taggedpowershellorbatare Windows-only and will fail on Linux or macOS, where those shells are not registered. Therez-interpretexamples are safe to run anywhere — it only prints text, never launches a shell.
Rez ships shell plugins for bash, sh, csh, tcsh, zsh, cmd, gitbash, powershell and pwsh, but only the ones valid for the current platform are registered. On Windows:
cmd, gitbash, powershell, pwsh
The POSIX shells are not registered there, so rez-env --shell bash is not a valid value on
Windows and vice versa. Ask rez rather than assuming, because the answer is platform-dependent:
from rez.shells import get_shell_types
print(get_shell_types()) # ['cmd', 'gitbash', 'powershell', 'pwsh'] on Windows
The order is default_shell, then system.shell:
rez-config default_shell
default_shell is empty ('') out of the box, in which case rez falls back to detecting the current
shell — on Windows that is typically powershell. There is no default_windows_shell setting in
rez 3.4.0; default_shell is the only knob, and it applies on every platform.
To target a shell for one invocation:
# Windows only — 'cmd' is not a registered shell on Linux or macOS
rez-env foo --shell cmd
REM Windows only
rez-env foo --shell cmd
This is the difference that breaks real packages. The same rex produces different text per shell:
rez-interpret -c 'env.MY_PATH.prepend("C:/pkgs/foo/bin")' -f cmd --pv MY_PATH
rez-interpret -c 'env.MY_PATH.prepend("C:/pkgs/foo/bin")' -f pwsh --pv MY_PATH
rez-interpret -c 'env.MY_PATH.prepend("C:/pkgs/foo/bin")' -f gitbash --pv MY_PATH
With MY_PATH already set, the generated code is:
| Shell | Generated line | Separator |
|---|---|---|
cmd | set MY_PATH=C:\pkgs\foo\bin;C:\Program Files\Git\usr\bin;... | ; |
pwsh | Set-Item -Path "Env:MY_PATH" -Value ("C:\pkgs\foo\bin;" + ...) | ; |
gitbash | export MY_PATH="C:/pkgs/foo/bin:${MY_PATH}" | : |
Two things to take from it:
; under cmd and pwsh, and : under gitbash. A package.py that
builds a list by hand — joining with : because it was written on Linux — produces a single
unreadable entry on Windows. Use the rex list operations (append, prepend, set) and let rez
pick the separator.cmd and pwsh emit backslashes; gitbash keeps forward slashes. Both work in their own
shell, so the difference only bites when you compare or string-match paths.The separator applies to every list-valued variable, not just PATH — PYTHONPATH,
LD_LIBRARY_PATH-style variables and any custom list behave the same way.
os.sep is a backslash and os.pathsep is a semicolon on Windows, versus a forward slash and a
colon on POSIX.packages_path is a Python list, so it is immune to the separator problem — do not build a
;-joined string for it.os.pathsep, so they take ; on Windows. This
includes rez-env --paths and rez-search --paths:# Windows only — the separator is ';' here, not ':'
rez-env --paths "C:/studio/packages;C:/studio/local" foo -o context.rxt
package.py should be written with forward slashes or with {root}, and joined
with the rex API. A hard-coded backslash will not survive a move to Linux, and a hard-coded colon
will not survive a move to Windows.Win32 caps a path at 260 characters (MAX_PATH) unless long paths are enabled. Rez paths are
deep by construction, so this is a real failure mode and not a theoretical one.
The depth comes from how a variant is laid out. For the filesystem repository the install path is
<repo>/<name>/<version>/<variant subpath>/, and the variant subpath nests one directory per
variant requirement. A package with
variants = [["python-3.11", "pytest-7", "six"]] installs under:
python-3.11\pytest-7\six
Add a deep shared-storage root, a build directory during rez-build, and the package's own
internal tree, and the total passes 260 long before the layout looks unreasonable. A realistic
studio example — a UNC share, a long show name, an eight-requirement variant and a nested Python
package — measures 316 characters, 56 over the limit.
Rez 3.4.0 has a helper for this, rez.utils.filesystem.windows_long_path(), which prefixes the
extended-length marker to lift the limit.
\\?\C:\pkgs\foo # local path
\\?\UNC\server\share\x # UNC path
It is applied internally and selectively — notably in the retry path of robust_rmtree — so do
not assume it covers the operation that just failed for you. Most user-facing operations still go
through ordinary paths.
To enable long paths system-wide on Windows 10 1607 and later, set the registry value
LongPathsEnabled to 1 under HKLM\SYSTEM\CurrentControlSet\Control\FileSystem, or apply the
equivalent Group Policy ("Enable Win32 long paths"). A reboot is required. The extended-length
prefix itself only works on absolute paths with no forward slashes and no . or ..
components, which is why rez applies it to os.path.abspath() output rather than to the path as
written.
Both surface as "rez cannot find or write this path", and they are easy to confuse. Two cheap ways to separate them:
python -c "import os; print(len(os.path.abspath(<path>)))" — and compare against 260.If the path is under 260 and still fails, it is not the length limit — go back to the separator and quoting sections above.
When you cannot enable long paths fleet-wide, the cheapest wins are, in order:
C:\packages beats a deep UNC share).1.14.3+local.2026.10.05 costs more than 1.14.3.Windows resolves add implicit packages that carry the OS identity. On a Windows 11 machine:
rez-config implicit_packages
- ~platform==windows
- ~arch==AMD64
- ~os==windows-10.0.26100.SP0
Three consequences:
platform or os, not off sys.platform at module
scope — see rez-package-pitfalls for why module scope is evaluated on the build machine.os version string is a moving target: a Windows feature update changes ~os, so a variant
pinned to an exact os version stops resolving after an upgrade. Prefer platform.platform_map (default {}) can normalise a platform name across machines when a fleet reports
slightly different values.rez-interpret executes rex and prints the resulting shell code for any registered shell. It never
launches one, which makes it the cheapest way to answer "what will this actually do on cmd?" —
including on a Linux build machine that has no cmd at all.
rez-interpret -c 'env.PATH.prepend("{root}/bin")' -f cmd
rez-interpret -c 'env.PATH.prepend("{root}/bin")' -f pwsh
rez-interpret --no-env -c 'env.FOO = "bar"' -f cmd
-f accepts cmd, gitbash, powershell, pwsh, plus dict and table for a
shell-independent view. --pv marks variables that should be updated rather than overwritten on
first reference — without it, a prepend against a variable rez cannot see looks like a plain
overwrite, which is the most common way to misread this output.
Use it when reviewing a package.py for cross-platform behaviour, and when a one-liner works in bash
but not in cmd.
Rez is installed into the Python it was pip-installed into, so on Windows the entry points land in
that interpreter's Scripts directory rather than a bin directory. Confirm which rez you are
running and where its config comes from:
rez-status
rez-config --source-list packages_path
--source-list prints the config files rez actually read, in order, with real paths. On Windows those
are drive-lettered paths such as
C:\Users\<user>\AppData\Local\Programs\Python\Python312\Lib\site-packages\rez\rezconfig.py. It is
the fastest way to prove a setting is coming from the file you think it is.
PATH. On Windows hosted runners, prefer
actions/setup-python and install rez into it, so the Scripts directory is already on PATH.rez-build --install, then rez-test — but the shell
the runner uses to invoke them differs, which changes quoting. A request with a range
(rez-env 'foo<2') needs single quotes under bash and gitbash, and double quotes under cmd.rez-test-ci for wiring tests
into CI.rez-benchmark timings are not comparable across operating systems; compare Windows to Windows.| Symptom | Cause |
|---|---|
rez-env --shell bash rejected | bash is not registered on Windows; use cmd, gitbash, powershell or pwsh |
| A list variable arrives as one long entry | joined with : on a shell that expects ; (or the reverse) |
PATH grew instead of prepending | compared without --pv; the parent value rez cannot see looks like it was overwritten |
A one-liner works in bash, fails in cmd | quoting differs — single quotes are not quoting in cmd |
| Variant stops resolving after a Windows update | the variant pins an exact ~os version; prefer platform |
| Rez is not found in CI | the install's Scripts directory is not on PATH |
| Paths have the wrong slashes | cmd/pwsh emit backslashes, gitbash emits forward slashes; both are correct for their shell |
| A path fails only when deeply nested | over the 260-character MAX_PATH limit; measure it and shorten the root or the package name |
| A failure survives enabling long paths | probably not length — check separators and quoting instead |
| A package works when built on Windows only | a module-scope value was frozen on the build machine — see rez-package-pitfalls |
get_shell_types), not from memory.rez-config default_shell — empty means detection picked powershell on Windows.append/prepend so the separator is chosen per
shell; never hand-join with : or ;.rez-interpret -f <shell> --pv <VAR> for each shell you must support.platform over an exact os version when a variant needs to differ per OS.rez-config --source-list <setting> to prove which config file a value came from.