Machine tools

Register a CLI once, run it from anywhere, on the runtime it actually supports — independently of whatever project you are standing in.

Lifecycle

shell
jrt tool add black pypi:black@latest       # resolve + lock an exact version
jrt tool list                              # everything registered
jrt run black --check .                    # run it (from any directory)
jrt why black                              # locked version, runtime, reason
jrt tool update black                      # re-resolve to the newest compatible version
jrt tool remove black

tool add turns latest (or a range) into one exact version and stores it in the registry. Nothing changes until you run tool update. The first jrt run materializes the tool for the selected runtime; later runs start immediately.

Source format

A source is <ecosystem>:<package>[@version]. The version can be latest, an exact version, or a range.

PrefixRegistryRuns on
npm:npmnode
pypi:PyPIpython
go:Go module proxygo
cargo:crates.iorust
nuget:nuget.orgdotnet
maven:group:artifactMaven Centraljava
bun:npmbun
deno:npmdeno
gem:RubyGemsruby

Useful options

shell
jrt tool add eslint npm:eslint@9 --runtime node@22     # choose the runtime yourself
jrt tool add rg cargo:ripgrep@latest --bin rg          # executable name differs from package
OptionMeaning
--runtime <runtime@version>Pin the tool to this runtime (policy pinned).
--bin <name>Which executable to run when it differs from the package name or the package has several.
--runtime-arg <arg>Extra runtime flag, repeatable. deno: tools only (permission flags).

By ecosystem

Node.js — npm

Exact versions from the npm registry. Each package version × Node runtime gets its own install prefix, so native .node add-ons are built for the runtime that runs them.

shell
jrt tool add desktop-commander npm:@wonderwhy-er/desktop-commander@latest
jrt run desktop-commander

Python — PyPI

Requires-Python is evaluated with PEP 440 rules. Each package version × Python runtime gets its own virtual environment; pip downloads are shared.

shell
jrt tool add black pypi:black@latest
jrt tool add ruff pypi:ruff@latest
jrt run black --version

Go — module proxy

The owning module of a command package is discovered automatically and its go directive is used as the requirement. jrt sets GOTOOLCHAIN=local so a tool cannot swap in a different Go.

shell
jrt runtime install go@1.26
jrt tool add stringer go:golang.org/x/tools/cmd/stringer@latest --bin stringer
jrt run stringer -type=Pill

Rust — crates.io

rust-version (MSRV) maps to the minimum Rust runtime. Builds use --locked with the exact version, so newer transitive dependencies cannot raise the required Rust. Crates without MSRV need --runtime or a compat rule.

shell
jrt runtime install rust@1.85
jrt tool add rg cargo:ripgrep@latest --bin rg
jrt run rg --version

.NET — NuGet tools

DotnetTool packages from nuget.org. The packaged target framework maps to a compatible .NET major, and the tool DLL is executed through the exact selected dotnet runtime.

shell
jrt runtime install dotnet@8
jrt tool add ef nuget:dotnet-ef@latest
jrt run ef --version

Java — Maven Central

Self-contained executable JARs. The minimum Java is derived from the JAR class files, and the JAR SHA-256 is locked at registration and verified before every materialization.

shell
jrt runtime install java@temurin-17
jrt tool add lombok maven:org.projectlombok:lombok@latest
jrt run lombok version

Bun

npm packages run on Bun. Uses engines.bun when published; otherwise the bun: prefix is your explicit opt-in. Installed into a tool-specific root so a project node_modules can never shadow it.

shell
jrt runtime install bun@1.4
jrt tool add cowsay bun:cowsay@latest --bin cowsay
jrt run cowsay "Hello from JRT"

Deno

npm packages run on Deno with no permissions by default. Grant only what the tool needs with --runtime-arg; {DENO_DIR} expands to the managed cache. Runs with a frozen, integrity-checked lockfile.

shell
jrt runtime install deno@2.9
jrt tool add deno-cow deno:cowsay@latest --bin cowsay --runtime-arg "--allow-env" --runtime-arg "--allow-read={DENO_DIR}"
jrt run deno-cow "Hello from Deno"

Ruby — RubyGems

Pure-Ruby gems without runtime dependencies. required_ruby_version (including ~>) selects the runtime, and the .gem SHA-256 is locked and verified. --bin is required.

shell
jrt runtime install ruby@3.4
jrt tool add rake gem:rake@latest --bin rake
jrt run rake --version

Current limits

  • Public registries only: private registries and authentication are not supported yet for any ecosystem.
  • RubyGems: gems with runtime dependencies (e.g. RuboCop) or native extensions are refused.
  • Maven: only self-contained executable JARs (manifest Main-Class, no Class-Path); jrt compat set maven:… is not available yet.
  • Deno: npm-backed CLIs only; JSR and URL-native tools are not supported yet.