{
  description = "hakurei container tool and nixos module";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";

    home-manager = {
      url = "github:nix-community/home-manager/release-26.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
      home-manager,
    }:
    let
      supportedSystems = [
        "aarch64-linux"
        "i686-linux"
        "x86_64-linux"
      ];

      forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
      nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
    in
    {
      nixosModules.hakurei = import ./nixos.nix self.packages;

      checks = forAllSystems (
        system:
        let
          pkgs = nixpkgsFor.${system};

          inherit (pkgs)
            runCommandLocal
            callPackage
            nixfmt
            deadnix
            statix
            ;
        in
        {
          hakurei = callPackage ./. { inherit system self; };
          race = callPackage ./. {
            inherit system self;
            withRace = true;
          };

          sandbox = callPackage ./sandbox { inherit self; };
          sandbox-race = callPackage ./sandbox {
            inherit self;
            withRace = true;
          };

          sharefs = callPackage ./sharefs { inherit system self; };

          formatting = runCommandLocal "check-formatting" { nativeBuildInputs = [ nixfmt ]; } ''
            cd ${./.}

            echo "running nixfmt..."
            nixfmt --width=256 --check .

            touch $out
          '';

          lint =
            runCommandLocal "check-lint"
              {
                nativeBuildInputs = [
                  deadnix
                  statix
                ];
              }
              ''
                cd ${./.}

                echo "running deadnix..."
                deadnix --fail

                echo "running statix..."
                statix check .

                touch $out
              '';
        }
      );

      packages = forAllSystems (
        system:
        let
          inherit (self.packages.${system}) hakurei hsu;
          pkgs = nixpkgsFor.${system};
        in
        {
          default = hakurei;
          hakurei = pkgs.pkgsStatic.callPackage ./package.nix {
            inherit (pkgs)
              # passthru.buildInputs
              go_1_26
              clang

              # nativeBuildInputs
              pkg-config
              wayland-scanner
              makeBinaryWrapper

              # appPackages
              glibc
              xdg-dbus-proxy

              # for check
              util-linux
              nettools
              ;
          };
          hsu = pkgs.callPackage ./hsu.nix { inherit (self.packages.${system}) hakurei; };
          sharefs = pkgs.linkFarm "sharefs" {
            "bin/sharefs" = "${hakurei}/libexec/sharefs";
            "bin/mount.fuse.sharefs" = "${hakurei}/libexec/sharefs";
          };

          dist =
            pkgs.runCommand "${hakurei.name}-dist"
              {
                buildInputs = hakurei.targetPkgs ++ [
                  pkgs.pkgsStatic.musl
                ];
              }
              ''
                cd $(mktemp -d) \
                    && cp -r ${hakurei.src}/. . \
                    && chmod +w cmd && cp -r ${hsu.src}/. cmd/hsu/ \
                    && chmod -R +w .

                CC="musl-clang -O3 -Werror -Qunused-arguments" \
                GOCACHE="$(mktemp -d)" \
                PATH="${pkgs.pkgsStatic.musl.bin}/bin:$PATH" \
                DESTDIR="$out" \
                  ./all.sh
              '';
        }
      );

      devShells = forAllSystems (
        system:
        let
          inherit (self.packages.${system}) hakurei;
          pkgs = nixpkgsFor.${system};
        in
        {
          default = pkgs.mkShell {
            buildInputs = hakurei.targetPkgs;
            hardeningDisable = [ "fortify" ];
          };
          withPackage = pkgs.mkShell { buildInputs = [ hakurei ] ++ hakurei.targetPkgs; };

          vm =
            let
              nixos = nixpkgs.lib.nixosSystem {
                inherit system;
                modules = [
                  {
                    environment = {
                      systemPackages = [
                        (pkgs.buildFHSEnv {
                          pname = "hakurei-fhs";
                          inherit (hakurei) version;
                          targetPkgs = _: hakurei.targetPkgs;
                          extraOutputsToInstall = [ "dev" ];
                          profile = ''
                            export PKG_CONFIG_PATH="/usr/share/pkgconfig:$PKG_CONFIG_PATH"
                          '';
                        })
                      ];

                      hakurei =
                        let
                          # this is used for interactive vm testing during development, where tests might be broken
                          package = self.packages.${pkgs.stdenv.hostPlatform.system}.hakurei.override {
                            buildGo126Module = previousArgs: pkgs.pkgsStatic.buildGo126Module (previousArgs // { doCheck = false; });
                          };
                        in
                        {
                          inherit package;
                          hsuPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.hsu.override { hakurei = package; };
                        };
                    };
                  }

                  ./interactive/configuration.nix
                  ./interactive/vm.nix
                  ./interactive/hakurei.nix
                  ./interactive/trace.nix
                  ./interactive/raceattr.nix

                  self.nixosModules.hakurei
                  home-manager.nixosModules.home-manager
                ];
              };
            in
            pkgs.mkShell {
              buildInputs = [ nixos.config.system.build.vm ];
              shellHook = "exec run-nixos-vm $@";
            };

          generateDoc =
            let
              inherit (pkgs) lib;

              doc =
                let
                  eval = lib.evalModules {
                    specialArgs = {
                      inherit pkgs;
                    };
                    modules = [ (import ./options.nix self.packages) ];
                  };
                  cleanEval = lib.filterAttrsRecursive (n: _: n != "_module") eval;
                in
                pkgs.nixosOptionsDoc { inherit (cleanEval) options; };
              docText = pkgs.runCommand "hakurei-module-docs.md" { } ''
                cat ${doc.optionsCommonMark} > $out
                sed -i '/*Declared by:*/,+1 d' $out
              '';
            in
            pkgs.mkShell {
              shellHook = ''
                exec cat ${docText} > options.md
              '';
            };

          generateSyscallTable =
            let
              GOARCH = {
                x86_64-linux = "amd64";
                aarch64-linux = "arm64";
              };
            in
            pkgs.mkShell {
              shellHook = "exec ${pkgs.writeShellScript "generate-syscall-table" ''
                set -e
                ${pkgs.perl}/bin/perl \
                  container/std/mksysnum_linux.pl \
                  ${pkgs.linuxHeaders}/include/asm/unistd_64.h | \
                  ${pkgs.go}/bin/gofmt > \
                  container/std/syscall_linux_${GOARCH.${system}}.go
              ''}";
            };
        }
      );
    };
}
