Upgrade to Pro — share decks privately, control downloads, hide ads and more …

My 4 months with Nix

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

My 4 months with Nix

Avatar for Akihiro Okuno

Akihiro Okuno

April 21, 2026

More Decks by Akihiro Okuno

Other Decks in Programming

Transcript

  1. My 4 Months with Nix From curiosity to building on

    Nix Akihiro Okuno — Nix meetup #5 ミニ — 2026.04.20 1
  2. Agenda 1. Before Nix — what I was using 2.

    What Changed — Good — devshell, templates, unified config, composability 3. What Changed — Pragmatic choices — what I chose not to do 4. What Changed — Difficulties — conventions, too many options 5. AI Sandbox with Nix — sandlot: isolation for AI-driven development 6. Wrap-up 3
  3. Three Tools, One Goal Managing reproducible dev environments per repository

    chezmoi dotfile management mise dev tool versions environment variables Homebrew everything else Three systems, three config formats, three failure modes 4
  4. From Three Tools to One Dec 2025 — migrated during

    year-end holidays chezmoi → home-manager mise → devshell + direnv Homebrew → nix-darwin (partially — some packages still via brew) # devshell.toml — per-repo dev environment [devshell] name = "sandlot" packages = ["go", "gopls", "golangci-lint", "gofumpt", "gotools"] 5
  5. cd Into a Project, Everything Ready devshell + direnv =

    automatic environment activation $ cd ~/projects/sandlot direnv: loading .envrc Welcome to devshell - sandlot [sandlot] $ Tools, env vars, custom commands — all declared, all activated on cd Leave the directory → environment deactivated No source , no activate , no manual setup 6
  6. nix flake init: Template to Dev Shell in Seconds $

    nix flake init -t github:choplin/nix-templates#go One command, fully configured dev environment: Template Tools included go go, gopls, golangci-lint, gofumpt python python, ruff, pyright rust cargo, rustc, rust-analyzer scala scala-cli, metals, scalafmt ...and nodejs , java , bun , zig 7
  7. One System for OS, User, and Repo Config ┌────────────────────────────────────────────────────────┐ │

    nix-darwin │ │ System defaults, Homebrew casks, services │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ home-manager │ │ │ │ Shell, editor, git, CLI tools │ │ │ │ │ │ │ │ ┌──────────────────┐ ┌─────────────────────┐ │ │ │ │ │ flake + devshell │ │ flake + devshell │ │ │ │ │ │ repo-a │ │ repo-b │ │ │ │ │ └──────────────────┘ └─────────────────────┘ │ │ │ └─────────────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────┘ One language, one tool, every layer of configuration 8
  8. Composable by Design Example: Claude Code needs Node.js, but not

    globally in PATH # claude-code.nix (pkgs.symlinkJoin { name = "claude-code-with-runtimes"; paths = [ claudeWrapper ]; nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/claude \ --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs-fast.nodejs pkgs-fast.bun ]} ''; }) Per-command PATH injection — only claude sees node and bun 9
  9. What I Chose Not to Do Some apps via Homebrew

    / Mac App Store nixpkgs missing or broken (especially GUI apps) — but managed through nix- darwin nix-darwin and home-manager run separately Can integrate, but darwin-rebuild is slow + different lifecycles Dotfiles used as-is, not generated by home-manager Not all options supported — native config files are more practical Not everything needs to be Nix — use it where it adds value 10
  10. Simple Language, Complex Conventions The language Pure, lazy, functional Small

    set of primitives Easy to read Built on top Module system (options, types, mkIf , mkMerge ...) Derivation conventions (phases, hooks, wrappers) Overlays, overrides, callPackage The difficulty is not the language — it's the ecosystem conventions 11
  11. Too Many Paths to the Same Destination Just for "dev

    environment" alone: Tool Source Status nix-shell built-in legacy nix develop built-in (flakes) official numtide devshell community flake-native devenv community high-level devbox Jetify Nix wrapper Fast evolution = strength, but navigation cost for newcomers nix flake itself not yet stable — some samples still use channels My choice: numtide devshell — close to vanilla Nix, but ergonomic enough for daily 12
  12. AI Agents Need Isolation sandlot — isolated sandbox environments for

    AI-driven development (Go + Nix) The tension: AI agents are probabilistic — need isolation from host environment But isolation usually means a degraded dev experience sandlot's approach: Ephemeral VMs — disposable, not precious Your flake.nix defines the environment — full dev experience inside Both AI and human work in the same sandbox 13
  13. Shared Nix Store + Ephemeral VMs Host (macOS) ├── Shared

    Nix Store (case-sensitive APFS sparse image) │ ├── Store VM (persistent, vfkit) │ └── nix-daemon (rw to shared store) │ downloads packages, prefetches flakes │ ├── Sandbox VM-A (ephemeral, vfkit, 10s boot) │ ├── /nix/store ← shared store (virtiofs ro + overlayfs) │ ├── ~/project/ ← git clone --local (virtiofs rw) │ └── nix develop → AI agent / human work │ └── Sandbox VM-B (parallel) └── same structure, independent isolation Nix store model → shared-nothing VMs with zero-cost package availability 14
  14. Nix After 4 Months Good: Declarative, composable, unified — once

    it works, it just works devshell + direnv for repos, home-manager for user, nix-darwin for OS Difficult: Conventions on top of a simple language are steep Too many choices, fast-moving ecosystem, docs lag behind reality Happy with Nix — it's now my foundation for everything from dev environments to AI sandboxes 15