- The version and enabled features of a tool are identical
- Tools are isolated and unaffected by external sources
- Builds are consistent, reproducible, and hopefully deterministic
Overview
The toolchain manages:- Language runtimes - Node.js, Deno, Bun, Rust, Python, etc.
- Package managers - npm, yarn, pnpm, pip, cargo, etc.
- Build tools - TypeScript, webpack, esbuild, etc.
The toolchain eliminates the “works on my machine” problem by ensuring everyone uses the exact same tool versions.
How it Works
The toolchain is built around proto, our stand-alone multi-language version manager. Moon will piggyback off proto’s toolchain found at~/.proto and reuse any tools available, or download and install them if they’re missing.
Installation Flow
- Moon reads
.moon/toolchains.yml - Checks if required tools exist in
~/.proto/tools/ - Downloads and installs missing tools
- Adds tool binaries to PATH for task execution
Configuration
The tools that are managed by the toolchain are configured through the.moon/toolchains.yml file, but can be overridden in each project with moon.yml.
Basic Configuration
.moon/toolchains.yml
Language-Specific Configuration
Node.js
.moon/toolchains.yml
TypeScript
.moon/toolchains.yml
Rust
.moon/toolchains.yml
Python
.moon/toolchains.yml
Version Specification
As mentioned above, tools within the toolchain are managed by version for consistency across machines. These versions are configured on a per-tool basis in.moon/toolchains.yml. So what kinds of versions are allowed?
Full Versions
A full version is a semantic version that is fully specified, such as1.2.3 or 2.0.0-rc.1. This is the most common way to specify a version, and is preferred to avoid subtle deviations.
.moon/toolchains.yml
Full versions are recommended for production environments to ensure maximum consistency.
Partial Versions
A partial version is a version that is either missing a patch number, minor number, or both, such as1.2 or 1. These can also be represented with requirement syntax, such as ^1.2 or ~1.
.moon/toolchains.yml
~/.proto/tools/<tool>. For example, if the requested version is 1.2 and we have 1.2.10 installed locally, we’ll use that version instead of downloading the latest 1.2.* version.
Otherwise, we’ll download the latest version that matches the partial version, and install it locally.
Aliases
An alias is a human-readable word that maps to a specific version. For example:latestorstablemaps to the latest stable version of a toolcanarymaps to the canary releaseberry(for Yarn) maps to Yarn 2+
.moon/toolchains.yml
Project-Level Overrides
Individual projects can override workspace toolchain versions:packages/legacy/moon.yml
- Legacy projects that can’t be upgraded yet
- Projects with specific runtime requirements
- Gradual migration to new tool versions
Force Disabling
TheMOON_TOOLCHAIN_FORCE_GLOBALS environment variable can be set to true to force moon to use tool binaries available on PATH, instead of downloading and installing them. This is useful for pre-configured environments, like CI and Docker.
This is particularly useful in Docker containers where tools are already installed at specific versions.
Real-World Examples
Monorepo with Multiple Node Versions
.moon/toolchains.yml
packages/legacy-api/moon.yml
TypeScript with Strict Configuration
.moon/toolchains.yml
Multi-Language Workspace
.moon/toolchains.yml
Benefits
Reproducible builds
Reproducible builds
Everyone on the team uses the exact same tool versions, eliminating “works on my machine” issues.
Zero setup for new developers
Zero setup for new developers
New team members don’t need to manually install and configure tools. Moon handles it automatically on first run.
Simplified CI/CD
Simplified CI/CD
CI environments automatically use the correct tool versions without complex setup scripts.
Easy upgrades
Easy upgrades
Upgrade tool versions for the entire team by updating a single config file.
Isolated environments
Isolated environments
Tools are isolated to the workspace and don’t conflict with globally installed versions.
Best Practices
Use full versions in production
Use full versions in production
Always specify full semantic versions (e.g.,
20.14.0) in production to ensure reproducibility.Test upgrades carefully
Test upgrades carefully
When upgrading tool versions, test thoroughly before committing. Consider using a feature branch.
Document version requirements
Document version requirements
If a project requires a specific version, document why in the moon.yml file with comments.
Minimize project overrides
Minimize project overrides
Try to keep all projects on the same tool versions when possible. Use overrides sparingly.
Troubleshooting
Tools not found
If tools aren’t being downloaded:Version conflicts
If you see version conflicts:CI/CD issues
In CI, you may want to cache proto tools:Related Concepts
- Workspace - Where toolchains are configured
- Projects - Can override toolchain versions
- Tasks - Run using toolchain tools