{
  description = "Zsh configuration";

  inputs = {
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      with nixpkgs.legacyPackages.${system}; {
        packages.zsh =
          let
            config = runCommand "zsh-config" {
              nativeBuildInputs = [ makeWrapper ];
            } ''
              mkdir -p $out/share/zsh

              cat <<EOF > $out/share/zsh/.zprofile
              emulate sh -c 'source /etc/profile'
              EOF

              cat <<EOF > $out/share/zsh/.zshenv
              unsetopt GLOBAL_RCS
              EOF

              cat <<EOF > $out/share/zsh/.zshrc
              source ${nix-zsh-completions}/share/zsh/plugins/nix/nix-zsh-completions.plugin.zsh
              fpath+=(${nix-zsh-completions}/share/zsh/site-functions)

              fpath+=(~/.nix-profile/share/zsh/site-functions)

              autoload -U compinit && compinit

              source ${zsh-bd}/share/zsh-bd/bd.plugin.zsh
              source ${zsh-powerlevel10k}/share/zsh-powerlevel10k/powerlevel10k.zsh-theme

              path+=(${lib.makeBinPath [ any-nix-shell ]})

              source ${./config/fzf/fzf.zsh}
              source ${./config/config.zsh}
              source ${./config/p10k.zsh}
              source ${./config/title.zsh}

              if [ -f "\$HOME/.zsh/local.zsh" ]; then
                source "\$HOME/.zsh/local.zsh"
              fi

              # must be last
              source ${zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
              EOF
            '';
          in
          writeScriptBin "zsh" ''
            #!/bin/sh
            export ZDOTDIR=${config}/share/zsh
            for zsh in $(which -a zsh); do
              if [ "$0" = "$zsh" ]; then
                continue
              fi
              exec "$zsh" "$@"
            done
            echo "Could not find system zsh"
            exit 1
          '';

        packages.default = self.packages.${system}.zsh;
      }
    );
}