Introduction to asdf
As projects grow, managing different runtimes gets messy. Your Rails app might need Ruby 3.2, a microservice needs Node 18, and a data pipeline needs Python 3.11. Normally you would install separate tools like rbenv, nvm, and pyenv, each with its own setup.
asdf makes this easier by handling all runtimes with one tool. Instead of juggling different managers, you get a single, consistent interface for everything from Ruby to Terraform.
This guide shows you how to install asdf, use its plugins, and manage multiple runtimes smoothly across your projects.
Prerequisites
This article assumes you are on a Linux or macOS system and can use Homebrew. Windows users can access asdf through Windows Subsystem for Linux. Basic command-line familiarity helps, though we'll explain each step clearly.
Before installing asdf, check the official installation guide for system-specific requirements or alternative installation methods for your operating system.
asdf handles runtime installation completely, so you don't need languages pre-installed. The tool downloads, compiles, and configures everything through its plugin system.
Why choose asdf?
Before diving into installation, let's understand what sets asdf apart from language-specific version managers. The tool operates on a plugin architecture that extends to any runtime or tool you need.
Traditional version managers focus on single languages. Working across multiple languages means installing rbenv, nvm, pyenv, and goenv, each with different commands and behaviors. asdf eliminates this friction by providing one consistent command structure across all runtimes.
The plugin system isn't limited to programming languages. You can manage database versions (PostgreSQL, Redis), infrastructure tools (Terraform, kubectl), and build tools (Maven, Gradle) through the same interface. Each plugin follows asdf's conventions, so learning one teaches you how to use them all.
asdf provides three version scopes: global, project-level, and shell-level (current terminal session only). This flexibility helps when testing across versions or temporarily using different runtimes without affecting your project configuration.
The tool stays lightweight by installing only the plugins you actually use, starting minimal and growing based on your needs.
Installing asdf
Installing asdf with Homebrew is straightforward. Homebrew handles the installation and makes updates simple.
Install asdf using Homebrew:
brew install asdf
This installs the latest version of asdf along with its core dependencies. Homebrew places asdf in its standard installation directory and manages the binary for you.
Configure your shell to load asdf. For bash users, add this line to ~/.bashrc
:
echo 'source $(brew --prefix asdf)/libexec/asdf.sh' >> ~/.bashrc
This loads asdf automatically when you start a new bash session.
If you're using zsh, add this to ~/.zshrc
:
echo 'source $(brew --prefix asdf)/libexec/asdf.sh' >> ~/.zshrc
For zsh completions, Homebrew handles the setup if you have completion support configured. If you need to set it up manually:
echo 'fpath=($(brew --prefix asdf)/share/zsh/site-functions $fpath)' >> ~/.zshrc
echo 'autoload -Uz compinit && compinit' >> ~/.zshrc
Restart your terminal or source your shell configuration:
source ~/.bashrc
Verify asdf installed correctly:
asdf version
v0.14.0
This confirms asdf is installed and accessible. You now have the core tool ready, though you haven't installed any plugins yet.
To update asdf in the future, use Homebrew:
brew upgrade asdf
This keeps asdf up to date with the latest features and bug fixes.
Installing and managing plugins
Before you can install any runtime versions, you need to add plugins for the tools you want to manage. asdf maintains an official plugin repository with hundreds of available plugins.
List available plugins:
asdf plugin list all
This displays all plugins in the official repository, showing plugin names and their repository URLs. The list includes major languages, databases, and tools commonly used in development.
Add a plugin for Ruby:
asdf plugin add ruby
initializing plugin repository...
Cloning into '/home/user/.asdf/plugins/ruby'...
asdf clones the Ruby plugin repository into your plugins directory. The plugin is now available but hasn't installed any Ruby versions yet.
Add plugins for other tools you need:
asdf plugin add nodejs
asdf plugin add python
List your installed plugins:
asdf plugin list
nodejs
python
ruby
Each plugin manages its own set of versions independently. You can now install specific versions of Ruby, Node.js, and Python through asdf.
Update plugins periodically to get support for new runtime versions:
asdf plugin update ruby
Or update all plugins at once:
asdf plugin update --all
Plugins occasionally need updates as new versions of runtimes are released or installation methods change.
Remove plugins you no longer need:
asdf plugin remove nodejs
This removes the plugin and all versions you've installed through it, so use this carefully.
Installing runtime versions
With plugins installed, you can now install specific versions of runtimes. asdf provides a consistent interface regardless of which runtime you're installing.
List available versions for a plugin:
asdf list all ruby
This displays all Ruby versions the plugin knows about, including stable releases, preview versions, and older versions. The list can be long, so you might want to filter it:
asdf list all ruby | grep 3.2
Install a specific version:
asdf install ruby 3.2.2
==> Installing ruby-3.2.2...
ruby-build: using readline from homebrew
...
-> make install
==> Installed ruby-3.2.2 to /home/stanley/.asdf/installs/ruby/3.2.2
asdf downloads the Ruby source, compiles it, and installs it in the asdf directory structure. Compilation takes several minutes depending on your machine.
Install multiple versions:
asdf install ruby 3.4.6
asdf install nodejs 22.20.0
asdf install python 3.13.5
List installed versions for a plugin:
asdf list ruby
3.2.2
3.4.6
The output shows which versions you've installed locally. None are active yet because you haven't set any defaults or project-specific versions.
Uninstall versions you no longer need:
asdf uninstall ruby 2.7.4
This removes the installation directory and frees disk space. Each version typically consumes several hundred megabytes.
Setting runtime versions
After installing versions, you need to tell asdf which versions to use in different contexts. asdf provides three levels of version specification, each serving different purposes.
Set a global default version by creating a .tool-versions
file in your home directory:
asdf set -u ruby 3.4.6
The -u
flag tells asdf to set the version in your user home directory (~/.tool-versions
), making Ruby 3.4.6 your default Ruby version across all projects. Global versions provide a fallback when no project-specific version exists.
Verify the version is active:
ruby --version
ruby 3.4.6 (2025-09-16 revision dbd83256b1) +PRISM [x86_64-linux]
Check which version is currently active:
asdf current ruby
Name Version Source Installed
ruby 3.4.6 /home/stanley/.tool-versions true
Set multiple global versions at once:
asdf set -u nodejs 22.20.0
asdf set -u python 3.13.5
Each runtime maintains its own global version independently.
For project-specific versions, navigate to your project directory and set a local version:
mkdir ruby-app && cd ruby-app
asdf set ruby 3.4.6
This creates a .tool-versions
file in the current directory:
cat .tool-versions
ruby 3.4.6
The .tool-versions
file should be committed to version control. When team members with asdf clone your repository, they'll automatically use the correct versions when working in that directory.
Add multiple tools to the same file:
asdf set nodejs 22.20.0
asdf set python 3.13.5
The .tool-versions
file now specifies versions for all three runtimes your project needs.
Test automatic version switching by navigating between directories:
cd ..
asdf current ruby
ruby 3.4.6 /home/stanley/.tool-versions
cd ruby-app
asdf current ruby
ruby 3.4.6 /home/stanley/ruby-app/.tool-versions
The version switches automatically based on the .tool-versions
file asdf finds in each directory.
For temporary version overrides in your current shell session, set an environment variable:
export ASDF_RUBY_VERSION=3.2.2
ruby --version
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
This sets Ruby 3.2.2 for the current terminal session only. The setting disappears when you close the terminal or open a new one. Environment variables help when testing across versions without modifying configuration files.
Working with legacy version files
Many projects use version files from other version managers like .ruby-version
, .node-version
, or .python-version
. asdf can read these files, maintaining compatibility with existing projects.
Enable legacy version file support by configuring asdf:
echo 'legacy_version_file = yes' >> ~/.asdfrc
Now asdf will check for legacy version files when determining which version to use. If it finds both .tool-versions
and .ruby-version
in the same directory, .tool-versions
takes precedence.
Test this with a Ruby project. First, unset any environment variables:
unset ASDF_RUBY_VERSION
cd ~
asdf current ruby
Name Version Source Installed
ruby 3.4.6 /home/stanley/.tool-versions true
Now create a legacy project:
mkdir legacy-app && cd legacy-app
echo "3.2.2" > .ruby-version
asdf current ruby
Name Version Source Installed
ruby 3.2.2 /home/stanley/legacy-app/.ruby-version true
ruby --version
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
asdf read the .ruby-version
file and switched from Ruby 3.4.6 to 3.2.2 automatically. This compatibility makes adopting asdf easier since you don't need to convert all your projects immediately.
The feature works for Node.js .nvmrc
files, Python .python-version
files, and other common version files. Check your plugin's documentation to see which legacy formats it supports.
Final thoughts
asdf replaces multiple version managers with a single tool that works consistently across all your runtimes. Install plugins for the tools you need, set versions at global or project level, and let asdf handle the switching automatically. For more details, check the official documentation.