Introduction

Jervis Runtime (jrt) is a runtime-aware CLI router. It keeps every project on the runtime it pins, while machine-level tools run on the runtime they are actually compatible with.

Why jrt exists

Traditional version managers pick one active runtime for your shell. That model breaks as soon as a project and a tool disagree: a legacy app pinned to Node 18 cannot run a CLI that requires Node 22, and a Python 3.11 project forces your formatter onto Python 3.11 too.

jrt answers two questions separately, every time a command runs:

  • Which runtime does this project need? Read from .jrt.toml at the project root.
  • Which runtime does this tool need? Decided from the tool’s locked version, its declared requirements, and known-good compatibility rules.
shell
jrt pin node@18                     # this project stays on Node 18
jrt exec -- node -v                 # v18.x
jrt tool add black pypi:black@latest
jrt run black --version             # runs on its own compatible Python

What you get

  • Per-project pins for node, python, go, rust, dotnet, java, bun, deno and ruby.
  • Isolated machine tools from npm, PyPI, Go modules, Cargo, NuGet, Maven, Bun, Deno and RubyGems — each locked to an exact version and materialized per runtime.
  • Opt-in shims so you can type node or black directly.
  • Migration from .nvmrc, .python-version, asdf, mise and more with jrt import.
  • Offline mode, crash-safe state, and jrt doctor --fix.
  • Signed compatibility bundles for sharing known-good runtime evidence across a team.

How it is built

jrt is a single Go binary. Runtimes are installed and executed through a managed copy of mise that jrt downloads and checksum-verifies itself, so it never depends on whatever mise, nvm or pyenv setup is already on the machine. All state lives in one directory (JRT_HOME).