Turmeric Version Manager (tvm)

tvm downloads, caches, and switches between Turmeric compiler releases. It is intentionally close to nvm in spirit: if you know nvm install <v> / nvm use <v>, you already know tvm. Per-user, no root, no system package manager.


Install

From a checkout of the turmeric repo:

sh tvm/install.sh

The installer copies tvm.sh into $TVM_DIR (default ~/.tvm), creates the per-version cache layout under it, and appends a two-line init snippet to your shell rc (~/.zshrc, ~/.bashrc, or ~/.profile):

export TVM_DIR="$HOME/.tvm"
[ -s "$TVM_DIR/tvm.sh" ] && . "$TVM_DIR/tvm.sh"

Open a new shell, or source the snippet directly. After that, tvm is available as a shell function.

Override the install root by exporting TVM_DIR before running the installer:

TVM_DIR="$HOME/.turmeric-vm" sh tvm/install.sh

Quick reference

tvm install 0.24.0              # download + cache the v0.24.0 prebuilt
tvm install --activate 0.24.0   # install + use + set as default, one step
tvm install --build 0.17.0      # build from source against a tag (no prebuilt)
tvm use 0.24.0                  # activate for this shell
tvm use system                  # fall back to whatever `tur` is on PATH
tvm deactivate                  # drop back to the system tur
tvm alias default 0.24.0        # what new shells start with
tvm auto on                     # cd-driven .tur-version auto-switch

tvm current                     # active version
tvm ls                          # installed versions + aliases
tvm ls-remote                   # versions available to download
tvm which 0.24.0                # absolute path to that version's tur
tvm doctor                      # diagnose the setup

tvm run 0.24.0 build .          # one-shot: use a specific version
tvm exec 0.24.0 -- sh -c '...'  # run arbitrary command with that version on PATH
tvm uninstall 0.22.0

tvm completion zsh > _tvm       # shell completion

tvm --help prints the same surface.


Switching: per-shell vs. persistent

tvm use <v> is per-shell. It mutates PATH and TUR_STDLIB_DIR inside the current shell only -- new terminals are unaffected.

tvm alias default <v> is persistent. The alias is written to $TVM_DIR/aliases/default and applied when tvm.sh is sourced in a new shell. Setting default is the closest thing to "install Turmeric system-wide" that tvm offers.

tvm install --activate <v> is the shortcut for "install, use, and set as default" in a single step -- the right move when you are setting up a new machine or bumping the version everyone on the team should be on.

tvm install --activate 0.24.0   # this version, here and in new shells

.tur-version auto-switching

Drop a one-line .tur-version file at a project root and turn on auto mode:

# inside a project
echo 0.23.3 > .tur-version

# once per session (persisted via shell rc reload)
tvm auto on

cd-ing into that directory (or any subdirectory) switches the active compiler to the requested version automatically -- the .nvmrc model. cd-ing back out switches to the previous version (or to your default alias).

tvm auto with no argument prints the current state (on or off). tvm auto off disables it.

The hook is installed into chpwd_functions on zsh and into PROMPT_COMMAND on bash. If you use a non-stock shell setup that overrides those, expect to wire the hook yourself -- tvm doctor will warn when the hook is not attached.


Building from source

When a release tag has no prebuilt asset for your (os, arch) -- old versions, niche targets -- pass --build:

tvm install --build 0.17.0

tvm clones (or reuses) a source checkout under $TVM_DIR/cache/sources/, checks out the tag, runs cmake ... -DCMAKE_BUILD_TYPE=Release, and stages the resulting binary into $TVM_DIR/versions/0.17.0/bin/tur atomically. The bootstrap requires cmake and a C compiler on PATH (same prerequisites as building Turmeric from source by hand).

--build also works with --activate:

tvm install --build --activate 0.17.0

Inspect what's installed

$ tvm current
0.24.0

$ tvm ls
* 0.24.0
  0.23.3
  0.22.0
  aliases:
    default -> 0.24.0

$ tvm ls-remote
  0.24.0   2026-06-23   prebuilt
  0.23.3   2026-06-23   prebuilt
  0.23.2   2026-06-23   prebuilt
  ...

$ tvm which 0.24.0
/Users/you/.tvm/versions/0.24.0/bin/tur

ls-remote reads the release manifest from GitHub Releases and marks each entry prebuilt (host-compatible asset exists) or source (must be installed with --build).


One-shot invocations

When you want to use a non-active version for exactly one command, don't tvm use. Use run or exec:

# one-shot tur invocation: tvm picks the binary, you supply args
tvm run 0.23.2 build my-project/

# arbitrary command with that version on PATH (linters, scripts, CI):
tvm exec 0.23.2 -- bash ./scripts/regen-fixtures.sh

run's arguments after the version are passed verbatim to <TVM_DIR>/versions/<v>/bin/tur. exec sets PATH and TUR_STDLIB_DIR and then execs the command after --.

Useful for CI matrices, bisecting which version introduced a behavior change, or for running just regen-fixtures against an old compiler.


Diagnosing problems: tvm doctor

tvm doctor prints a checklist of common misconfigurations:

$ tvm doctor
tvm: TVM_DIR=/Users/you/.tvm (exists)
tvm: tvm.sh sourced from /Users/you/.tvm/tvm.sh
tvm: active version: 0.24.0 (from `tvm use`)
tvm: default alias: 0.24.0
tvm: auto-switch: on
tvm: chpwd hook attached
tvm: 3 versions installed
tvm: cache size: 47M

Run it any time tvm is not behaving the way you expect, before reporting an issue. Common failures it flags:


Shell completion

tvm completion zsh > ~/.zsh/completions/_tvm
tvm completion bash > /usr/local/etc/bash_completion.d/tvm

Completes subcommands, installed versions for use/which/uninstall, and ls-remote entries for install.


How it works

tvm consumes the artifacts published by .github/workflows/release.yml. Each release ships one tarball per (os, arch):

turmeric-v<tag>-<target>.tar.gz   # target: linux-x86_64 | linux-aarch64 | macos-arm64
  tur                              # the compiler binary
  libturi.a                        # static interpreter library
  include/turi/*.h                 # headers for linking against libturi
  stdlib/                          # stdlib snapshot for that release

tvm install downloads the asset matching the current host, verifies its SHA-256 against the release's sha256sums.txt, and extracts it atomically into $TVM_DIR/versions/<v>/. tvm use then mutates PATH and exports TUR_STDLIB_DIR=$TVM_DIR/versions/<v>/stdlib so the compiler's resource lookup is unambiguous, even for versions installed side-by-side.

Directory layout

$TVM_DIR/                  # default: ~/.tvm
  tvm.sh                   # shell entry point (sourced from your rc)
  versions/<v>/
    bin/tur                # extracted compiler
    lib/libturi.a          # interpreter library
    include/turi/*.h
    stdlib/                # per-version stdlib snapshot
  aliases/
    default                # plain-text file: "0.24.0"
  cache/
    downloads/             # raw tarballs (kept; reuses on reinstall)
    sources/               # source checkout reused by --build

Nothing outside $TVM_DIR is touched, and tvm uninstall <v> removes exactly versions/<v>/ -- no leftover state.


See also