How do `nix-legacy` commands work when they are just symbolic links to `nix`?

Hi!

I’ve been trying to write a really trivial wrapper around nix repl that would load up a file containing definitions of pkgs and lib immediately on startup. My reasoning was simply because I use these values often and don’t want to manually type :l <nixpkgs> every startup. The idea was simple, and at first I did a really simple symlinkJoin atop pkgs.nix to replace the binary with my wrapper. What I didn’t expect was commands like nix-env and nix-instantiate to completely stop working.

Taking a closer look, I realized that all the legacy nix commands are actually symlinks to /bin/nix. I couldn’t really understand how that worked, because each command works so distinctly different from plain old nix .... My solution ended up needing to be a binary added via environment.systemPackages that collides with the old /bin/nix binary but won’t affect any of the legacy cli. My question is why? How does this work? What magic is within the symbolic link here that makes this kind of trickery work? I was hoping that knowing this would help me accomplish my goals using symlinkJoin as opposed to what I need to do right now.

The dispatching happens at the very entry point of the nix executable where it reads the program name and decides what to do from there:

But it should be much easier to achieve what you want with a shell alias from nix repl to nix repl --expr '<nixpkgs>'.

https://nix.dev/manual/nix/2.24/command-ref/new-cli/nix3-repl

1 Like

Fascinating! It makes perfect sense, thanks a lot for the information.