You Have Too Many Package Managers
You’re running Arch. Or Debian. Or macOS with Homebrew bolted on. Whatever the case, your system has at least four things that need updating independently, and you’re running them manually like it’s 2009.
apt update && apt upgrade, okay.
flatpak update, sure.
pip install --upgrade pip, sigh.
cargo install-update -a, wait, I need a plugin for that?
rustup update, oh right, that’s separate.
npm update -g, you’re still doing this?
It’s 2026. You should not be maintaining a personal shell alias that chains fifteen update commands together and breaks every time you install something new. That alias is load-bearing spaghetti and you know it.
Enter Topgrade.
What Topgrade Actually Does
Topgrade is a single binary that detects every package manager, runtime, and update mechanism on your system and runs them all in sequence. One command. Real output. Failures reported cleanly.
It handles:
- System package managers:
apt,dnf,pacman,zypper,apk,brew,nix,winget,scoop,chocolatey - Language runtimes:
cargo,rustup,pip,pipx,gem,npm,yarn,pnpm,go,opam,stack - Flatpak and Snap
- App-layer tools:
mas(Mac App Store),topgradeitself, VS Code extensions, Vim/Neovim plugins, Emacs packages - Custom commands you define yourself
And if it can’t figure out how to update something, it skips it and tells you. No silent failures. No mystery.
It’s written in Rust, installs as a static binary, and the current release as of mid-2026 is Topgrade 15.x. The project lives at github.com/topgrade-rs/topgrade.
Installing It
On Arch/Manjaro (AUR)
yay -S topgradeOr with paru:
paru -S topgradeOn Debian/Ubuntu
No official PPA yet. Grab the binary directly:
curl -s https://api.github.com/repos/topgrade-rs/topgrade/releases/latest \ | grep "browser_download_url.*linux-x86_64.tar.gz" \ | cut -d '"' -f 4 \ | xargs curl -L -o /tmp/topgrade.tar.gz
tar -xzf /tmp/topgrade.tar.gz -C ~/.local/bin/chmod +x ~/.local/bin/topgradeMake sure ~/.local/bin is in your $PATH. If it isn’t, that’s a separate problem you should fix anyway.
On macOS
brew install topgradeYes, Homebrew will also be one of the things Topgrade updates. The snake eats its own tail. It’s fine.
Via Cargo (if you’re already a Rust person)
cargo install topgradeRunning It
topgradeThat’s it. Topgrade detects what’s installed, runs each step, and prints a summary at the end. Steps that succeed show a checkmark. Steps that fail show the error. Steps that aren’t applicable are skipped silently.
Here’s what a typical run looks like on an Arch box with a handful of language runtimes:
[Topgrade]─────────────────────────────────────────────────────System [✔] Arch Linux: Upgrading packages [✔] AUR (yay): Upgrading AUR packages [✔] Flatpak: Updating system packages
Rust [✔] rustup: Updating toolchains [✔] cargo-update: Updating installed binaries
Python [✔] pipx: Upgrading all packages
Node [✔] npm: Upgrading global packages
Miscellaneous [✔] Neovim: Updating plugins (lazy.nvim) [✔] VS Code: Updating extensions
─────────────────────────────────────────────────────Finished. 0 errors.The whole thing takes two to five minutes depending on how stale your system is and how fast your internet connection is. Compare that to running each of those manually, waiting for output, forgetting one, and remembering at 2 AM that you haven’t updated your pip globals in three months.
Configuration
Topgrade reads from ~/.config/topgrade.toml. You probably don’t need to touch it immediately, but here are the parts worth knowing about.
Skip steps you don’t want
Maybe you manage your Neovim plugins yourself, or you don’t want Topgrade touching your npm globals because you know that’ll break something. Skip them:
[misc]disable = ["node", "neovim"]Available step names match what Topgrade prints during a run. Run topgrade --list-steps to see every step name your system has.
Add custom commands
This is where Topgrade gets genuinely useful. You can define your own update commands that run inside the Topgrade flow:
[commands]"Update my dotfiles" = "cd ~/.dotfiles && git pull --ff-only""Sync Helm repos" = "helm repo update""Update kubectl plugins" = "kubectl krew upgrade"These run as regular shell commands and their output is captured like any other step. If the command exits non-zero, it shows up in the failure summary.
Cleanup after upgrades
On Arch, you probably want to clear the package cache after upgrading. Topgrade can do that:
[linux]arch_package_cache_cleanup = trueOn macOS with Homebrew:
[brew]cleanup = trueRequire sudo upfront
If you hate being interrupted mid-run for a sudo prompt, use:
[misc]pre_sudo = trueThis forces a sudo credential refresh at the start so you can walk away and let it finish.
A complete realistic config
Here’s what a reasonably opinionated config looks like for a Linux developer with Rust, Python, and Node in the mix:
[misc]pre_sudo = truecleanup = truedisable = ["flutter", "opam", "stack"]
[linux]arch_package_cache_cleanup = true
[commands]"Update dotfiles" = "git -C ~/.dotfiles pull --ff-only --quiet""Helm repo sync" = "helm repo update 2>/dev/null || true""kubectl krew" = "kubectl krew upgrade 2>/dev/null || true"The || true on optional tools prevents Topgrade from counting a missing binary as a failure. Useful for commands that might not be installed on every machine where you share your config.
Handling Failures Gracefully
Topgrade doesn’t stop on failure by default. It runs everything and reports failures at the end. That’s the right call, a broken pip environment shouldn’t block your Arch system packages from updating.
If you want it to stop on the first failure (useful for scripted/CI scenarios):
topgrade --fail-fastYou can also run a dry-run to see what would happen without doing anything:
topgrade --dry-runThis is handy after you’ve edited your config and want to sanity-check that you haven’t accidentally disabled something important.
Topgrade vs. Your Existing Alias
You probably have something like this in your .bashrc or .zshrc:
alias update='sudo apt update && sudo apt upgrade -y && flatpak update -y && pip install --upgrade pip 2>/dev/null'Honestly, that’s fine for basic cases. But here’s where it falls apart:
It doesn’t adapt. Install Rust next month? Add it to the alias manually, or it won’t be updated. Install pipx? Same thing. Your alias is a static snapshot of your system state at the time you wrote it, which was probably when you first set up the machine and then never touched again.
It has no error handling. One command fails, the whole chain is at best uncertain. You don’t get a clean summary of what succeeded and what didn’t.
It doesn’t handle interactive prompts. Some package managers ask you things. Topgrade knows how to handle these in a non-interactive way for most common tools.
It doesn’t update itself. Topgrade updates Topgrade. Your alias can’t do that.
The alias is a good-enough solution for a system with two package managers. Once you’re running four or five, which is most developer machines these days, Topgrade is the right tool.
Running It Automatically
If you want zero-maintenance updates, you can schedule Topgrade with a systemd user timer or a cron job. For a daily run at 8 AM:
crontab -e0 8 * * * /usr/bin/topgrade --disable neovim --yes 2>&1 | logger -t topgradeThe --yes flag skips interactive confirmations. The logger pipe sends output to syslog so you can check it later with journalctl -t topgrade.
On macOS you can use a launchd plist or just run it in your terminal emulator’s startup config if you open a terminal every morning anyway.
Personally, I don’t run it automatically. I run it when I’m about to start working on something new, as a “let me make sure I’m not on a six-month-old version of something before I debug this.” Takes two minutes while coffee brews.
The One Gotcha Worth Knowing
Topgrade updates things. Sometimes, things break when they’re updated. This is not Topgrade’s fault, it’s the same risk you take when you run apt upgrade or brew upgrade. Topgrade just aggregates the risk into one convenient event.
For most tools, this is fine. For global npm packages or pip packages used by scripts you rely on daily, you might want to exclude those from automatic updates and manage them manually:
[misc]disable = ["node"]Or use pipx instead of pip for globally installed Python tools, since pipx isolates each tool in its own virtualenv. Topgrade handles pipx natively and updates each tool individually. If one breaks, the others are unaffected. This is the right way to manage global Python tooling in 2026, regardless of Topgrade.
Should You Bother?
If your machine has two package managers and you remember to update them regularly, probably not. Your alias is fine.
If your machine has four or more, apt plus flatpak plus cargo plus pipx, or brew plus npm plus gem plus some custom tooling, then yes, absolutely. Topgrade is a fifteen-second install that saves you the mental overhead of remembering to update things you installed three months ago and haven’t thought about since.
It’s the kind of tool that you set up once, run weekly, and then immediately forget about because it just works. The summary at the end is genuinely useful: you’ll catch outdated cargo binaries you forgot you installed, or a VS Code extension that hasn’t updated in months because you always close that prompt.
It’s not magic. It’s just a well-built wrapper around the tools you already have, with better error reporting and zero maintenance overhead. That’s enough.