tl;dr#

With home manager it really becomes easy to make a deterministic, version controlled tooling setup.

home manager#

Recently I switched jobs, this also meant switching laptops. In the past, I would probably have to spend at least a few hours, maybe a few days, for getting my terminal setup just like I want to.
But I also switched to home manager:

Home Manager is a Nix-powered tool for reproducible management of the contents of users’ home directories. This includes programs, configuration files, environment variables and, well… arbitrary files.

Which meant that I only had to get my home manager config, install nix and after a home-manager switch everything felt right at home.

So instead of having to remember which packages I have installed with homebrew, I have a section in config like this:

home.packages = [
    pkgs.age
    pkgs.argocd
    pkgs.aria2
    pkgs.atuin
    pkgs.bat
    pkgs.bun
    pkgs.claude-code
    pkgs.cmake
    pkgs.codex
    pkgs.cilium-cli
    pkgs.gitui
    pkgs.ghq
    pkgs.go
    pkgs.jq
    pkgs.jjui
    pkgs.jujutsu
    pkgs.k3d
    pkgs.k9s
    pkgs.kind
    pkgs.kustomize
    pkgs.kubectl
    pkgs.kubelogin-oidc
    pkgs.kubectx
    pkgs.lsd
    pkgs.lz4
    pkgs.zoxide
  ]
  ++ (pkgs.lib.optional (!isDarwin) pkgs.esphome)

Which manages all CLI programs I like to have available. Installing or removing a package is just as simple as editing a line in that file and doing a home-manager switch. And because of nix flakes it is deterministic as well. If I update my sources using nix flake update --flake . and some packages break, I can just do a git revert and everything works again. (too bad that I actually need this sometimes, because on macos the packages do seem to break occasionally)

neovim#

And it’s not just useful for managing installed packages, it can also configure them for you. My complete nvim setup is managed with home-manager, which is ALSO deterministic. I no longer run into updated plugins that break, everything is pinned and I’m very happy.

{
  imports = [
    ./core.nix
    ./colorscheme.nix
    ./plugins.nix
    ./treesitter.nix
  ];

  programs.neovim = {
    enable = true;
    defaultEditor = true;
    viAlias = true;
    vimAlias = true;
    vimdiffAlias = true;
  };
}

plugins = with pkgs.vimPlugins; [
      presence-nvim
      lsp_signature-nvim
      auto-save-nvim
      neo-tree-nvim
      nui-nvim
      plenary-nvim
      nvim-web-devicons
      bufferline-nvim
      which-key-nvim
      toggleterm-nvim
      telescope-nvim
      dashboard-nvim
      snacks-nvim
      mason-nvim
      mason-lspconfig-nvim
      nvim-lspconfig
      schema-companion-nvim
      hop-nvim
      vim-repeat
      tiny-glimmer-nvim
    ];

(obviously this is not everything, but you get the gist)

So when I opened vim on my fresh laptop, I was greeted with this nice splash screen:

ervim