asdf: a version manager to rule them all
Tags: languages, ruby, elixir, node
Published: 2020-02-13 15:11:11

When I started programming in Ruby, I had to install [`rvm`][rvm] (Ruby Version Manager) to use the correct Ruby version for each of the different projects I was in. After some time, I switched to [`rbenv`][rbenv] (yes, that's another Ruby version manager) because `rvm` was too slow. but then a workmate appeared, saying [`chruby`][chruby] (you guessed it, yet another Ruby version manager) was even faster, so I switched again. All was good, flowers were blooming, rainbows appeared in the sky and butterflies... Butterflied? Butterflew? Well, whatever, butterflies did their thing.

Then NodeJS appeared and, of course, I had to install its own version manager. I went with [`nvm`][nvm] (Node Version Manager), but then I switched laptops and I tried [`n`][n], a lighter version manager. I had some problems with it, so I finally went back to `nvm`. Butterflies started getting worried.

Then I started programming in Elixir. Guess my next step.

At this point, butterflies got sad and stopped butterflying.

This setup is not sustainable, for me. I need to keep remembering how to install new language versions, and when setting up a project I need to remember what files each of the version managers use to define what version this project uses. Oh, and I need to actually install all the needed version managers, and you'd probably want to set the version autodiscovery, so you always run the correct language version when changing projects...

"But Marc, you only need to install a new version once in a while, and you can set a project template that adds all the needed files", you might say. And you'd be right, it's not a big deal. But (of course there was a "but", otherwise this post would not make sense) this forces all devs in the project to install a version manager for each of the languages we need, and manually install the correct versions. This doesn't scale well.

Can we do better? Of course we can.

Enter `asdf`!

### Managing the managers

[`asdf`][asdf] is a version manager version manager. No, that's not a typo! With `asdf` you install language version managers, and it offers a common syntax to install language versions:

```shell
asdf plugin-install elixir
asdf plugin-install ruby
asdf install elixir latest
asdf install ruby 2.7.0
```

See? I don't even need to know what version managers it uses, internally. And in your project you can [setup the project language versions][asdf tool versions file] like this:

```none
# .tool-versions
ruby 2.7.0
node 12.8
elixir 1.4.0
```

When `cd`ing to this project, `asdf` will automatically set the correct versions for you. And the best thing is that, if some workmate enters the project and they don't have the dependencies installed they can run this command:

```shell
asdf install
```

And `asdf` will install all the needed managers and versions! You can see the list of plugins [here][asdf plugins]. Be sure to check the official docs for other useful commands!

### Switching to asdf

Switching all your projects to `asdf`, though, might be a little tiring. And maybe not everyone in the team will want to use it (yet). In these cases, `asdf` lets you [fallback to legacy version files][asdfrc file], so that managers that support it fallback correctly (e.g. the `.ruby-version` file for `rbenv`):

```other
# ~/.asdfrc
legacy_version_file = yes
```

### Wrapping up

I hope you see the advantages of using `asdf` in your local machine. It's been a game changer for me, and since I installed it I haven't had any problem remembering how to install new language versions or how to change them.

Thanks for reading!


[rvm]: https://rvm.io/
[rbenv]: https://github.com/rbenv/rbenv
[chruby]: https://github.com/postmodern/chruby
[nvm]: https://github.com/nvm-sh/nvm
[n]: https://github.com/tj/n
[asdf]: https://asdf-vm.com
[asdfrc file]: https://asdf-vm.com/#/core-configuration?id=homeasdfrc
[asdf tool versions file]: https://asdf-vm.com/#/core-configuration?id=tool-versions
[asdf plugins]: https://asdf-vm.com/#/plugins-all