Automatic `nix-shell -p` on command not found

When entering a command that’s not installed, Nix’s command-not-found usually provide some suggestion on package options to be installed.

Like this:

$ php artisan
The program 'php' is not in your PATH. It is provided by several packages.
You can make it available in an ephemeral shell by typing one of the following:
  nix-shell -p php
  nix-shell -p php81
  nix-shell -p php83

Is there a command / program that let us choose the package and run the command directly using nix-shell -p? That would be friction-less user experience.

3 Likes

comma is amazing. However, the problem with comma is that you have to know that you do not have the requested package beforehand, or prepend , in front of every command you are not sure whether you have installed or not.

I think the behaviour requested in this particular case would be as follows:

php
php81
php83

is automatically piped into something like fzf (after showing the warning message from above with a prompt whether to try to resolve this automatically). This would give you the option to choose from the suggested packages (and possibly even input a different package name?), the chosen package would then promptly be “installed” with nix shell -c and immediately executed on the previously run command, all within the initial try of running the missing command.

1 Like

I wouldn’t exactly call comma amazing, it glues together the actual amazing projects (nix-index is what’s doing the heavy lifting here).
comma is also unsuitable if there are multiple packages which contain the binary.

Better off using nix-locate -w --top-level --at-root --minimal /bin/<whatever> piped into fzf.
(nix-locate comes from nix-index.)

1 Like

When I open a command with comma it opens a fuzzy window (fzy) and lets me choose which program I want:

$ , php --help
> 
php81.out
php.out
php83.out

I believe this is exactly what OP is requesting: a tool which lets you choose the package from a list and automatically executes it through nix-shell -p.

Note: To open the package in a shell, you need: $ , -s php

Yes, but this probably won’t happen much as I assume you already know the majority of your installed packages. I, for one, know that php is not in my PATH, for example.

Also, some shells like fish can also change the color of the command if it doesn’t find it in the PATH, so you’d know that you need to open it with comma the moment you finish typing it.

I agree that this would actually be cool. If command-not-found finds comma installed then it could pass the packages to it, you choose one from the list and it automatically opens it.

This also seems like a good solution, which we can also pass to a nix shell afterwards:

nix-shell --run "php --help" -p "$(nix-locate -w --top-level --at-root --minimal /bin/php | fzf)"

At this point, though, we’re just re-implementing comma, so why not use that instead?

3 Likes

Depends. Personally, I never remember whether I have those random command line utilities installed, or if I just run them once in the past from within a shell or using comma, for example. Of course, the time spared by implementing something like this is minuscule, but it is always that “sigh, let’s try it again with comma or from within a shell” when some random command fails since I did not install it on this particular machine. Something like running a command forgetting sudo and rerunning the command again with sudo.

This seems to me as the most straightforward approach to resolve the discussed issue. Sounds good.

1 Like

Thank you. I was missing out a while.
Comma seems to be viable. I will try to create a command-not-found script using comma.

I was searching for this functionality as well, and it turns out it is right there and does work.
By setting environment variables NIX_AUTO_RUN and optionally NIX_AUTO_RUN_INTERACTIVE.

source

2 Likes