Skip to content

Instantly share code, notes, and snippets.

@venetanji
Created January 8, 2026 14:47
Show Gist options
  • Select an option

  • Save venetanji/1eb549705d2a8077b8a706b0025858c8 to your computer and use it in GitHub Desktop.

Select an option

Save venetanji/1eb549705d2a8077b8a706b0025858c8 to your computer and use it in GitHub Desktop.
Powershell script to install comfyui with cuda
$ErrorActionPreference = 'Stop'
function Write-Section([string]$Message) {
Write-Host "\n== $Message ==" -ForegroundColor Cyan
}
function Refresh-Path {
$machinePath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
$userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
$env:Path = "$machinePath;$userPath"
}
function Ensure-Command([string]$Name, [string]$InstallHint) {
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
throw "Required command '$Name' not found. $InstallHint"
}
}
function Ensure-Uv {
if (Get-Command uv -ErrorAction SilentlyContinue) {
return
}
Write-Section "Installing uv (Astral) via winget"
Ensure-Command winget "Install App Installer / winget, then re-run this script."
winget install -e --id Astral-Sh.uv
Refresh-Path
Ensure-Command uv "uv install appears to have failed; open a new terminal and re-run."
}
function Ensure-Repo([string]$RepoUrl, [string]$TargetDir) {
Ensure-Command git "Install Git (e.g. winget install -e --id Git.Git), then re-run."
if (Test-Path -LiteralPath $TargetDir) {
$doPull = Read-Host "Repo folder exists at '$TargetDir'. Run 'git pull' there? (y/N)"
if ($doPull -match '^(y|yes)$') {
Push-Location $TargetDir
try {
git pull
} finally {
Pop-Location
}
}
return
}
Write-Section "Cloning ComfyUI"
git clone $RepoUrl $TargetDir
}
function Ensure-UvVenv([string]$RepoDir, [string]$VenvDirName = '.venv') {
$venvDir = Join-Path $RepoDir $VenvDirName
$pythonExe = Join-Path $venvDir 'Scripts\\python.exe'
function Get-PreferredPythonSpec {
# Prefer versions that typically have PyTorch wheels first.
$candidates = @('3.12', '3.11', '3.10')
$pyLauncher = Get-Command py -ErrorAction SilentlyContinue
if (-not $pyLauncher) {
return $null
}
foreach ($spec in $candidates) {
try {
& $pyLauncher.Source "-$spec" -c "import sys; print(sys.version)" 1>$null 2>$null
if ($LASTEXITCODE -eq 0) {
return $spec
}
} catch {
# ignore
}
}
return $null
}
function New-Venv([string]$PythonSpec) {
Write-Section "Creating uv venv ($VenvDirName)"
Push-Location $RepoDir
try {
if ($PythonSpec) {
Write-Host "Using Python: $PythonSpec" -ForegroundColor Gray
uv venv $VenvDirName --python $PythonSpec
} else {
uv venv $VenvDirName
}
} finally {
Pop-Location
}
}
if (-not (Test-Path -LiteralPath $venvDir)) {
$preferred = Get-PreferredPythonSpec
New-Venv -PythonSpec $preferred
}
if (-not (Test-Path -LiteralPath $pythonExe)) {
throw "Expected venv python not found at '$pythonExe'."
}
# If the existing venv uses a Python version that likely lacks PyTorch wheels (e.g. 3.13), offer to recreate.
try {
$verText = & $pythonExe --version 2>$null
if ($verText -match 'Python\s+([0-9]+)\.([0-9]+)') {
$maj = [int]$Matches[1]
$min = [int]$Matches[2]
if ($maj -ge 3 -and $min -ge 13) {
$preferred = Get-PreferredPythonSpec
if ($preferred) {
$recreate = Read-Host "Venv is using Python $maj.$min. PyTorch may not be available for this version. Recreate venv with Python $preferred? (y/N)"
if ($recreate -match '^(y|yes)$') {
Remove-Item -LiteralPath $venvDir -Recurse -Force
New-Venv -PythonSpec $preferred
}
}
}
}
} catch {
# ignore
}
return $pythonExe
}
function Get-CudaInfo {
$toolkitRoot = 'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA'
$toolkitVersions = @()
if (Test-Path -LiteralPath $toolkitRoot) {
$toolkitVersions = Get-ChildItem -LiteralPath $toolkitRoot -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -match '^v\d+(\.\d+)?$' } |
Select-Object -ExpandProperty Name
}
$nvidiaSmi = Get-Command nvidia-smi -ErrorAction SilentlyContinue
$nvcc = Get-Command nvcc -ErrorAction SilentlyContinue
$nvidiaSmiCuda = $null
$nvidiaSmiDriver = $null
if ($nvidiaSmi) {
try {
$out = & $nvidiaSmi.Source 2>$null | Out-String
if ($out -match 'CUDA Version:\s*([0-9]+\.[0-9]+)') {
$nvidiaSmiCuda = $Matches[1]
}
if ($out -match 'Driver Version:\s*([0-9]+\.[0-9]+)') {
$nvidiaSmiDriver = $Matches[1]
}
} catch {
# ignore
}
}
$nvccCuda = $null
if ($nvcc) {
try {
$out = & $nvcc.Source --version 2>$null | Out-String
if ($out -match 'release\s+([0-9]+\.[0-9]+)') {
$nvccCuda = $Matches[1]
}
} catch {
# ignore
}
}
[pscustomobject]@{
HasNvidiaSmi = [bool]$nvidiaSmi
HasNvcc = [bool]$nvcc
NvidiaSmiCudaVersion = $nvidiaSmiCuda
NvidiaSmiDriverVersion = $nvidiaSmiDriver
NvccCudaVersion = $nvccCuda
InstalledToolkitVersions = $toolkitVersions
CudaPath = $env:CUDA_PATH
}
}
function Get-LatestCudaVersionMajorMinor([string]$Fallback = '13.1') {
# Best-effort: NVIDIA hosts a directory listing with redistrib_<version>.json files.
# If this fetch fails, fall back to the provided version.
try {
$ProgressPreference = 'SilentlyContinue'
$html = (Invoke-WebRequest -UseBasicParsing -Uri 'https://developer.download.nvidia.com/compute/cuda/redist/' -TimeoutSec 15).Content
$versions = [regex]::Matches($html, 'redistrib_([0-9]+\.[0-9]+\.[0-9]+)\.json') |
ForEach-Object { $_.Groups[1].Value } |
Sort-Object -Unique
if (-not $versions -or $versions.Count -eq 0) {
return $Fallback
}
$latest = $versions | Sort-Object {[version]$_} -Descending | Select-Object -First 1
$parts = $latest.Split('.')
if ($parts.Length -ge 2) {
return "$($parts[0]).$($parts[1])"
}
return $Fallback
} catch {
return $Fallback
}
}
function Install-Torch([string]$PythonExe, [string]$CudaMajorMinor, [bool]$HasNvidiaSmi) {
Write-Section "Installing PyTorch"
$defaultChoice = if ($HasNvidiaSmi -or $CudaMajorMinor) { 'cuda' } else { 'cpu' }
$choice = Read-Host "Install PyTorch for 'cuda' or 'cpu'? (default: $defaultChoice)"
if ([string]::IsNullOrWhiteSpace($choice)) {
$choice = $defaultChoice
}
$choice = $choice.Trim().ToLowerInvariant()
if ($choice -eq 'cpu') {
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu --python $PythonExe
return
}
function Test-HttpOk([string]$Url) {
try {
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -UseBasicParsing -Uri $Url -Method Head -TimeoutSec 15 | Out-Null
return $true
} catch {
return $false
}
}
# IMPORTANT: PyTorch CUDA wheel indexes (cuXXX) do NOT necessarily exist for the newest CUDA Toolkit
# version (e.g., CUDA 13.1 -> there is no cu131 index at the time of writing).
# The safest approach is to pick the newest published cuXXX index.
$candidates = @('cu130', 'cu128', 'cu126', 'cu124', 'cu121', 'cu118')
$available = @()
foreach ($c in $candidates) {
$u = "https://download.pytorch.org/whl/$c"
if (Test-HttpOk $u) {
$available += $c
}
}
$auto = if ($available.Count -gt 0) { $available[0] } else { $null }
if ($CudaMajorMinor) {
Write-Host "Detected CUDA (driver/toolkit): $CudaMajorMinor" -ForegroundColor Gray
}
if ($auto) {
Write-Host "Auto-selected PyTorch CUDA wheels: $auto" -ForegroundColor Yellow
} else {
Write-Host "Could not probe a PyTorch cuXXX index-url (network issue?)" -ForegroundColor Yellow
}
$hint = if ($auto) { "(default: $auto)" } else { "(examples: cu128, cu126, cpu)" }
$build = Read-Host "Torch build to install: type 'cpu' or a cuXXX (e.g. cu128) $hint"
if ([string]::IsNullOrWhiteSpace($build)) {
$build = $auto
}
$build = $build.Trim().ToLowerInvariant()
if ($build -eq 'cpu') {
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu --python $PythonExe
return
}
if (-not $build -or $build -notmatch '^cu\d{3}$') {
throw "Invalid torch build '$build'. Use 'cpu' or something like 'cu128'."
}
$indexUrl = "https://download.pytorch.org/whl/$build"
Write-Host "Using PyTorch index-url: $indexUrl" -ForegroundColor Yellow
uv pip install torch torchvision torchaudio --index-url $indexUrl --python $PythonExe
}
function Install-ComfyDeps([string]$RepoDir, [string]$PythonExe) {
Write-Section "Installing ComfyUI requirements"
Push-Location $RepoDir
try {
uv pip install -r requirements.txt --python $PythonExe
} finally {
Pop-Location
}
Write-Section "Installing comfyui_manager (pre-release)"
uv pip install --pre comfyui_manager --python $PythonExe
}
Write-Section "Prereqs"
Ensure-Uv
Refresh-Path
$repoUrl = 'https://github.com/Comfy-Org/ComfyUI'
$repoDir = Join-Path $PSScriptRoot 'ComfyUI'
Ensure-Repo -RepoUrl $repoUrl -TargetDir $repoDir
$pythonExe = Ensure-UvVenv -RepoDir $repoDir
Write-Section "CUDA detection"
$cuda = Get-CudaInfo
Write-Host "nvidia-smi present: $($cuda.HasNvidiaSmi)" -ForegroundColor Gray
Write-Host "nvcc present: $($cuda.HasNvcc)" -ForegroundColor Gray
Write-Host "CUDA via nvidia-smi: $($cuda.NvidiaSmiCudaVersion)" -ForegroundColor Gray
Write-Host "Driver version: $($cuda.NvidiaSmiDriverVersion)" -ForegroundColor Gray
Write-Host "CUDA via nvcc: $($cuda.NvccCudaVersion)" -ForegroundColor Gray
Write-Host "CUDA_PATH: $($cuda.CudaPath)" -ForegroundColor Gray
Write-Host "Toolkit folders: $([string]::Join(', ', $cuda.InstalledToolkitVersions))" -ForegroundColor Gray
$latestCuda = Get-LatestCudaVersionMajorMinor -Fallback '13.1'
Write-Host "Latest CUDA (best-effort): $latestCuda" -ForegroundColor Yellow
$openCuda = Read-Host "Open CUDA Toolkit download page in browser? (y/N)"
if ($openCuda -match '^(y|yes)$') {
Start-Process 'https://developer.nvidia.com/cuda-downloads'
}
# Prefer an installed toolkit version (highest) or fall back to detected runtime / latest.
$installedToolkitMajorMinor = $null
if ($cuda.InstalledToolkitVersions -and $cuda.InstalledToolkitVersions.Count -gt 0) {
$installedToolkitMajorMinor = $cuda.InstalledToolkitVersions |
ForEach-Object { $_ -replace '^v', '' } |
Sort-Object {[version]$_} -Descending |
Select-Object -First 1
}
$cudaForTorch = $installedToolkitMajorMinor
if (-not $cudaForTorch) { $cudaForTorch = $cuda.NvccCudaVersion }
if (-not $cudaForTorch) { $cudaForTorch = $cuda.NvidiaSmiCudaVersion }
if (-not $cudaForTorch) { $cudaForTorch = $latestCuda }
Install-Torch -PythonExe $pythonExe -CudaMajorMinor $cudaForTorch -HasNvidiaSmi $cuda.HasNvidiaSmi
Install-ComfyDeps -RepoDir $repoDir -PythonExe $pythonExe
Write-Host "\nDone." -ForegroundColor Green
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment