Nix Developer Shells · Workshop Lektion 7 / Flakes & mkShell

mkShell II: vertieft

Die vier Schlüssel, die du wirklich brauchst: packages, nativeBuildInputs, shellHook, env vars.

Warum das zählt
Eine produktive Dev-Shell ist mehr als eine Tool-Liste: Sie setzt Umgebungs­variablen, gibt beim Betreten eine Begrüßung aus und richtet das Projekt ein. Heute lernst du die Schalter, mit denen aus „ein paar Tools" eine vollständige Arbeitsumgebung wird.

Die Schlüssel von mkShell

Schlüssel Wofür
packages Tools, die du benutzt (go, jq, git). Der Normalfall.
nativeBuildInputs Build-Werkzeuge, die auf der Bau-Maschine laufen (Compiler, pkg-config).
buildInputs Libraries, gegen die das Ziel linkt (openssl, zlib).
inputsFrom „Übernimm die Build-Inputs dieser Pakete" – ideal, um die Shell eines eigenen Pakets zu spiegeln.
shellHook Shell-Befehle, die beim Betreten laufen.
Faustregel zur Wahl Für eine reine Dev-Shell, in der du Tools nutzt, ist packages fast immer richtig. nativeBuildInputs/buildInputs werden wichtig, sobald du kompilierst – also ab den Paket-Lektionen 9–11.

Umgebungsvariablen: jedes Attribut wird zur env var

Das ist der elegante Trick von mkShell: jedes Attribut, das kein reservierter Schlüssel ist und sich zu einem String machen lässt, landet als Umgebungs­variable in der Shell.

      devShells.${system}.default = pkgs.mkShell {
        packages = [ pkgs.go pkgs.jq ];

        # diese beiden werden zu echten env vars:
        GOFLAGS    = "-mod=vendor";
        PROJECT    = "toolbox";

        shellHook = ''
          echo "→ toolbox dev-shell ($PROJECT) bereit"
          export PATH="$PWD/bin:$PATH"
        '';
      };

In der Shell sind dann $GOFLAGS und $PROJECT gesetzt, und der shellHook begrüßt dich und erweitert den PATH. Der mehrzeilige ''…''-String ist genau der aus Lektion 2.

shellHook: das Einrichtungs-Skript

Typische Aufgaben beim Betreten der Shell:

Dein Win Deine toolbox-Shell richtet sich jetzt selbst ein: richtige Tools, gesetzte Variablen, ein Begrüßungs-Hook. Für die meisten Projekte ist das die fertige Dev-Umgebung – es fehlt nur noch das Pinnen (Lektion 8).

Besonderheiten & Stolperfallen

packagesnativeBuildInputs – aber nah dran Für eine reine Tool-Shell verhalten sie sich fast gleich (beide kommen in den PATH). Der Unterschied zählt erst beim Bauen (Cross-Compiling: Host- vs. Ziel-Plattform). Verlier dich jetzt nicht darin – nimm packages, bis du wirklich kompilierst.
Reservierte Namen werden nicht zu env vars packages, shellHook, name & Co. sind Schlüssel von mkShell selbst – die tauchen nicht als Variablen auf. Willst du eine Variable name, brauchst du einen anderen Mechanismus (z. B. im shellHook exportieren).
Kein Compiler nötig? mkShellNoCC pkgs.mkShell zieht standardmäßig eine C-Toolchain herein. Brauchst du keinen Compiler (reine Skript-/Web-Umgebung), spart pkgs.mkShellNoCC diese Abhängigkeit.

Kurz prüfen (aus dem Kopf)

Nicht spicken – Abrufen aus dem Gedächtnis ist genau die Übung, die hängen bleibt.

Wie definierst du in mkShell eine Umgebungsvariable?

Welcher Schlüssel passt für Tools, die du in der Shell nutzt?

Wann läuft der shellHook?

Übung für Teilnehmende

Ziel: Die toolbox-Shell mit env var und Begrüßungs-Hook ausstatten.

  1. Füge deiner mkShell ein Attribut PROJECT = "toolbox"; hinzu.
  2. Ergänze einen shellHook, der beim Betreten "→ $PROJECT bereit" ausgibt.
  3. git add, dann nix develop – siehst du die Begrüßung?
  4. Prüfe in der Shell mit echo $PROJECT, dass die Variable gesetzt ist.

Tipp: Innerhalb des ''…''-Strings benutzt du normale Shell-Syntax mit $PROJECT.

Lösung anzeigen
      default = pkgs.mkShell {
        packages  = [ pkgs.go pkgs.jq ];
        PROJECT   = "toolbox";
        shellHook = ''
          echo "→ $PROJECT bereit"
        '';
      };
# nix develop  →  "→ toolbox bereit"
# echo $PROJECT →  toolbox

Damit ist die Shell „komplett" – als Nächstes machen wir sie mit Lock-Files reproduzierbar.

Primärquelle zum Lesen nixpkgs Manual – pkgs.mkShell. Die maßgebliche Referenz. Lies, wie packages, inputsFrom und env-Attribute behandelt werden – kurz, aber definitiv.
Ich bin dein Teacher. Unsicher, ob etwas in packages oder nativeBuildInputs gehört? Beschreib mir dein Projekt – ich ordne die Tools mit dir zu.
← Lektion 6 · mkShell I Lektion 8 · Lock-Files →
Als Nächstes: Lektion 8 – Lock-Files (flake.lock, pinnen, nix flake update)