Documentation is currently for moon v2 and latest proto. Documentation for moon v1 has been frozen and can be found here.
Lockfiles
Lockfiles allow you to lock the exact version (and checksum) of every tool installed in a project, ensuring that all machines — your own, your teammates', and CI — resolve and install identical tools, regardless of when they run. If you've used package managers like npm, Cargo, or uv, the concept is the same, just applied to the tools themselves.
Lockfiles are currently unstable. The functionality works as documented, but behavior and the lockfile structure may change between releases. If you run into any issues, please report them!
Enabling lockfiles
Lockfiles are opt-in, and can be enabled with the
settings.unstable-lockfile setting in a .prototools file.
node = "22"
[settings]
unstable-lockfile = true
Once enabled, a .protolock file will be created in the same directory as the .prototools file,
the next time records are written (typically by proto install). This file
should be committed to your version control system, so that other machines can make use of it.
If the setting is later disabled or removed, the sibling .protolock file will automatically be
deleted the next time proto runs.
How it works
Scopev0.60.0
A lockfile is scoped to the .prototools configuration file in which the setting was enabled.
- The lockfile only tracks tools with versions defined in its sibling
.prototoolsfile. Tools installed ad-hoc (without a configured version) are tracked by the closest configuration file. - Versions defined in nested configuration files are not included in a parent's lockfile. To lock a nested configuration, enable the setting in that file as well.
- Multiple lockfiles can exist within a directory tree (for example, one per project in a monorepo), with each operating independently.
Before v0.60, a lockfile locked its directory and all of its subdirectories, similar to how package manager workspaces function, and defining nested lockfiles would trigger an error.
Records
For each tool, the lockfile stores a list of records, with each record representing an installation for a specific version requirement, operating system, and architecture. Records are grouped by the tool identifier using TOML's array of tables syntax.
# Generated by proto. Do not modify!
[[tools.node]]
os = "linux"
arch = "x64"
spec = "22"
version = "22.17.0"
checksum = "sha256:325c377fbb4e547444a5da404e474fda52eb0adb3bbafcd25eee38e5766a1cfa"
[[tools.node]]
os = "macos"
arch = "arm64"
spec = "22"
version = "22.17.0"
checksum = "sha256:29b8fc16b1d1b0b7d19d444b8fac9e6ca4b39ee01bd097756975f92a25deba71"
Each record supports the following fields:
spec- The version requirement that was requested, typically from a.prototoolsfile.version- The exact version that the requirement resolved to.checksum- A checksum of the installed artifact, prefixed with its algorithm. Builds from source and native installations may not have a checksum.os/arch- The operating system and architecture the record applies to. Since pre-built artifacts differ per platform, a record exists for each combination.backend- The backend the tool was installed with, if applicable.
Records are created and updated when a tool is explicitly installed with
proto install, and removed when uninstalled with
proto uninstall. Do not edit this file manually — proto owns it entirely.
Version resolution
When a version requirement is being resolved — during an install, or when detecting versions for
proto run and shims — proto will first look for a matching record in the
applicable lockfile. A record matches when it has the same requirement (spec), backend, operating
system, and architecture. If a match is found, the exact version from the record is used,
instead of re-resolving the requirement against the tool's available versions.
This is what guarantees determinism: a requirement like node = "22" will keep resolving to the
locked 22.17.0, even after newer 22.x versions have been released. To break out of this and
re-resolve, pass --update-lockfile to proto install, which will skip the
lockfile during resolution, and update the record with the newly resolved version.
$ proto install node --update-lockfile
Checksum verification
When installing a version that has a lockfile record, proto will verify the installation against
that record: the checksum of the artifact must match the locked checksum, and the operating
system and architecture must line up. If they don't, the install fails with an error — ensuring
that the artifact installed on another machine (or in CI) is the same one that was originally
locked.
When a record is migrated to a new version (through the commands below), its checksum is removed, and will be re-populated on the next install.
Lockfile-aware commandsv0.60.0
Beyond installation, lockfiles are integrated across the command line.
proto outdatedandproto statusdisplay a "Locked" column, showing the version locked for each configured requirement, and include alocked_versionfield in their--jsonoutput.proto outdated --updateupdates matching records when writing new versions to their respective configuration files.proto pin(andproto install --pin) migrates matching records to the newly pinned requirement, whileproto unpinremoves them entirely.proto versionslabels versions that have a record with "locked", and includes alockedfield in its--jsonoutput.proto debug configrenders.protolockfiles alongside their sibling configuration files.proto cleandoes not remove records when cleaning stale versions, as the version may still be required by a configuration, or in use on other machines.proto diagnoseaudits the health of lockfiles, reporting warnings for records that are missing a resolved version, duplicate records for the same requirement, and stale records that no longer match a configured version.