What asdf Is

The asdf virtual environment manager is what you wish nvm, rbenv, and all the others were. It’s not that it’s that much better than those. It’s just all of them in one. It uses a plugin mechanism to support different environments.

Installation

In theory, asdf can be installed with Homebrew. However, there are additional manual steps required, and potentially several other problems. It makes sense to just go to the asdf instructions and follow those.

That said, on my Mac I have generally installed the Oh My Fish package:

omf install asdf

This adds asdf config to the shell and installs completions. The package has not seen updates for a while, but how often would it need them? Just in case, here is how a direct installation from Github would go:

git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch <current-version>
echo "source ~/.asdf/asdf.fish" >> ~/.config/fish/config.fish
mkdir -p ~/.config/fish/completions
cp ~/.asdf/completions/asdf.fish ~/.config/fish/completions

In either case, there is one configuration add to allow use of pre-existing version files like .ruby-version in projects:

echo "legacy_version_file = yes" >> ~/.asdfrc

There are similar installation methods for other shells, but there is also enough difference that, again, I recommend just following asdf’s instructions.

Usage

This is where asdf pays off: The commands are uniform regardless of the language being managed.

Find, Install, Update, and Remove Plugins and Versions

Using Versions

Like most virtual environment managers, asdf is capable of automatically choosing a version of a language based on the directory. It has it’s own expected file, .tool-versions, but it can also use most other managers’ files such as .ruby-version. See the Installation section above for how this is configured as it is not the default.

The .tool-versions file is a list, one per line, of plugin names and versions to use in the directory where the file is located as well as all child directories. To set defaults for your account, place a .tool-versions file in your home directory.

The tool provides commands to automatically add/change the .tool-versions files:

It is also possible to set the version in the current shell without having or changing a version file using: asdf-shell <plugin-name> <version>. This sets and environment variable named ASDF_<plugin-name>_VERSION. You can use that variable “manually” if you want to set or change a version in a script or for a single command.

Plugins

In Use

elixir
erlang
nodejs
python
ruby
rust
yarn

Available

As of when this was written, the below plugins were available. I cannot speak to how useful some of them would be. For example, 1password—even the CLI—isn’t something that generally needs to be a different version based on the directory you are in. Regardless, there are a ton of potentially useful ones.

1password
R
act
adr-tools
aks-engine
alp
argo
argocd
aria2
asciidoctorj
bat
bazel
binnacle
bitwarden
brig
buildpack
bundler
caddy
ccache
cf
chezscheme
chicken
clojure
clusterctl
cmake
cockroach
concourse
conduit
conform
conftest
consul
container-diff
copper
coq
crc
crystal
cue
dart
deno
dep
desk
dhall
digdag
direnv
dive
dmd
docker-slim
doctl
dome
dotnet-core
dotty
draft
dust
eksctl
elasticsearch
elixir
elm
embulk
emsdk
erlang
esy
etcd
fd
firebase
flutter
fluxctl
fzf
gauche
gcloud
getenvoy
ghq
github-cli
github-markdown-toc
gitui
gleam
gohugo
golang
golangci-lint
gomplate
goss
graalvm
gradle
grails
groovy
grpcurl
guile
hadolint
hamler
haskell
haxe
helm
helm-cr
helm-ct
helm-docs
helmfile
heptio-authenticator-aws
httpie-go
hub
idris
idris2
imagemagick
io
istioctl
java
jb
jbang
jmespath
jq
jsonnet
julia
just
jx
k14s
k3d
k6
k9s
kind
kops
kotlin
kpt
kscript
ksonnet
kube-capacity
kubectl
kubectl-bindrole
kubectx
kubefedctl
kubeseal
kubesec
kubeval
kubie
kustomize
lean
levant
lfe
linkerd
logtalk
lua
luaJIT
maven
mc
meson
micronaut
mill
minikube
minio
minishift
mkcert
mlton
mockery
mongodb
mysql
neko
neovim
nim
ninja
nodejs
nomad
nova
nuclei
oc
ocaml
opam
openresty
operator-sdk
osm
pachctl
packer
php
please
pluto
pnpm
poetry
popeye
postgres
protoc
pulumi
python
racket
rancher
rbac-lookup
rclone
rebar
reckoner
redis
redskyctl
reg
riak
riff
ripgrep
rke
rlwrap
ruby
rust
saml2aws
sbcl
sbt
scala
scenery
serf
shellcheck
shfmt
skaffold
smlnj
snyk
solidity
sops
sopstool
spark
sqlite
starship
stern
swift
swiftlint
swiprolog
talos
tanka
tekton-cli
terraform
terraform-docs
terraform-lsp
terraform-validator
terragrunt
tflint
tfsec
tilt
tmux
trdsql
tridentctl
v
vagrant
vault
velero
vim
wren-cli
yarn
yq
zig
zola