# 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](https://asdf-vm.com/) 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.

[ad-logs]

## 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](https://asdf-vm.com/guide/getting-started.html#_1-install-asdf) 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:

```command
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`:

```command
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`:

```command
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:

```command
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:

```command
source ~/.bashrc
```

Verify asdf installed correctly:

```command
asdf version
```

```text
[output]
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:

```command
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:

```command
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:

```command
asdf plugin add ruby
```

```text
[output]
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:

```command
asdf plugin add nodejs
```
```command
asdf plugin add python
```

List your installed plugins:

```command
asdf plugin list
```

```text
[output]
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:

```command
asdf plugin update ruby
```

Or update all plugins at once:

```command
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:

```command
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:

```command
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:

```command
asdf list all ruby | grep 3.2
```

Install a specific version:

```command
asdf install ruby 3.2.2
```

```text
[output]
==> 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:

```command
asdf install ruby 3.4.6
```
```command
asdf install nodejs 22.20.0
```
```command
asdf install python 3.13.5
```

List installed versions for a plugin:

```command
asdf list ruby
```

```text
[output]
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:

```command
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:

```command
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:

```command
ruby --version
```

```text
[output]
ruby 3.4.6 (2025-09-16 revision dbd83256b1) +PRISM [x86_64-linux]
```

Check which version is currently active:

```command
asdf current ruby
```

```text
[output]
Name            Version         Source                       Installed
ruby            3.4.6           /home/stanley/.tool-versions true
```

Set multiple global versions at once:

```command
asdf set -u nodejs 22.20.0
```
```command
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:

```command
mkdir ruby-app && cd ruby-app
```
```command
asdf set ruby 3.4.6
```

This creates a `.tool-versions` file in the current directory:

```command
cat .tool-versions
```

```text
[output]
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:

```command
asdf set nodejs 22.20.0
```
```command
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:

```command
cd ..
```
```command
asdf current ruby
```

```text
[output]
ruby            3.4.6           /home/stanley/.tool-versions
```

```command
cd ruby-app
```
```command
asdf current ruby
```

```text
[output]
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:

```command
export ASDF_RUBY_VERSION=3.2.2
```

```command
ruby --version
```

```text
[output]
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:

```command
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:

```command
unset ASDF_RUBY_VERSION
```

```command
cd ~
```
```command
asdf current ruby
```

```text
[output]
Name            Version         Source                       Installed
ruby            3.4.6           /home/stanley/.tool-versions true
```

Now create a legacy project:

```command
mkdir legacy-app && cd legacy-app
```

```command
echo "3.2.2" > .ruby-version
```

```command
asdf current ruby
```

```text
[output]
Name            Version         Source                                 Installed
ruby            3.2.2           /home/stanley/legacy-app/.ruby-version true
```

```command
ruby --version
```

```text
[output]
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](https://asdf-vm.com/).