{
  lib,
  stdenvNoCC,
  bun,
  bunCpu ? if stdenvNoCC.hostPlatform.isAarch64 then "arm64" else "x64",
  bunOs ? if stdenvNoCC.hostPlatform.isLinux then "linux" else "darwin",
  rev ? "dirty",
  hash ?
    (lib.pipe ./hashes.json [
      builtins.readFile
      builtins.fromJSON
    ]).nodeModules.${stdenvNoCC.hostPlatform.system},
}:
let
  packageJson = lib.pipe ../packages/opencode/package.json [
    builtins.readFile
    builtins.fromJSON
  ];
in
stdenvNoCC.mkDerivation {
  pname = "opencode-node_modules";
  version = "${packageJson.version}-${rev}";

  src = lib.fileset.toSource {
    root = ../.;
    fileset = lib.fileset.intersection (lib.fileset.fromSource (lib.sources.cleanSource ../.)) (
      lib.fileset.unions [
        ../packages
        ../bun.lock
        ../package.json
        ../patches
        ../install
      ]
    );
  };

  impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
    "GIT_PROXY_COMMAND"
    "SOCKS_SERVER"
  ];

  nativeBuildInputs = [
    bun
  ];

  dontConfigure = true;

  buildPhase = ''
    runHook preBuild
    export HOME=$(mktemp -d)
    export BUN_INSTALL_CACHE_DIR=$(mktemp -d)
    bun install \
      --cpu="${bunCpu}" \
      --os="${bunOs}" \
      --frozen-lockfile \
      --ignore-scripts \
      --no-progress \
      --linker=isolated
    bun --bun ${./scripts/canonicalize-node-modules.ts}
    bun --bun ${./scripts/normalize-bun-binaries.ts}
    runHook postBuild
  '';

  installPhase = ''
    runHook preInstall

    mkdir -p $out
    find . -type d -name node_modules -exec cp -R --parents {} $out \;

    runHook postInstall
  '';

  dontFixup = true;

  outputHashAlgo = "sha256";
  outputHashMode = "recursive";
  outputHash = hash;

  meta.platforms = [
    "aarch64-linux"
    "x86_64-linux"
    "aarch64-darwin"
    "x86_64-darwin"
  ];
}
