proto: a pluggable version manager for every language you use
A pluggable multi-language version manager.
At a glance
- What is it?
- proto is a Rust toolchain manager that installs and pins the right version of a language for each project, and it treats Node, Python, Go, Rust, Bun, Deno, Ruby and moon the same way. The parts worth understanding are the shim that intercepts the binaries and the WASM plugin system that lets a new language be added without touching the core.
- Who is it for?
- Adopt proto if you juggle several language toolchains across several projects and want one command that resolves the right version in the right directory, and if you are willing to put the shims on the path. Do not adopt it if a single language with a single version is all you need, since a version manager adds a layer between you and the toolchain.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One tool for every toolchain
proto is a pluggable next-generation version manager for multiple programming languages, described as a unified toolchain. It is written in Rust, published on crates.io, MIT licensed, and the project site is moonrepo.dev/proto with the documentation, the getting started guide and the list of supported tools under the same domain.
The relationship to the wider moonrepo project is stated in one line in the README: proto powers moon's toolchain. So proto is the version management layer for moon. That is a useful signal about the design, because a version manager that a build tool depends on has to be predictable in a way that a personal convenience does not have to be.
The list of supported languages is the clearest statement of the scope. Bun, Deno, Go, moon itself, Node with npm, pnpm and yarn, Python with poetry and uv, Ruby, Rust, and, in the README's phrasing, and more via plugins. The package managers are the detail that matters in practice, because a language runtime without its package manager is half a toolchain, and a team that runs pnpm and a colleague who runs npm is a version of the problem this tool exists to remove.
The release line is dense, with 0.62.3 on 2026-09-22, 0.63.0 on 2026-10-07 and 0.63.1 on 2026-10-08, and the last push was on 2026-10-17.
The seven arguments in the README
The reasons to use proto are listed compactly, and each one names a specific mechanism.
Lightspeed comes first, with the argument that in Rust they can guarantee exceptional performance. That is a claim about the implementation, and the reason the tool can afford to do work on every invocation, such as resolving a version, without the delay a shell script would add.
Multi-language is the second: a single CLI for managing versions for all of your languages. Cross-platform is the third, for a consistent experience across machines and teams, which matters most in a team where the CI runner and your laptop are different operating systems.
Contextual version detection is the fourth and the most substantive: ensuring the correct version of a tool is always used. That is the behaviour that distinguishes a toolchain manager from a version switcher. A switcher changes a global version; contextual detection means the version depends on where you are, so the repository you are in decides.
Checksum verification is the fifth, ensuring a tool came from a trusted source. That is a supply-chain feature, and it is one that most version managers do not offer.
The sixth is that it detects and infers from a language's ecosystem for maximum compatibility, which is how it knows that Node has npm, pnpm and yarn, and that Python has poetry and uv, without you configuring the relationship.
The seventh is the pluggable architecture via WASM, enabling custom integrations. That is the extension model, and it is the subject of its own section here.
The shim is how the version gets applied
The mechanism that makes contextual version detection work is not described in the README, but it is visible in the justfile, and it is the most interesting engineering in the repository.
There is a second binary in the project, proto-shim, built alongside the main one, and the setup-shims target copies it into a shims directory under three different names:
cp -f "$CARGO_TARGET_DIR/debug/proto-shim" ./shims/node
ln -f "$CARGO_TARGET_DIR/debug/proto-shim" ./shims/node-hard
ln -fs "$CARGO_TARGET_DIR/debug/proto-shim" ./shims/node-softThe three names exist because the linking strategy is a choice with trade-offs. The node entry is a copy, the node-hard entry is a hard link and the node-soft entry is a symbolic link. A hard link is invisible to the process, a symlink is a path that can be resolved, and a copy is the bluntest option, so the project ships all three and lets you pick.
Once a shim named after a binary is on your path, the tool that gets run is not the real one. It is the shim, which resolves the version that the current directory context calls for, and then it execs the real binary from the tool cache. The Windows variant of the same target does the equivalent with New-Item and a hard link, a symbolic link and a copy, because the tooling differs there.
The build targets confirm the shape. The normal build compiles the proto binary and the proto-shim binary together with --no-default-features, and there is a separate build-shim target, which suggests the shim can be built and installed on its own.
WASM plugins and how a language gets added
The pluggable architecture via WASM is the feature that makes proto different from a fixed list of supported languages, and the build system shows exactly how it works.
There is a plugins/ directory with its own Cargo workspace, and the justfile has a build-wasm target that compiles it for the wasm32-wasip1 target in release mode. The dependency list explains the runtime: extism at a version lower-bounded for consumers, and extism-pdk for writing plugins. Extism is a WASM plugin system, so a proto plugin is a WASM component that gets loaded into the CLI and can extend it.
The boundary between the core and the plugin is visible in the dependency flags. The extism dependency carries the comment that it is lower for consumers, which is about the version of the plugin ABI the core will load, and there is a separate lint-wasm target so the plugin workspace is linted with the same clippy settings as the rest.
Two files at the repository root complete the picture. The .prototools file is the configuration that pins which tool versions a project uses, and the .protolock file is the lockfile for those versions, in the same spirit as a package lockfile. The registry/ directory holds the registry data about the tools themselves, the package/ directory the packaging, and the crates/ directory the workspace members, with the CLI crate as the default member.
The practical consequence is that a language proto does not know about can still be managed, provided someone writes a plugin for it, and the plugin runs in a sandboxed WASM runtime rather than as native code in the CLI.
A Rust workspace with a configuration schema
The Cargo manifest is a workspace with the crates/ directory as its members and the CLI crate as the default, and the dependency list describes the tool's internals.
The command line is clap, and clap_complete is there for shell completion generation. The error reporting is miette, which is why the tool's diagnostics are likely to read better than a stack trace. The terminal interface is iocraft, and the tracing and telemetry stack is opentelemetry with starbase, which also provides the miette integration and the test helpers.
The configuration is schema-driven, with schemars for JSON Schema generation and schematic for the configuration types, which is what lets a tool like proto validate and describe its own settings.
The network stack is reqwest with http2 and vendored TLS, with the comment that openssl is not used but is required for musl builds, and alongside it reqwest-middleware and http-cache-reqwest, so caching of registry responses is part of the design. The crypto side is sha2 and hex for the checksum verification, and pgp is in the dependency list, which is a strong hint that the tool verifies signatures as well as checksums.
There is also docker_credential and oci-client, so credentials for private registries and OCI images are first-class. rmcp is the Model Context Protocol library, and the release and version machinery uses the starbase ecosystem, which also brings the test and release tooling.
The justfile shows the developer loop: check runs cargo check across the workspace, lint runs clippy over all targets, format runs cargo fmt, gen runs the proto_codegen package, and the test targets use cargo nextest with the PROTO_TEST and STARBASE_TEST environment variables set.
An MCP server and a collector for traces
Two capabilities in the manifest are worth a paragraph each, because they are not what you would expect from a version manager.
The first is the Model Context Protocol. rmcp is a dependency, and the justfile has an mcp target that runs the tool's MCP server:
PROTO_NPM_VERSION=* npx @modelcontextprotocol/inspector -- cargo run -- mcpSo proto can be driven by an AI agent through MCP, with the Model Context Protocol inspector as the client for local testing. The rmcp dependency carries the base64 and macros features, and it sits alongside the other MCP tooling in the repository, including the.agents/ and.claude/ directories at the root, which are the instruction files for coding agents working on the project.
The second is observability. There is an otel-collector task in the justfile that starts a collector in Docker with ports 3000, 4317 and 4318 published, mounting the collector configuration from dev/otel/otel-collector.yaml. The OpenTelemetry-based stack in the dependencies, with the tracing integration through starbase, means a tool that resolves versions on every shell command can report what it did.
The end-to-end tests are in the same spirit. The test-e2e target builds the release binaries and runs a shell script under e2e/, and the e2e/ directory is in the repository root next to the dev/ directory for local infrastructure.
Releases, packaging and the project rules
The release cadence is fast, with 0.62.3 on 2026-09-22, 0.63.0 on 2026-10-07 and 0.63.1 on 2026-10-08, and the last push was on 2026-10-17. The version is still in the 0.x range, so the conventional semver promise of stability is not on offer, and a team pinning proto should pin an exact version rather than a range.
The packaging is handled by cargo-dist, with the dist-workspace.toml file at the root configuring it, and there is a Nix flake as well, flake.nix with flake.lock, so the tool can be built both as a distributed binary and through Nix. The rust-toolchain.toml pins the Rust version for the project, and the .cargo/ directory holds the cargo configuration.
The repository also carries a version file at the root, a CHANGELOG.md, a CONTRIBUTING.md, a docs/ directory for the documentation sources that feed the site, and a package/ directory.
The contributor tooling is worth noting, because it is a lot of automation for a project of this size: the .agents/ and .claude/ directories hold instructions for coding agents, the .vscode/ directory holds editor settings, and the justfile is the primary entry point for every task. The init task installs cargo-binstall, cargo-insta, cargo-nextest and cargo-wasi, which tells you the test runner is nextest, the snapshot library is insta, and that the WASM plugin build needs the wasi target tooling.
Editorial conclusion
Adopt proto if you juggle several language toolchains across several projects and want one command that resolves the right version in the right directory, and if you are willing to put the shims on the path. Do not adopt it if a single language with a single version is all you need, since a version manager adds a layer between you and the toolchain. Before you start, look at how the shim is set up on your platform, because the hard link and symlink variants behave differently, and pin the tool versions in the .prototools file so a new contributor gets the same environment as everyone else.
Frequently asked questions
What is proto and which languages does it manage?
It is a pluggable version manager written in Rust, described as a unified toolchain. The supported list is Bun, Deno, Go, moon, Node with npm, pnpm and yarn, Python with poetry and uv, Ruby and Rust, with more available through plugins.
How does proto decide which version of a tool to use?
Through contextual version detection: the correct version of a tool is always used based on where you are, rather than a single global version. It also detects and infers from each language's ecosystem, which is how it knows that Node has npm, pnpm and yarn, and it verifies checksums so a tool came from a trusted source.
How do plugins add support for a new language?
The plugin architecture is WASM based, with the plugins directory built as its own Cargo workspace against the wasm32-wasip1 target. The runtime is extism with the extism PDK for writing plugins, so an integration runs as a sandboxed component rather than as native code in the CLI.
What is the proto-shim and why are there three copies of it?
It is a second binary that stands in for the real tool on the path and resolves the version the current context calls for before running the actual binary. The setup-shims task installs it three ways, a copy as node, a hard link as node-hard and a symbolic link as node-soft, so you can choose the linking strategy.
How is proto released and how fast does it change?
The releases are frequent, with 0.62.3 on 2026-09-22, 0.63.0 on 2026-10-07 and 0.63.1 on 2026-10-08, and the last push was on 2026-10-17. The version is still in the 0.x range, so pin an exact version rather than a range. Packaging uses cargo-dist with dist-workspace.toml, and there is also a Nix flake.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/moonrepo-proto)Was this useful?