I have been using chruby1 for about 2 years. But when I started
in the team I choose chruby because people on my team were using it.
Emacs integration was terrible, because of the way chruby works you
need a plugin. The other viable option seemed to be rbenv2, which was
widely used but I had only ever seen it installed on server. I did
always think that it's model of using shims was a bit better than
chruby that updates the
PATH. The shim model provides better
integration with any program that generates sub-processes, this
because the complexity of managing the interpreters is done with these
wrapper shims instead of burdening the program with being aware beyond
just adding it to your path, you just need to execute from within the
context of the project.
Gradually though, as I started contributing to more projects, and needed more interpreters, it seemed like the list kept growing. Pyenv3 was used for python in a previous job, and then when working in TypeScript, NVM4 was the obvious choice. It's amazing how each language seemed to be solving the same problems over and over.
It's a bad sign when there is so much duplication of effort configuring all the alternative implementations, but they worked for the most part. What made me consider looking for alternatives for was noticed my shell was taking an unreasonable time at start. Maybe 4 seconds to get to the prompt, long enough for me to even think it could be DNS.
Profiling the evaluation of
zshrc is fortunately pretty easy to
do. ZSH has a module that can help with profiling called
can be used like this.
zmodload zsh/zprof # ... the code you want to profile zprof
It outputs a whole lot of timing information, and bam. NVM, there it was, it was most of my startup time. There was an outstanding bug5 it had already been open a few months, so that was what got me looking for alternatives.
I can't remember how I came across ASDF-VM6, it was probably on a news site. But it's a real game changer.
The 2 killer features, are.
- it's a universal interface
- using the shim model
The universal interface is great because it supports more than one ecosystem's tools, I have so far used this for terrafrom, python, nodejs, ruby. Just not having to hunt around for the local languages tool to do this one thing is very helpful.
The shim model is compatible by default with all IDE's and tools, which is great because having to install an associated plugin into every tool to make it work is not really scale able
Each language is expressed as a plugin, so you install a plugin for the interpreters you want to be able to set the version of.
asdf plugin list all
1password-cli https://github.com/NeoHsu/asdf-1password-cli.git act https://github.com/grimoh/asdf-act.git actionlint https://github.com/crazy-matt/asdf-actionlint.git action-validator https://github.com/mpalmer/action-validator.git adr-tools https://gitlab.com/td7x/asdf/adr-tools.git ag https://github.com/koketani/asdf-ag.git age https://github.com/threkk/asdf-age ...
It reminds me a bit of how on supercomputer setups we used a tool called Modules7. We used it in HPC because we wanted to provide multiple versions of all software and libraries.
Listing tool versions
ASDF acts in a similar way for lots of tools which is why you see a list of programs that aren't actually interpreters or compilers in the list above. Once a plugin is installed you can then list all the possible version of it to install.
asdf list all nodejs
... 19.6.1 19.7.0 19.8.0 19.8.1 19.9.0 20.0.0 20.1.0 20.2.0 20.3.0 20.3.1 20.4.0
Installing a specific tool version
Once you know the available versions you can install a specific one, with an install command.
asdf install nodejs 20.4.0
Setting default packages to install
Another cool features is the possibility to install some global packages
for example my
bundler pry pry-doc pry-rescue pry-stack_explorer pry-byebug solargraph rdoc-data
Default tool versions
This gives me some gems by default with each version of the interpreter.
Finally, there is a
~/.tool-versions file that containers the
default interpreter to use if there is no project specified version.
python 3.9.5 nodejs 18.16.1 ruby 2.7.1