Core Technology

The key to this entire setup is rtx, which is a clone of asdf in Rust. Both of these projects are runtime version managers, similar to something like rustup for Rust, virtual environments for Python, and sdkman for JVM languages.

What's special about asdf is that its built entirely with shell scripts, and was developed in such a way as to be usable for nearly anything you'd want to get multiple different versions of. My general understanding is that it works through something called shims instead of directly manipulating the PATH environment variable. Rtx instead directly manipulates the PATH, and it does so every time the shell prompt repaints itself.

Here's a breakdown of the script I use to set everything up, the latest version of which can be found in my dotfiles.

Step 0: Install Chezmoi

This might come out of the blue, but the first thing I need to do is install chezmoi, which is the tool I use to manage my dotfiles. My dotfiles contain my configuration files for all the tools I use, including rtx, so it's the first thing I need to get my hands on.

It can be installed with a one-liner that looks like this:

sh -c "$(curl -fsLS" -- init --apply

After this I delete the chezmoi executable that the one-liner downloaded and instead install it through rtx.

Step 1: Install rtx

Rtx has a statically compiled binary available for Linux (and probably other platforms too), which you can get with the following:

curl | sh

Because I run this in a shell script, I also add the following lines to make sure I can use rtx while in this script:

eval "$(~/.local/share/rtx/bin/rtx activate -s bash)"
eval "$(rtx hook-env)"

Once this is done we can now start installing rtx plugins.

Step 2: Install Plugins

I have two asdf plugins that I maintain for myself, one for mold and one for chafa. Normally when you search for available plugins with rtx or asdf it'll return a list of the plugins that match a query. I am not sure how to get my plugins to show up in this list, so as a result I need to install them manually from a URL:

rtx install mold
rtx install chafa

After this I use the following to install the plugins I have defined in my rtx config:

rtx install

My config is located at ~/.config/rtx/config.toml and contains something similar to the following:

neovim = "stable"
rust = "stable"
chezmoi = "latest"
java = "latest"
go = "latest"
node = "20"
kotlin = "1.8"
gradle = "8"
fzf = "latest"
zola = "latest"
poetry = "latest"
cmake = "3.26"
meson = "1.1"
ninja = "1.11"
mold = "1.11"
chafa = "1.12"

experimental = true

This config file is for globally used plugins, but if you look into rtx or asdf more there are ways to override which plugins and what versions of those plugins are meant to be used while in a particular folder.

Before moving on I also re-initialize plugins within this script to make sure that Rust will show up, so I can install the rest of my cli tools with cargo:

eval "$(rtx hook-env)"

Step 3: Install Rust Programs

For installing programs with cargo I use cargo-binstall, which I must first install regularly with cargo:

cargo install cargo-binstall

After this I then install my tools of choice:

cargo binstall -y \
	b3sum \
	bacon \
	bat \
	bottom \
	broot \
	cargo-binstall \
	cargo-docs \
	cargo-tarpaulin \
	cargo-update \
	exa \
	fd-find \
	hexyl \
	hyperfine \
	just \
	kondo \
	names \
	procs \
	ripgrep \
	sccache \
	sd \
	starship \
	tokei \
	topgrade \
	trashy \
	type_buddy \
	watchexec-cli \
	zellij \

Step 4: Install Projectdo

You can find projectdo here. Its main purpose is to provide single letter commands for common project actions. For example, b will be for building, r for running, and t for testing the project. There's support for a number of different build systems, but the one that matters most to me is Cargo for Rust.

I install the latest version from the master branch with:

curl -o ~/.local/bin/projectdo
chmod +x ~/.local/bin/projectdo

Step 5: Install Fish Plugins

I use a couple of different plugins with my shell of choice, fish. I install the fisher package manager and the plugins listed in my config with the following:

if [ -x /usr/bin/fish ]; then
	fish -c "\
curl -sL \
| source && fisher install jorgebucaran/fisher

This only installs fisher if fish is executable, that way if I'm stuck with bash on a particular machine or in a container it won't try and fail.