Managing bash functions with nix, or somehing equivalent

I want to add a function to make initializing a flake easier, I thought about making a bash function but since I manage my bash shell with home-manager I was wondering if there was a way to create commands/functions in nix home-manager that I can then run in bash, something akin to the following snippet would be nice

  programs.bash = {
    enable = true;
    sessionVariables = {
      DIRENV_LOG_FORMAT="-";
      EDITOR="emacsclient -c";
      commands = [
        {
          name = "flake:init";
          help = "initialize a flake";
          command = ''
            nix flake init -t "~/nixos/flakes#$1"
          '';
        }
      ];
    };
  };

There is the writeShellScriptBin function. You’d have to put it in environment.systemPackages (or similar), something like:

{
  environment.systemPackages = [
    (writeShellScriptBin "flake:init" ''
      nix flake init -t "~/nixos/flakes#$1"
    '')
  ];
}

If you need runtime dependencies you would use writeShellApplication.

Edit: writeShellScriptBin accepts two arguments, not an attrset.

2 Likes

I don’t like that solution. Creating full derivations for this seems wasteful.

You can simply define a function in your rcfiles:

{
  programs.bash.initExtra = ''
    function flake::init {
      nix flake init -t "~/nixos/flakes#$1"
    }
  '';
}

The full power of bash is available to you here, so turning this snippet into a custom module that works as teased in the post is quite doable, but takes some programming.

The benefit of this over the accepted solution is that both the executed functions are lighter (because they don’t need to call out to subshells) and that you’re just concatenating strings rather than building derivations.

The downside is that it’s bash-specific and the syntax requires understanding bash.

1 Like