Nix Repl : add `builtins.*` to global scope

I would love to have all of the builtins automatically added to my global scope when I’m playing around in Nix Repl. Even a little trick that someone might know so I can add it as a nix repl -E '...' wrapper or something as a shell alias.

I CANNOT be bothered to write builtins. ever again. :joy:

Essentially I want with builtins; or with lib; statements to persist for the life of the REPL. :l <nixpkgs/lib> actually accomplishes this for lib, but it wouldn’t work for actual attributes.

I’d prefer to have something like Haskell’s .ghci file. You can have one in your working directory or your home directory, and each line in the file is used as a command to ghci when it starts up. So you could just add :a builtins to such a file for nix repl

1 Like

Yes!
I might need to spend a weekend to extend it or something. I’m sure its not even a big push. I get the sense that the repl just wasnt developed all that much.

Well, it sounds like you could just write :a builtins as the first line in the REPL.

In any case, you could do something like nix repl <(echo builtins) and this will have the same effect as running :a builtins as the first line.

1 Like

I can’t seem to get this to work. I get:

λ nix repl <(echo builtins)                                                       
Welcome to Nix version 2.2. Type :? for help.

Loading '/proc/self/fd/12'...
error: getting status of '/proc/self/fd/pipe:[183479]': No such file or directory

Huh you’re right, it doesn’t work on NixOS. It works on macOS though. I don’t know what the difference is.

Alternatively you could just create a file with the contents builtins somewhere and then pass that file as an argument to nix repl.

nix repl =(echo builtins) works. Not too sure what nix tries to do with that file that a pipe does not support.

=(echo builtins) must be a zsh thing? That’s certainly not supported by Bash. The Fish equivalent is nix repl (echo builtins | psub) which also works on NixOS. I’m not aware of any Bash equivalent for “write the contents to a temporary file, pass it to the command, and delete the file when the job completes”.

Not meant seriously, but if you don’t want to create a file¹ or use a different shell you could also vastly overengineer this by using a base64-encoded tar.xz passed via file:// URI:

nix repl file://<(echo /Td6WFoAAATm1rRGAgAhARwAAAAQz1jM4Cf/AJFdADEdSVZjYCMVSnMdMhyem4Lxxsmjn4RXoab9vopKoxzV9eZZmo2FmbaJDuB7gNe/VK+gFE5lI3VUCGmKWNs5JxAOhNQCAyaT6ByczZES8wfdfHgKM4oHELnfMJqsA+mNLkgJIDsmut7h6XhJahRCVoqMN/kMT3MWyPOfg830HAcnk/e9xPGvEGeoDy2t1ySKqkAAAAAASMZR5KVyXMgAAa0BgFAAANZnUtqxxGf7AgAAAAAEWVo= | base64 -d)

¹ Well, practically you create files in Nix’s cache and the store :wink:

3 Likes

Clearly someone needs to submit a PR to teach nix repl to accept a data: URI, thus allowing you to say nix repl data:text/plain,builtins. Or maybe just teach it accept plain text URLs in addition to tar.xz ones so you can say file://<(echo builtins).

Or I guess we could figure out why nix repl <(echo builtins) fails and fix it.

I filed an issue for this nix repl failure. I believe the underlying cause is that nix repl resolves the symlink and tries to read the underlying path, instead of just reading from the symlink directly. File as https://github.com/NixOS/nix/issues/2771

You can use an expect wrapper around nix repl that does what you need after it starts. The following always imports builtins:

#!/usr/bin/env nix-shell
#!nix-shell -i expect -p expect
spawn -noecho nix repl {*}$argv
expect "nix-repl> " {
  send ":a builtins\n"
  interact
}

But you can see that it’s easy to add more commands :slight_smile:

2 Likes

I love this answer.
Wildly over engineered/obfuscated solutions to simple peoblems is kind of my aesthetic :joy:

1 Like