{
  description = "Mbed OS dev env (STM32U575ZI-Q) using mbed-tools v2 + uv";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachSystem [
      "x86_64-linux"
      "aarch64-linux"
      "x86_64-darwin"
      "aarch64-darwin"
    ] (system:
      let
        pkgs = import nixpkgs { inherit system; };

        # ARM Embedded Toolchain
        armGcc =
          if pkgs ? arm-none-eabi-gcc
          then pkgs.arm-none-eabi-gcc
          else pkgs.gcc-arm-embedded;

        # Use a Python version that works well with mbed-tools today
        pythonPin = "3.12";

        # Wrapper: mbed-tools via uvx, pin Python and ensure setuptools is present
        mbedTools = pkgs.writeShellScriptBin "mbed-tools" ''
          exec ${pkgs.uv}/bin/uvx \
            --python ${pythonPin} \
            --with setuptools \
            --from mbed-tools mbed-tools "$@"
        '';

        # Wrapper: pyocd via uvx, pin Python for compatibility
        pyOcd = pkgs.writeShellScriptBin "pyocd" ''
          exec ${pkgs.uv}/bin/uvx \
            --python ${pythonPin} \
            --from pyocd pyocd "$@"
        '';
      in {
        devShells.default = pkgs.mkShell {
          packages = [
            pkgs.uv
            pkgs.python3
            pkgs.git
            pkgs.mercurial
            pkgs.cmake
            pkgs.ninja
            armGcc
            pkgs.openocd
            pkgs.stlink
	    pkgs.probe-rs
	    pkgs.probe-rs-tools
	    pkgs.bear
	    pkgs.chafa
	    pkgs.imagemagick
            mbedTools
            pyOcd
          ];

          # Make compiler visible for Mbed
          MBED_GCC_ARM_PATH = "${armGcc}/bin";
          MBED_TARGET = "NUCLEO_U575ZI_Q";

          shellHook = ''
            export PATH="${armGcc}/bin:$PATH"
            export UV_TOOL_DIR="$PWD/.uv-tools"

            echo
            echo "✅ Mbed dev shell ready"
            echo "   - Target      : $MBED_TARGET"
            echo "   - Compiler    : ${armGcc}"
            echo "   - Commands    : mbed-tools, pyocd, openocd, st-flash"
	    echo "probe-rs run --chip STM32U575ZITxQ cmake_build/NUCLEO_U575ZI_Q/develop/GCC_ARM/mbed-os-example-blinky.elf"
            echo
          '';
        };

        # nix run .#build-blinky -> builds example
        apps.build-blinky = flake-utils.lib.mkApp {
          drv = pkgs.writeShellScriptBin "build-blinky" ''
            set -euo pipefail

            export PATH="${armGcc}/bin:$PATH"
            export MBED_GCC_ARM_PATH="${armGcc}/bin"
            export MBED_TARGET="NUCLEO_U575ZI_Q"

            workdir="mbed-os-example-blinky"
            if [ ! -d "$workdir" ]; then
              git clone --depth 1 \
                https://github.com/ARMmbed/mbed-os-example-blinky "$workdir"
            fi
            cd "$workdir"

            # Install deps (fetches mbed-os)
            ${mbedTools}/bin/mbed-tools deploy

            # Configure + build
            ${mbedTools}/bin/mbed-tools configure \
              -m "$MBED_TARGET" -t GCC_ARM
            ${mbedTools}/bin/mbed-tools compile \
              -m "$MBED_TARGET" -t GCC_ARM -c

            echo
            echo "🎉 Build complete"
            echo "   Check BUILD/NUCLEO_U575ZI_Q/GCC_ARM/ for binaries"
            echo
          '';
        };
      });
}
