I have recently been trying out NixOS on a second laptop, and have been trying to do development on it. From this I found out about nix-shell and shell.nix files, however I have encountered strange behavior that I cannot explain relating to this.
Originally, I had this as my shell.nix for a zig project:
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/0b4defa2584313f3b781240b29d61f6f9f7e0df3.tar.gz"; # nixos-unstable as of 13 oct 2025
pkgs = import nixpkgs { config = {}; overlays = []; };
# raylib deps GLX, X11, Xcursor, Xext, Xfixes, Xi, Xinerama, Xrandr, Xrender
raylib_deps = with pkgs; [
libx11
libxcursor
libxext
libxfixes
xorg.libXi
xorg.libXinerama
libxrandr
libxrender
];
in
pkgs.mkShellNoCC {
packages = with pkgs; [
zig
] ++ raylib_deps;
}
This installs zig and the dependencies for raylib to build.
However, because it is a NoCC environment, I can’t use it to compile my zig program. Following this I changed pkgs.mkShellNoCC to pkgs.mkShell.
This however cannot add the packages to path.
$ nix-shell
$ zig
zig: command not found
I don’t know how or why this is happening, as everything I know about these 2 functions says they should function the same with respects to this.
This doesn’t reproduce for me. If i use your provided shell.nix and just change it to pkgs.mkShell instead of pkgs.mkShellNoCC, my path contains zig.
[user@host:~]$ whereis zig
zig:
[user@host:~]$ nix-shell
unpacking 'https://github.com/NixOS/nixpkgs/archive/0b4defa2584313f3b781240b29d61f6f9f7e0df3.tar.gz' into the Git cache...
these 2 paths will be fetched (159.10 MiB download, 923.62 MiB unpacked):
/nix/store/idzxmdfd24hcr4aazvpvb91lfxp4m3xs-llvm-20.1.8-lib
/nix/store/q7ym78ggwsd3ahbcamjqafsagvsg9hvi-zig-0.15.1
copying path '/nix/store/idzxmdfd24hcr4aazvpvb91lfxp4m3xs-llvm-20.1.8-lib' from 'https://cache.nixos.org'...
copying path '/nix/store/q7ym78ggwsd3ahbcamjqafsagvsg9hvi-zig-0.15.1' from 'https://cache.nixos.org'...
[nix-shell:~]$ zig
info: Usage: zig [command] [options]
Commands:
build Build project from build.zig
fetch Copy a package into global cache and print its hash
init Initialize a Zig package in the current directory
build-exe Create executable from source or object files
build-lib Create library from source or object files
build-obj Create object from source or object files
test Perform unit testing
run Create executable and run immediately
ast-check Look for simple compile errors in any set of files
fmt Reformat Zig source into canonical form
reduce Minimize a bug report
translate-c Convert C code to Zig code
ar Use Zig as a drop-in archiver
cc Use Zig as a drop-in C compiler
c++ Use Zig as a drop-in C++ compiler
dlltool Use Zig as a drop-in dlltool.exe
lib Use Zig as a drop-in lib.exe
ranlib Use Zig as a drop-in ranlib
objcopy Use Zig as a drop-in objcopy
rc Use Zig as a drop-in rc.exe
env Print lib path, std path, cache directory, and version
help Print this help and exit
std View standard library documentation in a browser
libc Display native libc paths file or validate one
targets List available compilation targets
version Print version number and exit
zen Print Zen of Zig and exit
General Options:
-h, --help Print command-specific usage
error: expected command argument
[nix-shell:~]$ whereis zig
zig: /nix/store/q7ym78ggwsd3ahbcamjqafsagvsg9hvi-zig-0.15.1/bin/zig
Is your modified file 1) named shell.nix, 2) written to disc, 3) in the same folder in which you are calling nix-shell?
EDIT: consider adding a shellHook = "echo 'called into the right shell.nix'"; attribute to your mkShell invocation as a cheap/dirty way to ensure you are calling into the right file
[small@small:~/Documents/Development/threedee]$ whereis zig
zig:
[small@small:~/Documents/Development/threedee]$ cat shell.nix
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/0b4defa2584313f3b781240b29d61f6f9f7e0df3.tar.gz"; # nixos-unstable as of 14 oct 2025
pkgs = import nixpkgs { config = {}; overlays = []; };
# raylib deps GLX, X11, Xcursor, Xext, Xfixes, Xi, Xinerama, Xrandr, Xrender
raylib_deps = with pkgs; [
libx11
libxcursor
libxext
libxfixes
xorg.libXi
xorg.libXinerama
libxrandr
libxrender
];
in
pkgs.mkShell {
packages = with pkgs; [
zig
cowsay
];
# ] ++ raylib_deps;
shellHook = "echo 'called into the right shell.nix'";
}
[small@small:~/Documents/Development/threedee]$ nix-shell
[nix-shell:~/Documents/Development/threedee]$ whereis zig
zig:
[nix-shell:~/Documents/Development/threedee]$ zig
zig: command not found
My file is indeed named shell.nix and is written to disc. It appears however, that the shellHook is not working in the makeShell version specifically. In makeShellNoCC, it outputs as expected. I have no idea what to make of this, as having looked at the definitions for these, this makes no sense.
[small@small:~/Documents/Development/threedee]$ cat shell.nix
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/0b4defa2584313f3b781240b29d61f6f9f7e0df3.tar.gz"; # nixos-unstable as of 14 oct 2025
pkgs = import nixpkgs { config = {}; overlays = []; };
# raylib deps GLX, X11, Xcursor, Xext, Xfixes, Xi, Xinerama, Xrandr, Xrender
raylib_deps = with pkgs; [
libx11
libxcursor
libxext
libxfixes
xorg.libXi
xorg.libXinerama
libxrandr
libxrender
];
in
pkgs.mkShellNoCC {
packages = with pkgs; [
zig
cowsay
];
# ] ++ raylib_deps;
shellHook = "echo 'called into the right shell.nix'";
}
[small@small:~/Documents/Development/threedee]$ nix-shell
called into the right shell.nix
[nix-shell:~/Documents/Development/threedee]$ zig
info: Usage: zig [command] [options]
...
It’s highly suspicious that shellHook doesn’t seem to be called, but why is still confusing.
Weird suggestions - try it in another folder? Try verifying nix store? Try garbage collecting? Try booting into a different generation in case nix itself is somehow weirdly configured? Try on a different account?
Seems a bit unlikely in this case, but one thing that could interfere with PATH inside a nix shell is bash’s init scripts. They still get run inside a nix-shell, and in some environments they may overwrite the PATH value nix-shell set.
Doesn’t explain the difference in behavior between the 2 versions of mkShell, though.
Might be worth trying nix-shell’s --pureoption to avoid any conflicts with the existing environment. Seems to make everything work for me with mkShell
$ cat shell.nix
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/0b4defa2584313f3b781240b29d61f6f9f7e0df3.tar.gz"; # nixos-unstable as of 14 oct 2025
pkgs = import nixpkgs { config = {}; overlays = []; };
# raylib deps GLX, X11, Xcursor, Xext, Xfixes, Xi, Xinerama, Xrandr, Xrender
raylib_deps = with pkgs; [
libx11
libxcursor
libxext
libxfixes
xorg.libXi
xorg.libXinerama
libxrandr
libxrender
];
in
pkgs.mkShell {
packages = with pkgs; [
zig
cowsay
];
# ] ++ raylib_deps;
shellHook = "echo 'called into the right shell.nix'";
}
$ nix-shell --pure shell.nix --command 'zig version'
called into the right shell.nix
0.15.1
The folder change did nothing, and verifying the nix store and garbage collecting did nothing until I rebooted. Now, everything works, and I appear to be unable to reproduce my own issue on older generations, probably meaning that something really weird got corrupted.
For anyone who somehow has the same issue as me, the solution was one of: