A single minimal seed.wsl is published from every push to master. Importing it
gives you a tiny NixOS-WSL bootstrap that, on first interactive login, asks
which identity to take and nixos-rebuild boots into it.
From Windows PowerShell:
$tarball = "$env:USERPROFILE\Downloads\seed.wsl"
Invoke-WebRequest -Uri "https://github.com/tteggel/.dotfiles/releases/latest/download/seed.wsl" -OutFile $tarball
wsl --import thixos "$env:USERPROFILE\WSL\thixos" $tarball
wsl -d thixos
# → at the prompt, type `t` for thixos or `y` for yoloixos (YOLO to confirm)
# → seed stages the chosen config and terminates the distro
wsl -d thixos
# → boots into the chosen identity; init-gh / init-yolo completes setupseed— minimal bootstrap; bash login, NOPASSWD wheel sudo,inputs.selfbaked at/etc/seed-source. Prompts t/y, runsnixos-rebuild switch --flake /etc/seed-source#<choice>(switch, not boot — activation must rewrite/etc/wsl.confnow so the next launch finds the new default user), marks/var/lib/seed-bootstrap.done, thenwsl.exe --terminate $WSL_DISTRO_NAME.thixos— interactive dev. Userthom(wheel), Tailscale, full toolchain.yoloixos— agent sandbox. Useragent(no wheel), no interop, no automount, outbound firewall, 4GB / 200% CPU slice. One-way:agenthas no sudo, so the image can never be rebuilt.
Inside thixos:
sudo nixos-rebuild switch --flake ~/src/github.com/tteggel/.dotfiles#thixos(Inside yoloixos this is intentionally impossible.)
thixos forwards a USB debug probe from Windows into WSL over USB/IP, so you can
flash/debug ARM/RISC-V targets (e.g. a Pico running debugprobe firmware wired to
a target Pico 2 / RP2350 over SWD). nixos/embedded.nix provides only the USB
plumbing: the wsl.usbip client, the vhci_hcd kernel module, an auto-attach
service, and a udev rule giving thom (via plugdev) non-root access to the probe.
The toolchain (probe-rs etc.) lives in your project's devshell, not the system.
On Windows (admin PowerShell) — install the USB/IP daemon and share the probe:
winget install usbipd
usbipd list # note the BUSID of your probe, e.g. 3-1
usbipd bind --busid <BUSID> # plain bind — NOT --force (see Troubleshooting)Set autoAttach = [ "<BUSID>" ]; in nixos/embedded.nix, rebuild, then restart
WSL once (the restart loads vhci_hcd and applies the plugdev group):
sudo nixos-rebuild switch --flake ~/src/github.com/tteggel/.dotfiles#thixoswsl --shutdown # from Windows; reopen thixos afterwardsNothing — a systemd service (usbip-auto-attach@<BUSID>) polls every second and
(re)attaches the probe across boots, replugs and resets. Confirm with lsusb
(probe shows up, e.g. 2e8a:000c). Manual override: usbip-attach [VID:PID].
probe-rs is intentionally not system-installed — add it to the project devshell:
devShells.default = pkgs.mkShell {
packages = [ pkgs.probe-rs-tools /* + rust toolchain, flip-link, … */ ];
};Then probe-rs list sees the probe (via the system udev rule) and you flash with
probe-rs run --chip RP235x <elf> (probe-rs chip list | grep -i rp235 for the
exact chip name).
- Never
usbipd bind --force. It permanently swaps the device onto usbipd's VBoxUSB stub driver; it then flip-flops ("Shared (forced)" toggling) and the WSL attach alternates "Device in error state"/"not found". Use plainbind. To recover a stuck device: Device Manager → Uninstall device → unplug/replug, then plainbind. If plainbindwon't hold, a USB filter driver (real VirtualBox, or RDP/AV USB redirection) is claiming it — remove that. - Not in
lsusb,usbip portsays "is vhci_hcd loaded?" → the module didn't load. It'sboot.kernelModules = [ "vhci_hcd" ]; needs awsl --shutdown(orsudo modprobe vhci_hcdto load immediately). - Can't reach the server (
usbip list -r 127.0.0.1fails) → Windows Firewall rule for TCP 3240.snippetIpAddress = "127.0.0.1"assumes mirrored networking (whichconfig/wslconfigsets); NAT mode uses the eth0 gateway instead. - No custom kernel is built — USB/IP rides the stock WSL2 kernel. "WSL kernel is
not USBIP capable" →
wsl --update. - Same port:
bind/autoAttachkey on the physical port (busid); a different port needs a one-timebind+autoAttachupdate.
Open the session-picker and press Ctrl+Y ("Create from seed"). It prompts
for a name, downloads the latest seed.wsl from GitHub Releases, runs
wsl.exe --import, and launches it — landing you back at the t/y prompt
inside the new distro. Locally-installed distros also show up in the
session-picker (wsl/<name>) for quick attach.
Just the home-manager profile, no system-level isolation:
sh <(curl -L https://nixos.org/nix/install) --daemon
echo "trusted-users = root $USER" | sudo tee -a /etc/nix/nix.conf
sudo systemctl restart nix-daemon
mkdir -p ~/.config/nix && echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
mkdir -p ~/src/github.com/tteggel
git clone https://github.com/tteggel/.dotfiles.git ~/src/github.com/tteggel/.dotfiles
MINIMAL_ENV=1 nix run home-manager/master -- switch --impure -b backup \
--flake ~/src/github.com/tteggel/.dotfiles#thom@nix
# then, once the binary cache has primed, the full env:
home-manager switch --impure -b backup --flake ~/src/github.com/tteggel/.dotfiles#thom@nixSwap thom@nix for agent@nix to take the restricted agent profile (no
infrastructure tools; relies on shell-level discipline, not kernel
isolation).