Zsh Users: how do you manage plugins?


I recently migrated from arch to nixOS and would like to know how you manage your Zsh plugins. I have used ansible to manage my dotfiles in the past, but would like to have more stuff configured declaratevly in my configuration.nix

The plugins I use are these: https://github.com/pinpox/ansible-zsh/blob/0b4da8baf9b209833d19e9b251471c8d6ec34637/files/zsh_plugins

I’m not using home-manager (yet) and I have seem some plugins (but not all of them) are packaged in nixpkgs. Also in nixpkgs are a few zsh plugin-managers, like zplug e.g. but I’m wondering if the plugin-management could be done with nix itself instead of using a manager.

What would be the best way to have them installed and configured as default for all users? Any hints? Any experienced Zsh + NixOS users that would like to share their setup?

1 Like

I’ve configured some oh-my-zsh things as documented at NixOS 23.11 manual | Nix & NixOS - not sure how to load other plugins.

1 Like

I still use zplug. I couldn’t find the convenience of zplug update on nix yet.

But looks like documentation posted by @raboof worth a shot, I hope I can sneak fetchGit without providing a hash.

Thanks, I’ll look into that configs

I used to use antibody when I first migrated, but I found NixOS is a pretty good zsh plugin manager all by itself. You can see starting from my interactiveShellInit, that I actually pull plugins directly from nixpkgs and just source them directly into the global rc.

I really don’t use that many plugins, but since I am really concerned with shell load time, this is an ideal solution, as I don’t have to wait on a plugin manager every time my shell starts. You can see I am using some plugins from oh-my-zsh, for example, without having to actually configure or use the entire oh-my-zsh setup (saving significant load time).

If you want to do something similar, but the plugin you use isn’t in nixpkgs, you could simply define an overlay for it and go from there. Good luck.

Since when I started the thread, I’ve migrated my setup to use nix itself aswell. My current configuration is here: https://github.com/pinpox/nixos-home/blob/58dc8cba602fe6298e7f8802d9d542fea9ece432/modules/shell.nix#L109-L152

I manage my machine’s configuration and my home-manager configs with flakes, so I will be replacing that builtins.fetchGit lines with flake and have the management and updates be done via the flake.lock file.


here is my solution , use home-manager’s zsh.plugins to manage static zsh plugin module


{pkgs, ...}:
with builtins;
  _zplug=( _group: _name : {
    name = "${_name}";
    src = builtins.fetchTarball "https://github.com/${_group}/${_name}/archive/master.tar.gz";
  make_plugin = {group, name , file, ...} : {
    name = "${name}";
    src = builtins.fetchTarball "https://github.com/${group}/${name}/archive/master.tar.gz";
    file = file;
  rec {

    zsh_plugins = {
      zsh-autosuggestions = _zplug "zsh-users" "zsh-autosuggestions";
      zsh-completions= _zplug "zsh-users" "zsh-completions";
      zsh-syntax-highlighting = _zplug "zsh-users" "zsh-syntax-highlighting";
      zsh-history-substring-search = _zplug "zsh-users" "zsh-history-substring-search";
      powerlevel10k = make_plugin { group = "romkatv"; name = "powerlevel10k"; file = "powerlevel10k.zsh-theme";};
      nix-zsh-completions = _zplug "spwhitt" "nix-zsh-completions";
      zsh-vim-mode = _zplug "softmoth" "zsh-vim-mode";
      desyncr-auto-ls = _zplug "desyncr" "auto-ls";
    plugin_list = builtins.attrValues zsh_plugins;


programs.zsh.plugins = with zsh_plugins; trace "++zsh plugin list: ${lib.concatMapStringsSep "," (x: x.name) plugin_list}" plugin_list;


In the nixOS config I hav it like so:

programs.zsh = {
      shellInit = ''
        autoload -U promptinit; promptinit
      interactiveShellInit = ''
        source ${pkgs.zsh-nix-shell}/share/zsh-nix-shell/nix-shell.plugin.zsh
        source ${pkgs.zsh-vi-mode}/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
        source ${pkgs.zsh-you-should-use}/share/zsh/plugins/you-should-use/you-should-use.plugin.zsh

in home manager config I can use the plugins keyword:

programs.zsh = {
      plugins = [
          name = "nix-shell";
          src = "${pkgs.zsh-nix-shell}/share/zsh-nix-shell";
          name = "you-should-use";
          src = "${pkgs.zsh-you-should-use}/share/zsh/plugins/you-should-use";
          name = "zsh-vi-mode";
          src = "${pkgs.zsh-vi-mode}/share/zsh-vi-mode";
          name = "zsh-z";
          src = "${pkgs.zsh-z}/share/zsh-z";

I figured the paths by poking the store with something like find /nix/store -iwholename "*you-should-use*"