Back to Moon

Tool specification

website/docs/proto/tool-spec.mdx

2.4.68.5 KB
Original Source

import HeaderLabel from '@site/src/components/Docs/HeaderLabel'; import VersionLabel from '@site/src/components/Docs/VersionLabel';

<HeaderLabel text="3 min" />

Since proto is a toolchain for multiple tools, each with differing version formats, we must align them on a standard specification that can resolve and store safely. To handle this, we've implemented our own solution called the tool and version specification. This specification currently supports semantic and calendar based versions, each with their own guidelines and caveats.

:::info

If you're implementing a plugin for a specific tool that has a different version format, you'll need to re-format it into one of the specifications below.

:::

Backends<VersionLabel version="0.47.0" />

A backend is an internal system that allows proto to use plugins from 3rd-party package/version managers within proto, greatly expanding the amount of tools that proto can install and support. This functionality is achieved through special WASM plugins under the hood.

To make use of a backend, prefix the tool identifier in .prototools with the backend's unique identifier. For example, we can install Zig via asdf.

toml
# >= v0.52
"asdf:zig" = "0.13.0"

# <= v0.51
zig = "asdf:0.13.0"

asdf

The asdf backend will utilize the asdf version manager for downloading and installing a tool, loading versions, and locating executables. This backend implementation does not use the asdf binary itself, and instead emulates the environment as best we can. Because of this, some tools may not be usable through proto.

toml
"asdf:<id>" = "20"

By default, the ID pinned in .prototools is the asdf shortname used when cloning a repository. If the ID is different than the shortname (node vs nodejs), you can configure the shortname setting.

toml
"asdf:node" = "20"

[tools."asdf.node"]
shortname = "nodejs"

The following settings are supported:

  • shortname (string) - The name of the asdf plugin if different than the configured ID.
  • repository (string) - The Git repository URL in which to locate scripts. If not defined, is extracted from the shortname plugin index.
  • exes (string[]) - List of executable file names (relative from bin) to be linked as a shim/bin. If not defined, we'll automatically scan the bin directory.

cargo<VersionLabel version="0.57.0" />

The cargo backend will install CLIs from crates.io using cargo install under the hood. The ID after the prefix is the crate name as published to the registry.

toml
"cargo:<id>" = "0.31"

For example, to install cargo-dist:

toml
"cargo:cargo-dist" = "0.31"

npm<VersionLabel version="0.57.0" />

The npm backend will install CLIs from the npm registry using the npm package manager under the hood. The ID after the prefix is the package name as published to the registry.

toml
"npm:<id>" = "6"

For example, to install typescript:

toml
"npm:typescript" = "6"

Semantic versions

The most common format is semver, also known as a semantic version. This format requires major, minor, and patch numbers, with optional pre-release and build metadata.

toml
tool = "1.2.3"

Syntax

  • <major>.<minor>.<patch> - 1.2.3
  • <major>.<minor>.<patch>-<pre> - 1.2.3-alpha.0
  • <major>.<minor>.<patch>-<pre>+<build> - 1.2.3-alpha.0+nightly456
  • <major>.<minor>.<patch>+<build> - 1.2.3+nightly456

Guidelines

  • major, minor, patch - 0-9 of any length
  • pre, build - a-z, A-Z, 0-9, -, _, .
    • Must start with a letter or number.
  • A leading v or V prefix is accepted and ignored (v1.2.3).

Learn more about this format!

Calendar versions<VersionLabel version="0.37.0" />

Another popular format is calver, also known as a calendar version, which uses the calendar year, month, and day as version numbers. This format also supports pre-release and build metadata, but with different syntax than semver.

toml
tool = "2025-02-26"

Syntax

  • <year>-<month> - 2024-02
  • <year>-<month>-<day> - 2024-02-26
  • <year>-<month>-<day>-<pre> - 2024-02-26-alpha.0
  • <year>-<month>-<day>+<build> - 2024-02-26+123
  • <year>-<month>-<day>-<pre>+<build> - 2024-02-26-alpha.0+123

Guidelines

  • year - 0-9 of 2-4 length
    • If the year is not YYYY format, it will use the year 2000 as the base. For example, 24 becomes 2024, and 124 becomes 2124.
  • month - 0-9 of 1-2 length
    • Supports with and without a leading zero (02 vs 2).
    • Does not support invalid months (0 or 13).
  • day - 0-9 of 1-2 length
    • Can be omitted, even with pre/build.
    • Supports with and without a leading zero (02 vs 2).
    • Does not support invalid days (0 or 32).
  • pre - a-z, A-Z, 0-9, -, _, .
    • Must start with a letter, so that it is not mistaken for a day number.
  • build - a-z, A-Z, 0-9, -, _, .
    • Uses the same + prefixed build metadata syntax as semver.
  • A leading v or V prefix is accepted and ignored (v2024-02).

:::caution

The dot (2024-02-26.123) and underscore (2024-02-26_123) suffixed "micro" build segments from older proto versions were removed in v0.59. Use build metadata instead, for example 2024-02-26+123.

:::

Learn more about this format!

Version scopes<VersionLabel version="0.59.0" />

Both version formats support an optional scope, which is a named prefix attached to the version with a dash. What a scope represents is defined by each tool's plugin — for example, the built-in Java plugin uses scopes to choose a distribution vendor — but the format itself is universal.

toml
java = "openjdk-21.0.2"
jdk = "temurin-21"

Syntax

  • <scope>-<version> - openjdk-21.0.2, zulu-2026-01-15
  • <scope>-<requirement> - temurin-21, ^zulu-26

Guidelines

  • scope - a-z, A-Z, 0-9, -, _, .
    • Must start with a letter or number.
    • May itself contain dashes, as the scope ends where a valid version or requirement begins. For example, graalvm-community-24.1.2 is the scope graalvm-community with the version 24.1.2.
  • Scopes also work within requirements and ranges, for example temurin-21 || zulu-22.
  • Available version lists are fetched and cached separately for each scope.

Requirements and ranges

Besides an explicit version, we also support partial versions known as version requirements or version ranges. These are quite complex as we need to support both semver and calver in unison, as well as support partial/incomplete numbers (missing patch/day, missing minor/month, etc). We do our best to support as many combinations as possible.

toml
tool-a = "^1"
tool-b = "~2.1"
tool-c = ">=2000-10"

Syntax

  • Requirement - [<op>]<pattern> - 1.2.3, >4.5, ~3, ^2000-10, 1.x, etc
  • AND range - <requirement>[,|&&] <requirement> ... - >=1, <2, >=1 && <2, ^1.3 <=1.3.9, etc
  • OR range - <requirement> || <requirement> ... - ^1.2 || ^2.3, ~2000-10 || ~2010-2, etc

Guidelines

  • op - =, >, >=, <=, <, ~, ^
    • If omitted, defaults to ~ when a partial version is provided (i.e. allow the minimum specified version component to increase)
    • If a full version is provided, defaults to ^ (i.e. allow any newer version that is nominally compatible)
    • To specify an exact version, use the = operator explicitly.
  • pattern
    • Dot-separated semver, with optional minor and patch numbers.
    • Dash-separated calver, with optional month and day numbers.
    • Numbers may be a wildcard (*, x, X) to match any value, for example 1.x or 2024-2-*.
    • May be prefixed with a version scope.
    • Pre-releases may be suffixed to partial versions, but must start with a letter.

For example, if you want to use npm 11.6.2 but 11.6.3 has an issue, use: npm = "^11.6.4 || =11.6.2"