Speeding up nix-shell shebang

Having a single file contains both code and its dependencies is a useful feature provided by nix-shell. However long startup times make it unsuitable for some use-cases.

This example script took 0.5 seconds to run on my machine:

#! /usr/bin/env nix-shell
#! nix-shell -i python -p python

print "Hello world!"

Scripts with more dependencies can take a couple of seconds just to set up the environment.

I’ve found that direnv can cache things up, but it is not a one-file solution as I understand it.

So, is there a way to reduce the startup time of single-file scripts?

6 Likes

For running a single script, I don’t think you have a lot of options to speed it up (it’s doing a lot under the covers, checking if you have the dependencies, creating a new shell, starting a new process). But I think it’s a worthwhile trade-off given you can hand someone a script that needs nasm, python (with certain packages), and other commands; and it will quickly install all the packages from binaries and run the command/script with no fuss. (think of examples where you need to do sudo apt install x y z and now you have that on global environment just to run a script).

On a related note, a common use case for nix-shell is to drop you into an environment with certain commands and variables present. I would recommend direnv + nixify which documentation can be found here. This way, if you nixify $HOME/my_project/ which contains a shell.nix, it will drop you into that shell almost instantly when you do cd $HOME/my_project/(or child directory) and will unload almost instantly when leaving.

I manage my personal script collection with home-manager and use it to “build” all my scripts, thereby only paying the evaluation price at build time (not at runtime):

https://github.com/rycee/home-manager/issues/447

3 Likes