Managing toolchains
You'll learn:
- How to pin Node, Python, Rust (and more) per repo.
- What Versionx's shim layer actually does.
- How to install, update, and remove runtimes.
- How to share a set of pins across a fleet.
Prerequisites: Versionx installed; versionx install-shell-hook run once.
Pin a runtime
In versionx.toml:
[runtimes]
node = "22.11.0"
python = "3.13.1"
rust = "1.95"
Versions can be exact (22.11.0), minor-loose (22), semver ranges (^22.11), or latest-in-channel (lts, stable, nightly where meaningful).
Open a new shell inside the repo. node --version resolves to the pinned version via the Versionx shim. When you leave the directory, PATH behavior depends on global defaults (see below).
How shims work
Versionx prepends a single shim directory to your PATH ($XDG_DATA_HOME/versionx/shims on Linux, ~/Library/Application Support/versionx/shims on macOS, %LOCALAPPDATA%\versionx\shims on Windows). Each shim is a tiny native binary that looks up the right version by:
- Looking up from the current directory for a
versionx.toml. - Falling back to the user's global
config.toml. - Dispatching to the real binary in the runtime cache.
Cold-path dispatch is sub-millisecond — the shim uses an mmap'd PATH cache so it doesn't need to parse TOML on every call.
Install what's pinned
versionx sync
Installs every pin in versionx.toml that isn't already cached. Existing installs are not re-downloaded.
Install a specific runtime at a specific version:
versionx install node 22.11.0
List what's installed:
versionx list
Switch versions
Edit versionx.toml. The shim picks up the change immediately — no shell reload needed. versionx install (or versionx sync) will pull the new version if it isn't cached.
You can also override on the command line for one invocation:
versionx run --node 20 -- npm test
Global defaults
Per-user defaults live in $XDG_CONFIG_HOME/versionx/config.toml:
[runtimes]
node = "lts"
python = "3.13"
Used when you're outside any versionx.toml-scoped directory. Repo pins always override globals.
Package manager pinning
Node package managers (pnpm, yarn) and Python package managers (uv, pipx) are pinnable as first-class runtimes:
[runtimes]
node = "22"
pnpm = "9.15.4"
uv = "0.5.8"
Versionx installs them as real binaries — not via corepack (which is being removed in Node 25+).
Clean up
Remove a runtime you no longer use:
versionx uninstall python 3.12.7
Prune runtimes not referenced by any known repo:
versionx prune --dry-run # show what would be removed
versionx prune
Sharing pins across a fleet
For multiple repos that should share a toolchain baseline, put the pins in a fleet config:
# In your ops repo: platform-ops/versionx-fleet.toml
[runtimes]
node = "22"
python = "3.13"
Downstream repos inherit:
# In each repo: versionx.toml
[workspace]
inherit = ["fleet://acme-platform/baseline"]
See Multi-repo & monorepos for how the fleet config is resolved.
Troubleshooting
command not foundinside a repo. Runversionx doctor. Likely the shim directory isn't on PATH — check your shell rc has theversionx install-shell-hookline.- Version mismatch.
versionx currentprints the authoritative resolution with the reason ("from ./versionx.toml line 4", "from global ~/.config/versionx/config.toml", etc.). - Slow first run of a tool. First invocation of a newly-installed runtime pays a shim cache rebuild cost (~5ms). Subsequent runs are sub-ms.
See also
versionx.tomlreference —[runtimes]schema.- Adding a runtime installer — if you want to add a language Versionx doesn't support yet.