Asdf – An Extendable Version Manager
asdf-vm.com
asdf-vm.com
Isn't there some other part of the keyboard they could have mashed?
I wish this was available out of the box to handle literary 90% of the tools.
Also, I typically pair it with direnv [1] for even more magic.
[0]: https://github.com/Banno/asdf-hashicorp
[1]: https://direnv.net/
Seems like a lot of duplicated work across all these plugins
Can you be more specific? Maybe something's broken.
Direnv breaks referential transparency of the shell. I heavily use my shell history to riff on commandlines I've entered in the past. If direnv is in the mix, my shell pipelines sometimes have to have `cd` in them, often in subshells because that works better for me than pushd/popd.
pyenv/rbenv/asdf do the same thing, but you can have a "global" version pinned and do all your shell-related package installs there, so it doesn't end up being that bad. Though, this still breaks when I happen to be sitting in a directory on my system that has a .python-version file. All of a sudden my "global"ly installed python packages don't work. I greatly prefer tools like pipx / pipsi for this purpose (is there a language-agnostic pipx-alike? or is that nix?) because the shims they install usually work no matter what my shell environment/CWD is.
.... Maybe most of my ire is because my only exposure to direnv is because at least one repo at my day job uses it. For me it's not so much "customize your environment any way you want", it's "oh did you run that command from projectdir/foo instead of projectdir/foo/bar? That doesn't work". Debugging the interactions between people's individual poetry/pipenv/pip/rbenv/direnv/etcetcetc setups and project-based setups is the bane of my work life.
Tools like asdf, direnv, nix-shell, etc. just encapsulate the environment and help set up some guarantees. The referential transparency of shells is something that these tools help enforce, if anything.
I agree that frequent jumping between the fragmented environments is pain point in software development these days. That's due to a lack of tooling to support the new workflow, in my opinion. I hope enough people feel this pain that we see some solutions.
Having an expressive shell like https://starship.rs helps keep you oriented as a sort of HUD. Nix is definitely a life-saver, but you can probably roll your own nix-a-likes. Encapsulate all the "global" precious tools, hardening them against changes in the "local" shell environment. Whether through wrapper scripts, containerization, or what have you, the building blocks are there, the "best practices" are still being created.
(My favorite worth-1000-words picture about that is e.g. here: http://www.tshirtvortex.net/free-magic/)
Thank you for the feedback. I’ll ping the team to let them know about this thread.
The plugins were kept as separate repos - like Heroku Buildpacks, because I never had the time to vet/review them. I had written plugins for Ruby, Node.js, Erlang and Elixir because those are the ones I wanted. I did not expect the project to be active this long or have these many contributors, maintainers and users.
We’ll bring back the readme in the repo with usage instructions.
P.S: Author here. Not an active maintainer except helping clean issues
The only thing I miss from homebrew is the pre-compiled stuff like e.g. Postgres or redis
[0]: https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge...
Eventually moving our Postgres, Redis, etc. to docker is also a solution. Unfortunately node and ruby take a performance hit if you mount them into containers and update loads of files.
Granted, I didn’t try any of this yet, but the more I read about it, the more I want to. You can even build docker images from the .nix file so the CI/CD pipeline will have the exact same environment as all the dev machines.
The general idea is that it installs the binaries and the data into a subdirectory of ~/.asdf, then sets PATH and the other environment variables to point to there. Then pg_ctl start starts the database.
Each project has its own .tool_versions file so you can have different versions of the same database running in parallel. I was doing that with docker containers but this is easier.
I also use the companion n-install [1] utility to get setup very quickly.
One of my favorite things is to quickly start a new shell with a specific version to test something: 'asdf shell python $ver'.
I did try direnv as others mentioned here, but I found it a bit too magical and eventually abandoned it.
[0]: [https://mac.install.guide/ruby/index.html] [1]: [https://learn-rails.com/install-rails-mac/index.html]
Install with Homebrew if you’re building only one project with Ruby (especially if you are a student learning Ruby). If you’re a solo developer and you're juggling multiple projects that can't be updated all at once, use asdf or chruby or rbenv. Choose asdf if you're using multiple languages such as Ruby, Node, and Python; otherwise chruby or rbenv are fine for just managing Ruby versions. Finally, use Docker or Nix if you’re on a team with a complex project environment (for example, Ruby, Node, Redis, and PostgreSQL all in one project).
After giving up on the website I look at the code. It's a shell script. Wonderful.
I'll stick with Nix any day. Or maybe conda.
If you wanna do something quickly to ease the pain of version management, asdf is there, helpful, and ergonomic. But if you want to make version management an issue of the past and fix it for good, nix is the way to go.
So they both have their use. nix just feels more proper.
I have a .tool-versions file in code repo that lists what I need for a project.
elixir 1.2.3
erlang 1.2.3
nodejs 1.2.3
Whenever I `cd` into the folder, asdf automatically uses the right versions for me. I don't have to worry about anything. Razer sharp scalpel of a tool.[0]: https://direnv.net/
.tool-versions means everyone on the team knows which version(s) to use for a project, for anything outside of docker. Auto-install is an awesome feature, too.
The name is off putting to me though, because it’s meaningless. Maybe I could alias it to something like xenv and pretend it didn’t bother me.
It's made collaboration with contractors much easier to just be able to drop a .tool-versions file into a project and know that regardless of what OS each of us are on, we'll have the same language versions.
> asdf is a CLI tool that can manage multiple language runtime versions on a per-project basis. It is like gvm, nvm, rbenv & pyenv (and more) all in one! Simply install your language’s plugin!
For example:
$ asdf global python 3.6.2
$ python -V
Python 3.6.2
$ asdf local python 3.9.1
$ python -V
Python 3.9.1
"asdf local" stores the version to use for the current directory across shells, which is neat. "shell" is for the current session, and "global" is for the system.The supported CLI tools is extendable via plugins: https://asdf-vm.com/#/plugins-all
Main benefit is you no longer need N half-baked utilities fighting over your path and shell completions, just asdf.
And plug-ins mostly re-use other tools, so it's both simple to set up and mostly avoids duplicating effort.
I just checked it a second time and recall now what was turning me off: I found the installation of the node plugin and node super tedious and too much overhead[1], it's just once but yeah, didn't like the the UX (eg reshim), then asdf always forgot my current node version and finally, I was missing a quick ls command for checking out installed node versions and versions/lts-versions available remotely (nvm ls and ls-remote ) without having to checkout the node website or repo.
I cannot speak for other languages but I found it for node rather a bigger step back and for stuff like Mongo—it's in their plugins!—I just use Docker, IDK but asdf feels just wrong for things like Mongo. I usually use node also from the node Docker image and have node versions only locally installed for stuff like coc-vim or when quickly needing the node REPL but anything serious runs in a container with a volume mapped to the project folder.
So, I guess it's rather for languages that do not have a proper version manager and/or folks not into containerization.
> A bill of materials or product structure (sometimes bill of material, BOM or associated list) is a list of the raw materials, sub-assemblies, intermediate assemblies, sub-components, parts, and the quantities of each needed to manufacture an end product. [0]
Later on I ran into still more problems on the m1 and convinced a project manager to take it and got an Intel Mac instead and back to blissful working asdf.
I feel like I keep having to hack together ways to do the same thing when building containers for apps build with asdf. (Github actions, dockerfile, heroku, etc)
We have this great .tool-versions file defining the version of ruby, node, yarn, etc. It's great.
Then we setup github actions to run linting/tests/etc, and we have to define those same versions either explicitly in the .yml or via some hacky shell commands to pull version info into a RUN curl...
It would be great if there was a little more standardization around language versions. Or maybe there is a secret convention that I just haven't heard of yet.
Having a single version manager that manages the versions for numerous tools across different teams has been invaluable.
Use alias.
Although I don't like the name as well as it's only easy to type but nothing really meaningful.
asdf seems like it has much wider support