Moving to asdf: A Developer's Guide to Simplifying Version Management
TL;DR
nah fr, juggling multiple version managers like nvm, rbenv, gvm, and brew for different languages is actual pain. I switched to asdf and it’s been a game changer - one CLI to manage ALL my runtime versions (Node.js, Ruby, Go, Python, you name it). It’s faster, cleaner, and way less mental overhead. Here’s why you should make the switch too.
The Pain Was Real
Let’s be honest - before asdf, my dev setup was lowkey chaotic:
- nvm for Node.js
- rbenv for Ruby
- gvm for Go
- pyenv for Python
- brew for PHP and other random tools
Each had their own commands, config files, and weird quirks. My shell took forever to load because of all the version managers sourcing their scripts. Plus, keeping track of different syntax across tools? That hits different when you’re context switching between projects.
Enter asdf: The One Tool to Rule Them All
asdf is basically a universal version manager with a plugin architecture. Instead of managing separate tools, you get one consistent interface for everything. Think of it as the npm/yarn of version managers.
Key Benefits That Actually Matter
- Single CLI interface - no more remembering if it’s
nvm useorrbenv local - One config file (
.tool-versions) per project - Way better performance - no more 2-second shell startup delays
- Plugin ecosystem - supports literally everything you need (at least for me) (Node.js, Ruby, Go, Python, PHP, and more)
Migration Made Easy
From nvm (Node.js)
If you’re coming from nvm, the migration is pretty straightforward:
Old way:
# .nvmrc
16.14.0
New way:
# .tool-versions
nodejs 16.14.0
From rbenv (Ruby)
Old way:
# .ruby-version
3.1.0
New way:
# .tool-versions
ruby 3.1.0
From gvm (Go)
Old way:
gvm use go1.19 --default
New way:
# .tool-versions
golang 1.19.0
The best part? asdf can read legacy version files (.nvmrc, .ruby-version, etc.) if you set legacy_version_file = yes in your ~/.asdfrc. This means you can migrate gradually without breaking existing projects.
Essential Commands You’ll Actually Use
Here are the commands I use daily (no cap, these are the ones that matter):
Plugin Management
# Add a new language
asdf plugin add nodejs
asdf plugin add ruby
asdf plugin add golang
# List available plugins
asdf plugin list all
# Update plugins
asdf plugin update --all
Version Installation
# See available versions
asdf list all nodejs
asdf list all ruby
# Install specific version
asdf install nodejs 18.17.0
asdf install ruby 3.2.0
# Install from .tool-versions file
asdf install # installs all tools defined in current dir
Setting Versions
# Set default for your home directory (formerly 'global')
asdf set --home nodejs 18.17.0
# Set project version in this directory (.tool-versions)
asdf set ruby 3.2.0
Checking Current Setup
# See current versions
asdf current
# See what's installed locally
asdf list nodejs
asdf list ruby
# Check where tool is installed
asdf where nodejs 18.17.0
The Magic .tool-versions File
This is where asdf really shines. One file to define all your project’s runtime requirements:
# .tool-versions
nodejs 18.17.0
ruby 3.2.0
golang 1.20.0
python 3.11.0
When you cd into a project directory, asdf automatically switches to these versions. No more forgetting to switch environments!
Real Talk: Installation and Setup
macOS Installation
# Using Homebrew (recommended)
brew install asdf
# Add to your shell config (~/.zshrc or ~/.bashrc)
echo '. /opt/homebrew/opt/asdf/libexec/asdf.sh' >> ~/.zshrc
Linux Installation
# Clone the repo
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.18.0
# Add to shell config
echo '. ~/.asdf/asdf.sh' >> ~/.bashrc
echo '. ~/.asdf/completions/asdf.bash' >> ~/.bashrc
First Project Setup
# Install plugins you need
asdf plugin add nodejs
asdf plugin add ruby
# Install versions
asdf install nodejs latest
asdf install ruby latest
# Set up your project
echo "nodejs 18.17.0" >> .tool-versions
echo "ruby 3.2.0" >> .tool-versions
# Install project dependencies
asdf install # reads .tool-versions and installs missing versions
Pro Tips That’ll Save You Time
1. Auto-install Missing Versions
Add this to your shell config for automatic version installation:
# Auto-install missing versions when entering directories
asdf_auto_install() {
if [[ -f .tool-versions ]]; then
asdf install
fi
}
cd() { builtin cd "$@" && asdf_auto_install; }
2. Global Package Management
When you install global packages (like npm install -g typescript), you might need to reshim:
asdf reshim nodejs # after installing global npm packages
3. Legacy Compatibility
Enable legacy file support in ~/.asdfrc:
legacy_version_file = yes
Now asdf will read .nvmrc, .ruby-version, etc. files automatically.
4. Plugin-specific Config
Some plugins need extra setup. For Node.js, you might want:
# Import Node.js release team's OpenPGP keys
bash -c '${ASDF_DATA_DIR:=$HOME/.asdf}/plugins/nodejs/bin/import-release-team-keyring'
Why This Actually Matters
Beyond the obvious convenience, asdf solves real problems:
Team Synchronization: Everyone runs the exact same versions defined in .tool-versions. No more “works on my machine” issues.
CI/CD Consistency: Your local environment matches production because you’re using the same version definitions.
Context Switching: Jump between projects without thinking about version management. It just works.
Mental Load Reduction: One syntax to rule them all. Less cognitive overhead = more focus on actual coding.
Common Gotchas (And How to Fix Them)
Shim Issues
If commands aren’t found after installation:
asdf reshim <plugin-name>
Plugin Not Found
Always check the plugin repository:
asdf plugin list all | grep <language>
Slow Performance
asdf is generally faster than alternatives, but if you’re experiencing slowness:
- Update plugins:
asdf plugin update --all - Check for conflicting installations
- Make sure you’re not sourcing multiple version managers
The Verdict
Look, I’m not trying to be dramatic, but switching to asdf was genuinely one of those “why didn’t I do this sooner” moments. The setup takes like 10 minutes, and then you never have to think about version management complexity again.
If you’re still juggling multiple version managers in 2025, you’re making your life harder than it needs to be. asdf isn’t just another tool - it’s the tool that makes all other version management tools obsolete.
Give it a try. I guarantee you won’t go back to the old fragmented approach. Your future self (and your teammates) will thank you.
Summary
What we covered:
- Why multiple version managers are pain
- How asdf simplifies everything with one tool
- Easy migration from nvm, rbenv, gvm, etc.
- Essential commands you’ll actually use
- Real setup instructions that work
- Pro tips for power users
Key takeaway: asdf eliminates the complexity of managing multiple version managers while providing better performance and team consistency. It’s 2025 - time to upgrade your workflow.