23 command-line tools, pinned. Tested on 30 distros every commit. fzf, fish, nvim+LazyVim, the whole modern-CLI starter pack — installed silently while you go get a coffee.
wget -qO- https://raw.githubusercontent.com/hiAndrewQuinn/shell-bling-ubuntu/main/install.sh | sh
curl -fsSL https://raw.githubusercontent.com/hiAndrewQuinn/shell-bling-ubuntu/main/install.sh | sh
wget is preferred because it ships in more base images than curl does — fresh Debian 13, for example, has wget but not curl. Either way the script installs curl itself before it needs to fetch anything else, so they're equivalent once it's running.
Drop into a fresh container with the installer already done — kick the tires without touching your real system.
git clone https://github.com/hiAndrewQuinn/shell-bling-ubuntu
cd shell-bling-ubuntu
make dev DISTRO=ubuntu-24.04 # or debian-13, fedora-44, arch, alpine, …
Want it to stick around so you can ssh in from another terminal? make dev-bg DISTRO=… spins it up in the background with sshd on port 2222. Tear down with make dev-down.
Shell Bling never drops a dotfile in your home directory. No .vimrc, no .tmux.conf, no opinionated config.fish. The one exception is the optional LazyVim starter, which is its own scaffolded thing you can ignore or replace.
Where possible we ship zero-config tools that just work — fzf, starship, zoxide, bat, eza, lsd, helix, micro. Where there's a real choice to make, we ship multiple variants side-by-side and let you pick: nvim / vim / hx / micro for editors, lsd + eza for modern ls, xclip + wl-clipboard for the X11/Wayland split. You configure your shell on your own time, in your own way.
foo.bar[3].baz = "…" line per leaf so you can rg / grep / fzf through it with tools you already know. Round-trips back to JSON with gron -u.✓ Docker matrix · ✓ automated VM matrix · ✓ manual VM end-to-end
✓ Docker matrix · ~ automated VM matrix (in progress) · ✗ manual VM
✓ Docker matrix · ✗ automated VM · ✗ manual VM
For legacy-glibc distros, five Rust binaries (bat, fd, eza, lsd, starship) auto-route to their musl variants. You get the same version as on a modern distro, just statically linked.
"Tested on 30 distros every commit" is a real claim. Every push to main kicks off a three-layer test pipeline before anything lands. Here's what each layer catches.
Every commit rebuilds 30 minimal container images — one per supported distro release — and runs the installer end-to-end inside each. Each image starts from the distro's official base, adds only an unprivileged tester user with sudo/wheel/doas, and installs just enough of wget + ca-certificates for the installer to bootstrap itself. Nothing more — we want each container to look like a fresh box, not a curated one.
The container then runs the same wget -qO- … | sh one-liner a real user would, in SHELL_BLING_NONINTERACTIVE=1 mode. A smoke script execs every binary the registry installed (fzf --version, rg --version, nvim --version, fish --version, …) and asserts it returns 0 and prints a sane version. Any non-zero kills the lane.
The Tier 1 / Tier 2 / Tier 3 split above is exactly this matrix's grading rubric — a Tier 1 distro is one where everything passes without softening; a Tier 3 distro is one where the installer detects an ancient glibc and auto-routes a handful of Rust binaries to their musl variants.
Containers are great for catching "does this command exist?" regressions but they don't have systemd, a real init, a desktop session, or the chsh / usermod / cloud-init interactions a fresh install actually hits. So if the container matrix is green, the pipeline fans out to a second matrix against real cloud-init-provisioned VMs.
Each VM lane boots an upstream cloud image (Debian generic-cloud, Ubuntu cloud-img) seeded with a minimal cloud-init drive that adds the tester user and an SSH key, waits for cloud-init to converge, then runs the same wget one-liner + smoke pass over SSH. Result JSON and the full run log get collected back to the build agent — guests stay credential-free, with no in-guest secrets and no in-guest upload step.
Today the VM matrix covers Debian 12/13 and Ubuntu 22.04/24.04/26.04 on amd64 and arm64. Expanding it to the Tier 2 distros is an in-progress work item.
For Tier 1 specifically, every functional change to install.sh also gets a manual run-through on a local libvirt VM with a real desktop session (GNOME on Debian/Ubuntu, the Kali default on Kali). The flow: boot a golden-clean snapshot, paste the wget one-liner, sit through the install, log out, log back in, open a terminal, confirm the new $SHELL, the prompt, the editor picker, and the keybinds all behave. Snapshot back to golden-clean and move on.
This layer is what catches the things automation will never catch — a confusing prompt phrasing, a final message that says the wrong thing, an x-terminal-emulator alternative that didn't take, a desktop session that didn't re-source $SHELL the way the docs claimed it would.
Tier 2 and Tier 3 distros get only the container layer right now. Tier 2 expansion into the VM matrix is a tracked work item. Tier 3 (legacy-glibc) will likely stay container-only — the value there is "the installer doesn't explode on a 2015-era box," not "the modern editor works perfectly under systemd 219."
sudo / doas / root with a usability test, not a "is it on PATH" test — so non-sudoers get a real error message instead of a wasted password prompt.
nvim / vim / hx / micro). Fish becomes your login shell automatically. Skip the picker with SHELL_BLING_NONINTERACTIVE=1.
$SHELL and the new x-terminal-emulator default to take effect. Just reopening a terminal isn't enough on most desktops.