Difference between buildInputs and packages in mkShell

I don’t know where you got the answer from, but gcc would not go in the shell that way. If you want to override the C compiler, you override the stdenv (and gcc is the default C compiler on Linux in any case).

The authoritative answer is always in the code; I think @TLATER’s explanation does a good job of explaining the code and the reasoning behind it. Essentially mkShell is just a specialized case of stdenv.mkDerivation which exposes two more args: packages (nativeBuildInputs alias) and inputsFrom (a list of packages to pull inputs and shell hooks from). There’s also mkShellNoCC which is the stdenvNoCC.mkDerivation counterpart if you don’t need a C compiler.

If you want the general difference between nativeBuildInputs, buildInputs, etc., I discussed it further here: Frustrations about splicing - #21 by waffle8946