There are 3 Types of Dependencies

A friend asked me how I managed a single neovim config across multiple machines when the neovim versions are different. neovim frequently breaks APIs between versions. Writing a single config for multiple versions, even if you never upgrade neovim explicitly, can still be a pain.

The answer is "simple", use the same version across all machines. But managing dependencies are hard. What if one machine runs MacOS, another Ubuntu and yet another Arch Linux? But OS package managers struggle with tools like neovim.

The issue is not specific to neovim. Other tools have the same issue: aws CLIs, delta, rg and direnv.

The 3 Types of Dependencies

I find that there are 3 types of dependencies:

  1. System dependencies (these make sure your computer turns on, can connect to the internet, drivers for your mouse)
  2. Tooling dependencies (your editor, command-line tools, small utilities)
  3. Project dependencies (packages/libraries, react, numpy)

It's not always clear what category a dependency belongs in. For example, is python3.12 a project dependency or tooling dependency? It's usually the former since different projects may each have different versions of python for, at least, a moment in time. It could also be both if any of your tools need python.

As a general rule of thumb,

The crux of the problem is that most machines have a package manager that treats everything like system dependencies. neovim and the program/package that connects you to the internet are controlled by the same system. The issue then roots from how each distro manages packages. Ubuntu takes the approach of slow updates to avoid things breaking. This is nice for system dependencies, annoying for tooling dependencies and (often) hostile for project dependencies.

The difference is fundamental. How do we select versions for each dependency type?

Managing your Tooling Dependencies with asdf

The fix is straightforward: use different package managers for each type of dependency:

How about my tooling dependencies?

There are a bunch of options. But, I'd like to recommend a tool I've come to enjoy using to manage my tooling dependencies, asdf. asdf is a universal version manager, like pyenv or nvm, but for many tools at once. It lets you install and lock versions of editors, languages, and CLIs independently of your system package manager.

For example, I can use asdf to remedy the "neovim versioning problem" I introduced above. The process starts with following the install instructions and then:

$ asdf plugin add neovim  # Add the neovim "plugin" to tell asdf you want it to manage nvim
$ asdf install neovim stable  # Install the stable version (or use a tag like 0.11.4)
$ asdf set --home neovim stable  # Use the stable version of neovim everywhere by default
$ nvim --version  # Now the exact version of neovim I want has been installed
NVIM v0.11.4

The Other Options

For completeness, I should bring up the other options for managing tool dependencies.

pyenv and nvm are tools to manage python and node versions. I would argue that these (almost always) manage project dependencies. Yes, the version of node/npm is a dependency for your project. However, nvm itself is a tool dependency. This highlights one of the drawbacks of tooling dependencies: we don't have many good tools to manage them. pyenv and nvm, as a result, have had to invent their own install processes distinct from your system package manager and the project package manages like pip and nvm.

Another tool, nix, could also be used to manage tooling dependencies. If you think nix (or any other tool for that matter) is great, I'd love to read your post about how you can use it to solve the "neovim version problem" ;).

Conclusion

The "neovim version problem" I presented initially is a case of a more general problem of managing the versions of your tools.

Tooling dependencies are a type of dependency distinct from system and package dependencies. Package managers like apt or npm are best for system and project dependencies, respectively. However, using the system package manager to manage the versions of your tools can create the "neovim version problem".

To remedy the issue, I presented a tool I use, asdf to solve the "neovim version problem". asdf makes design decisions which match the needs of tool dependencies better than apt or npm.