'nix-shell: how to specify a custom environment variable?

I'm learning about nixos and nix expressions. In a project folder I created a shell.nix and I when I run nix-shell I want it to preset an environment variable for me. For example to set the PGDATA env var.

I know there are several ways to write nix expression files (I'm not yet used to most of them). Here is my sample:

shell.nix

let 
  pkgs = import <nixpkgs> {};
  name = "test";
in pkgs.myEnvFun {
  buildInputs = [
    pkgs.python
    pkgs.libxml2
  ];
  inherit name;
  extraCmds = ''
    export TEST="ABC"
  '';
 }


Solution 1:[1]

You may also use pkgs.stdenv.mkDerivation.shellHook.

let 
  pkgs = import <nixpkgs> {};
  name = "test";
in pkgs.stdenv.mkDerivation {
  buildInputs = [
    pkgs.python
    pkgs.libxml2
  ];
  inherit name;
  shellHook = ''
    export TEST="ABC"
  '';
 }

Solution 2:[2]

To set environment variable for a nix-shell without creating a new package, shellHook option can be used. As shown in the example from the manual:

shellHook =
  ''
    echo "Hello shell"
    export SOME_API_TOKEN="$(cat ~/.config/some-app/api-token)"
  '';

A full shell.nix example based on my use-case - with go of version 1.18 from unstable channel:

let
  pkgs = import <nixpkgs> {};

  unstable = import <nixos-unstable> { config = { allowUnfree = true; }; };

in pkgs.mkShell rec {
  name = "go-1.18";

  buildInputs = with pkgs; [
    unstable.go_1_18
  ];

  shellHook = ''
    export PATH="$HOME/go/bin:$PATH"
  '';
}

The script also sets name option, which is then shown in the shell prompt (works nicely with Starship shell prompt).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Abdillah
Solution 2 kravemir