{ description = "ESP32 development tools"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; flake-utils.url = "github:numtide/flake-utils"; nixpkgs-esp-dev = { #url = "github:mirrexagon/nixpkgs-esp-dev"; url = "github:dvdvgt/nixpkgs-esp-dev/update-v6.0.1"; inputs = { nixpkgs.follows = "nixpkgs"; flake-utils.follows = "flake-utils"; }; }; }; outputs = { self, nixpkgs, flake-utils, nixpkgs-esp-dev, }: flake-utils.lib.eachDefaultSystem ( system: let idfVersion = "v6.0.1"; pkgs = import nixpkgs { inherit system; overlays = [ (import "${nixpkgs-esp-dev}/overlay.nix") ]; config.permittedInsecurePackages = [ "python3.13-ecdsa-0.19.1" ]; }; autoSerialPort = pkgs.writeShellScriptBin "esp-port" '' set -euo pipefail # Try common ESP USB serial patterns # TODO: reduce to Waveshare ESP32-S3 detection PORT=$( for p in /dev/serial/by-id/*; do case "$p" in *CP210*|*ch340*|*USB*|*ESP*) echo "$p"; break ;; esac done ) if [ -z "$PORT" ]; then echo "No ESP serial device found in /dev/serial/by-id" echo "Fallback: listing /dev/ttyUSB* /dev/ttyACM*" ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null || true exit 1 fi echo "$PORT" ''; esp-idf = pkgs.esp-idf-full.override { rev = idfVersion; sha256 = "sha256-4KJa686qc+u7XkF/GS2o53l1SpwP2EmdqAn/qmlL1yU="; }; in { apps = { run-agent = { type = "app"; program = "${pkgs.writeShellScript "run-agent" '' podman run -it --rm -v ./:/src -v ./models.json:/root/.pi/agent/models.json --device=/dev/ttyACM0 pidev:latest ''}"; }; build-agent = { type = "app"; program = "${pkgs.writeShellScript "build-agent" '' podman build -t pidev:latest -f Containerfile . ''}"; }; menuconfig = { type = "app"; meta.description = "โš™๏ธ Open ESP-IDF configuration menu (sdkconfig)"; program = "${pkgs.writeShellScriptBin "idf-menuconfig" '' ${esp-idf}/tools/idf.py menuconfig ''}/bin/idf-menuconfig"; }; build = { type = "app"; meta.description = "๐Ÿงฑ Build ESP32 firmware using ESP-IDF ${idfVersion}"; program = "${pkgs.writeShellScriptBin "idf-build" '' ${esp-idf}/tools/idf.py build ''}/bin/idf-build"; }; flash = { type = "app"; meta.description = "โšก Flash firmware to ESP32-S3 over auto-detected serial port"; program = "${pkgs.writeShellScriptBin "idf-flash" '' set -euo pipefail PORT=$(${autoSerialPort}/bin/esp-port) echo "Flashing on: $PORT" ${esp-idf}/tools/idf.py -p "$PORT" flash ''}/bin/idf-flash"; }; monitor = { type = "app"; meta.description = "๐Ÿ“ก Open serial monitor for ESP32 logs"; program = "${pkgs.writeShellScriptBin "idf-monitor" '' set -euo pipefail PORT=$(${autoSerialPort}/bin/esp-port) echo "Monitoring: $PORT" ${esp-idf}/tools/idf.py -p "$PORT" monitor ''}/bin/idf-monitor"; }; clean = { type = "app"; meta.description = "๐Ÿงน Clean ESP-IDF build directory"; program = "${pkgs.writeShellScriptBin "idf-clean" '' ${esp-idf}/tools/idf.py clean ''}/bin/idf-clean"; }; full = { type = "app"; meta.description = "๐Ÿš€ Full pipeline: build โ†’ flash โ†’ monitor"; program = "${pkgs.writeShellScriptBin "idf-full" '' set -euo pipefail PORT=$(${autoSerialPort}/bin/esp-port) echo "๐Ÿงฑ Building..." ${esp-idf}/tools/idf.py build echo "โšก Flashing on $PORT..." ${esp-idf}/tools/idf.py -p "$PORT" flash echo "๐Ÿ“ก Starting monitor..." ${esp-idf}/tools/idf.py -p "$PORT" monitor ''}/bin/idf-full"; }; }; devShells.default = pkgs.mkShell { buildInputs = with pkgs; [ esp-idf git minicom usbutils gawk coreutils cmake ninja ]; }; } ); }