#Requires -Version 5.1 <# .SYNOPSIS Claude Code Installer for Windows A colorized, interactive installer with full system detection .DESCRIPTION This script automates the installation of Claude Code on Windows systems. Features: - Detects Windows version and architecture - Checks/removes existing Node.js and npm installations - Installs Node.js 20 LTS - Installs Claude Code - Configures permissions interactively .NOTES Author: BitMaster Repository: https://git.bitmaster.cc/BitMaster/claude License: MIT .EXAMPLE .\claude-code-installer.ps1 .EXAMPLE # Run directly from web irm https://git.bitmaster.cc/BitMaster/claude/raw/branch/main/claude-code-installer.ps1 | iex #> # Ensure we're running with proper execution $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" #------------------------------------------------------------------------------- # Configuration #------------------------------------------------------------------------------- $script:BoxWidth = 65 # Inner width of boxes #------------------------------------------------------------------------------- # Color and Display Functions #------------------------------------------------------------------------------- function Write-ColorText { param( [string]$Text, [ConsoleColor]$Color = "White", [switch]$NoNewline ) if ($NoNewline) { Write-Host $Text -ForegroundColor $Color -NoNewline } else { Write-Host $Text -ForegroundColor $Color } } function Write-BoxTop { param([int]$Width = $script:BoxWidth) $line = "─" * $Width Write-ColorText " ┌$line┐" -Color White } function Write-BoxMiddle { param([int]$Width = $script:BoxWidth) $line = "─" * $Width Write-ColorText " ├$line┤" -Color White } function Write-BoxBottom { param([int]$Width = $script:BoxWidth) $line = "─" * $Width Write-ColorText " └$line┘" -Color White } function Write-BoxTitle { param( [string]$Title, [int]$Width = $script:BoxWidth ) $padding = $Width - $Title.Length - 2 $leftPad = [math]::Floor($padding / 2) $rightPad = $padding - $leftPad Write-ColorText " │" -Color White -NoNewline Write-ColorText (" " * ($leftPad + 1)) -Color White -NoNewline Write-ColorText $Title -Color White -NoNewline Write-ColorText (" " * ($rightPad + 1)) -Color White -NoNewline Write-ColorText "│" -Color White } function Write-BoxEmpty { param([int]$Width = $script:BoxWidth) Write-ColorText " │" -Color White -NoNewline Write-ColorText (" " * $Width) -Color White -NoNewline Write-ColorText "│" -Color White } function Write-BoxContent { param( [string]$Label, [ConsoleColor]$LabelColor = "Cyan", [string]$Value, [ConsoleColor]$ValueColor = "Green", [int]$LabelWidth = 16, [int]$Width = $script:BoxWidth ) $paddedLabel = $Label.PadRight($LabelWidth) $remainingWidth = $Width - $LabelWidth - 4 # 4 for prefix spacing $paddedValue = $Value if ($Value.Length -gt $remainingWidth) { $paddedValue = $Value.Substring(0, $remainingWidth - 3) + "..." } $totalPadding = $Width - $paddedLabel.Length - $paddedValue.Length - 2 if ($totalPadding -lt 0) { $totalPadding = 0 } Write-ColorText " │ " -Color White -NoNewline Write-ColorText $paddedLabel -Color $LabelColor -NoNewline Write-ColorText $paddedValue -Color $ValueColor -NoNewline Write-ColorText (" " * $totalPadding) -Color White -NoNewline Write-ColorText " │" -Color White } function Write-BoxLine { param( [string]$Text, [ConsoleColor]$Color = "White", [int]$Width = $script:BoxWidth, [int]$Indent = 1 ) $indentStr = " " * $Indent $maxTextWidth = $Width - $Indent - 1 $displayText = $Text if ($Text.Length -gt $maxTextWidth) { $displayText = $Text.Substring(0, $maxTextWidth - 3) + "..." } $padding = $Width - $Indent - $displayText.Length - 1 if ($padding -lt 0) { $padding = 0 } Write-ColorText " │" -Color White -NoNewline Write-ColorText $indentStr -Color White -NoNewline Write-ColorText $displayText -Color $Color -NoNewline Write-ColorText (" " * $padding) -Color White -NoNewline Write-ColorText " │" -Color White } function Write-BoxLineMultiColor { param( [array]$Parts, # Array of @{Text=""; Color="White"} [int]$Width = $script:BoxWidth, [int]$Indent = 1 ) $indentStr = " " * $Indent $totalLength = $Indent foreach ($part in $Parts) { $totalLength += $part.Text.Length } $padding = $Width - $totalLength - 1 if ($padding -lt 0) { $padding = 0 } Write-ColorText " │" -Color White -NoNewline Write-ColorText $indentStr -Color White -NoNewline foreach ($part in $Parts) { Write-ColorText $part.Text -Color $part.Color -NoNewline } Write-ColorText (" " * $padding) -Color White -NoNewline Write-ColorText " │" -Color White } function Write-Banner { Clear-Host Write-Host "" Write-ColorText " ╔═══════════════════════════════════════════════════════════════════╗" -Color Cyan Write-ColorText " ║ ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗" -Color Cyan -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝" -Color Cyan -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "██║ ██║ ███████║██║ ██║██║ ██║█████╗" -Color Cyan -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "██║ ██║ ██╔══██║██║ ██║██║ ██║██╔══╝" -Color Cyan -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "╚██████╗███████╗██║ ██║╚██████╔╝██████╔╝███████╗" -Color Cyan -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝" -Color Cyan -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "C O D E I N S T A L L E R" -Color White -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ ║" -Color Cyan Write-ColorText " ║ " -Color Cyan -NoNewline Write-ColorText "[ Windows Edition ]" -Color Yellow -NoNewline Write-ColorText " ║" -Color Cyan Write-ColorText " ║ ║" -Color Cyan Write-ColorText " ╚═══════════════════════════════════════════════════════════════════╝" -Color Cyan Write-Host "" } function Write-Section { param([string]$Title) Write-Host "" Write-ColorText " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -Color Blue Write-ColorText " $Title" -Color White Write-ColorText " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -Color Blue Write-Host "" } function Write-Step { param([string]$Message) Write-ColorText " → " -Color Cyan -NoNewline Write-ColorText $Message -Color White } function Write-Success { param([string]$Message) Write-ColorText " ✓ " -Color Green -NoNewline Write-ColorText $Message -Color Green } function Write-Error2 { param([string]$Message) Write-ColorText " ✗ " -Color Red -NoNewline Write-ColorText $Message -Color Red } function Write-Warning2 { param([string]$Message) Write-ColorText " ⚠ " -Color Yellow -NoNewline Write-ColorText $Message -Color Yellow } function Write-Info { param([string]$Message) Write-ColorText " ℹ " -Color Blue -NoNewline Write-ColorText $Message -Color DarkGray } function Confirm-Action { param( [string]$Prompt, [bool]$DefaultYes = $true ) if ($DefaultYes) { $options = "[Y/n]" } else { $options = "[y/N]" } Write-ColorText " ? " -Color Yellow -NoNewline Write-ColorText "$Prompt " -Color White -NoNewline Write-ColorText $options -Color DarkGray -NoNewline Write-ColorText ": " -Color White -NoNewline $response = Read-Host if ([string]::IsNullOrWhiteSpace($response)) { return $DefaultYes } return $response -match "^[Yy]" } function Wait-ForKey { Write-Host "" Write-ColorText " Press any key to continue..." -Color DarkGray $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Write-Host "" } #------------------------------------------------------------------------------- # System Detection Functions #------------------------------------------------------------------------------- function Get-SystemInfo { Write-Section "⚙ System Detection" Write-Step "Identifying your Windows system..." Start-Sleep -Milliseconds 500 # Get Windows version info $os = Get-CimInstance -ClassName Win32_OperatingSystem $cs = Get-CimInstance -ClassName Win32_ComputerSystem $script:WindowsVersion = $os.Caption $script:WindowsBuild = $os.BuildNumber $script:WindowsArch = $cs.SystemType $script:ComputerName = $cs.Name $script:TotalRAM = [math]::Round($cs.TotalPhysicalMemory / 1GB, 2) # Determine architecture for Node.js download if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64" -or $env:PROCESSOR_ARCHITEW6432 -eq "AMD64") { $script:Arch = "x64" $script:ArchDisplay = "64-bit (x64)" } elseif ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { $script:Arch = "arm64" $script:ArchDisplay = "ARM64" } else { $script:Arch = "x86" $script:ArchDisplay = "32-bit (x86)" } # Check if running as Administrator $script:IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) # Check PowerShell version $script:PSVersion = $PSVersionTable.PSVersion.ToString() # Display detected information Write-Host "" Write-BoxTop Write-BoxTitle -Title "System Information" Write-BoxMiddle Write-BoxContent -Label "Windows:" -Value $WindowsVersion Write-BoxContent -Label "Build:" -Value $WindowsBuild Write-BoxContent -Label "Architecture:" -Value $ArchDisplay Write-BoxContent -Label "Computer:" -Value $ComputerName Write-BoxContent -Label "RAM:" -Value "$TotalRAM GB" Write-BoxContent -Label "PowerShell:" -Value "v$PSVersion" if ($IsAdmin) { Write-BoxContent -Label "Admin Rights:" -Value "Yes" -ValueColor Green } else { Write-BoxContent -Label "Admin Rights:" -Value "No" -ValueColor Yellow } Write-BoxBottom Write-Host "" Write-Success "System detected successfully!" Start-Sleep -Seconds 1 } #------------------------------------------------------------------------------- # Node.js Detection and Installation #------------------------------------------------------------------------------- function Test-NodeInstallation { Write-Section "📦 Node.js & npm Detection" Write-Step "Checking for existing Node.js installation..." Start-Sleep -Milliseconds 500 $script:NodeInstalled = $false $script:NpmInstalled = $false $script:NodeVersion = "" $script:NpmVersion = "" $script:NeedsUpgrade = $false # Check Node.js try { $nodeOutput = & node --version 2>$null if ($nodeOutput) { $script:NodeInstalled = $true $script:NodeVersion = $nodeOutput } } catch { $script:NodeInstalled = $false } # Check npm try { $npmOutput = & npm --version 2>$null if ($npmOutput) { $script:NpmInstalled = $true $script:NpmVersion = $npmOutput } } catch { $script:NpmInstalled = $false } # Display current status Write-Host "" Write-BoxTop Write-BoxTitle -Title "Current Installation Status" Write-BoxMiddle if ($NodeInstalled) { # Check if version is sufficient (need v18+) $versionNum = $NodeVersion -replace "v", "" $majorVersion = [int]($versionNum.Split('.')[0]) if ($majorVersion -ge 18) { Write-BoxLineMultiColor -Parts @( @{Text="✓ "; Color="Green"}, @{Text="Node.js: "; Color="White"}, @{Text="$NodeVersion"; Color="Green"}, @{Text=" (Compatible)"; Color="Green"} ) } else { Write-BoxLineMultiColor -Parts @( @{Text="⚠ "; Color="Yellow"}, @{Text="Node.js: "; Color="White"}, @{Text="$NodeVersion"; Color="Yellow"}, @{Text=" (Needs upgrade to v18+)"; Color="Yellow"} ) $script:NeedsUpgrade = $true } } else { Write-BoxLineMultiColor -Parts @( @{Text="✗ "; Color="Red"}, @{Text="Node.js: "; Color="White"}, @{Text="Not installed"; Color="Red"} ) $script:NeedsUpgrade = $true } if ($NpmInstalled) { Write-BoxLineMultiColor -Parts @( @{Text="✓ "; Color="Green"}, @{Text="npm: "; Color="White"}, @{Text="v$NpmVersion"; Color="Green"} ) } else { Write-BoxLineMultiColor -Parts @( @{Text="✗ "; Color="Red"}, @{Text="npm: "; Color="White"}, @{Text="Not installed"; Color="Red"} ) } Write-BoxBottom Write-Host "" # Determine action needed if ($NodeInstalled -and $NeedsUpgrade) { Write-Warning2 "Your Node.js version is incompatible with Claude Code." Write-Info "Claude Code requires Node.js version 18.0.0 or higher." Write-Host "" if (Confirm-Action "Would you like to uninstall the existing version and install Node.js 20 LTS?") { Uninstall-Node Install-Node } else { Write-Error2 "Cannot proceed without Node.js 18+. Exiting." exit 1 } } elseif (-not $NodeInstalled) { Write-Info "Node.js is not installed on your system." Write-Host "" if (Confirm-Action "Would you like to install Node.js 20 LTS?") { Install-Node } else { Write-Error2 "Cannot proceed without Node.js. Exiting." exit 1 } } else { Write-Success "Node.js installation is compatible!" Write-Host "" if (Confirm-Action "Would you like to reinstall Node.js anyway (fresh installation)?" -DefaultYes $false) { Uninstall-Node Install-Node } } } function Uninstall-Node { Write-Section "⚙ Removing Existing Node.js Installation" Write-Step "Searching for Node.js installations..." Write-Host "" # Check for Node.js in common locations $nodePaths = @( "$env:ProgramFiles\nodejs", "${env:ProgramFiles(x86)}\nodejs", "$env:LOCALAPPDATA\Programs\nodejs" ) # Try to uninstall via Windows installer Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Checking for installed Node.js package..." -Color White $uninstallKeys = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" ) $nodePackage = $null foreach ($key in $uninstallKeys) { $nodePackage = Get-ItemProperty $key -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*Node.js*" -or $_.DisplayName -like "*Node*" } | Select-Object -First 1 if ($nodePackage) { break } } if ($nodePackage -and $nodePackage.UninstallString) { Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Found Node.js installation. Uninstalling..." -Color White try { $uninstallCmd = $nodePackage.UninstallString if ($uninstallCmd -match "msiexec") { # MSI uninstall $productCode = $uninstallCmd -replace ".*(\{[A-F0-9-]+\}).*", '$1' if ($productCode -match "^\{") { Start-Process "msiexec.exe" -ArgumentList "/x $productCode /qn" -Wait -NoNewWindow } } else { Start-Process $uninstallCmd -ArgumentList "/S" -Wait -NoNewWindow -ErrorAction SilentlyContinue } Write-ColorText " done" -Color Green } catch { Write-ColorText " manual removal required" -Color Yellow } } # Remove Node.js directories foreach ($path in $nodePaths) { if (Test-Path $path) { Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Removing $path..." -Color White -NoNewline try { Remove-Item -Path $path -Recurse -Force -ErrorAction Stop Write-ColorText " done" -Color Green } catch { Write-ColorText " failed (may need admin rights)" -Color Red } } } # Remove npm cache and global packages $npmPaths = @( "$env:APPDATA\npm", "$env:APPDATA\npm-cache", "$env:LOCALAPPDATA\npm-cache" ) foreach ($path in $npmPaths) { if (Test-Path $path) { Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Removing $path..." -Color White -NoNewline try { Remove-Item -Path $path -Recurse -Force -ErrorAction Stop Write-ColorText " done" -Color Green } catch { Write-ColorText " skipped" -Color Yellow } } } # Remove from PATH (current session) $env:Path = ($env:Path.Split(';') | Where-Object { $_ -notlike "*nodejs*" -and $_ -notlike "*npm*" }) -join ';' Write-Host "" Write-Success "Node.js removal completed!" Start-Sleep -Seconds 1 } function Install-Node { Write-Section "📦 Installing Node.js 20 LTS" Write-Step "Preparing to install Node.js 20 LTS..." Write-Host "" # Determine download URL based on architecture $nodeVersion = "20.19.0" # LTS version switch ($Arch) { "x64" { $installerFile = "node-v$nodeVersion-x64.msi" } "x86" { $installerFile = "node-v$nodeVersion-x86.msi" } "arm64" { $installerFile = "node-v$nodeVersion-arm64.msi" } default { $installerFile = "node-v$nodeVersion-x64.msi" } } $downloadUrl = "https://nodejs.org/dist/v$nodeVersion/$installerFile" $installerPath = "$env:TEMP\$installerFile" Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Downloading Node.js v$nodeVersion ($Arch)..." -Color White Write-Info " URL: $downloadUrl" try { # Download with progress $webClient = New-Object System.Net.WebClient $webClient.DownloadFile($downloadUrl, $installerPath) Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Download complete!" -Color Green } catch { Write-Error2 "Failed to download Node.js installer." Write-Info "Please check your internet connection and try again." Write-Info "Or download manually from: https://nodejs.org/" exit 1 } # Install Node.js Write-Host "" Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Installing Node.js (this may take a minute)..." -Color White try { $installArgs = "/i `"$installerPath`" /qn /norestart" $process = Start-Process "msiexec.exe" -ArgumentList $installArgs -Wait -PassThru -NoNewWindow if ($process.ExitCode -eq 0) { Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Installation successful!" -Color Green } elseif ($process.ExitCode -eq 3010) { Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Installation successful (restart may be required)" -Color Yellow } else { throw "MSI installer returned code: $($process.ExitCode)" } } catch { Write-Error2 "Installation failed: $_" Write-Info "Try running the installer manually: $installerPath" exit 1 } # Refresh environment variables Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Refreshing environment variables..." -Color White # Add Node.js to PATH for current session $nodePath = "$env:ProgramFiles\nodejs" if (Test-Path $nodePath) { $env:Path = "$nodePath;$env:APPDATA\npm;$env:Path" } # Also try to refresh from registry $machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine") $userPath = [Environment]::GetEnvironmentVariable("Path", "User") $env:Path = "$machinePath;$userPath" Write-ColorText " done" -Color Green # Cleanup Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Cleaning up installer..." -Color White -NoNewline Remove-Item -Path $installerPath -Force -ErrorAction SilentlyContinue Write-ColorText " done" -Color Green Write-Host "" Write-Success "Node.js installation completed!" Start-Sleep -Seconds 1 } function Test-NodeVerification { Write-Section "✓ Verifying Installation" Write-Step "Checking Node.js and npm versions..." Write-Host "" Start-Sleep -Milliseconds 500 # Refresh PATH $nodePath = "$env:ProgramFiles\nodejs" if (Test-Path $nodePath) { $env:Path = "$nodePath;$env:APPDATA\npm;$env:Path" } $nodeOk = $false $npmOk = $false # Verify Node.js try { $newNodeVersion = & "$nodePath\node.exe" --version 2>$null if (-not $newNodeVersion) { $newNodeVersion = & node --version 2>$null } if ($newNodeVersion) { $versionNum = $newNodeVersion -replace "v", "" $majorVersion = [int]($versionNum.Split('.')[0]) if ($majorVersion -ge 18) { Write-ColorText " ✓ " -Color Green -NoNewline Write-ColorText "Node.js: " -Color White -NoNewline Write-ColorText "$newNodeVersion" -Color Green -NoNewline Write-ColorText " (Compatible!)" -Color Green $nodeOk = $true } else { Write-ColorText " ✗ " -Color Red -NoNewline Write-ColorText "Node.js: " -Color White -NoNewline Write-ColorText "$newNodeVersion (Too old - need v18+)" -Color Red } } else { throw "No version output" } } catch { Write-ColorText " ✗ " -Color Red -NoNewline Write-ColorText "Node.js: " -Color White -NoNewline Write-ColorText "Not found!" -Color Red } # Verify npm try { $newNpmVersion = & "$nodePath\npm.cmd" --version 2>$null if (-not $newNpmVersion) { $newNpmVersion = & npm --version 2>$null } if ($newNpmVersion) { Write-ColorText " ✓ " -Color Green -NoNewline Write-ColorText "npm: " -Color White -NoNewline Write-ColorText "v$newNpmVersion" -Color Green $npmOk = $true } else { throw "No version output" } } catch { Write-ColorText " ✗ " -Color Red -NoNewline Write-ColorText "npm: " -Color White -NoNewline Write-ColorText "Not found!" -Color Red } # Show paths Write-Host "" Write-Info "Node path: $nodePath\node.exe" Write-Info "npm path: $nodePath\npm.cmd" Write-Host "" if ($nodeOk -and $npmOk) { Write-Success "All requirements verified successfully!" return $true } else { Write-Error2 "Verification failed! Please check the installation." return $false } } #------------------------------------------------------------------------------- # Claude Code Installation #------------------------------------------------------------------------------- function Install-ClaudeCode { Write-Section "🚀 Installing Claude Code" Write-Step "Installing Claude Code via npm..." Write-Host "" # Ensure npm is in PATH $nodePath = "$env:ProgramFiles\nodejs" $npmPath = "$env:APPDATA\npm" $env:Path = "$nodePath;$npmPath;$env:Path" Write-ColorText " → " -Color Yellow -NoNewline Write-ColorText "Running npm install..." -Color White Write-Host "" try { # Install Claude Code globally $npmCmd = if (Test-Path "$nodePath\npm.cmd") { "$nodePath\npm.cmd" } else { "npm" } $process = Start-Process -FilePath $npmCmd -ArgumentList "install", "-g", "@anthropic-ai/claude-code" -Wait -PassThru -NoNewWindow -RedirectStandardOutput "$env:TEMP\npm-out.txt" -RedirectStandardError "$env:TEMP\npm-err.txt" # Display output if (Test-Path "$env:TEMP\npm-out.txt") { $output = Get-Content "$env:TEMP\npm-out.txt" -Raw if ($output) { $output.Split("`n") | ForEach-Object { if ($_ -match "added|packages") { Write-ColorText " $_" -Color Green } elseif ($_ -match "WARN") { Write-ColorText " $_" -Color Yellow } elseif ($_.Trim()) { Write-ColorText " $_" -Color DarkGray } } } Remove-Item "$env:TEMP\npm-out.txt" -Force -ErrorAction SilentlyContinue } if (Test-Path "$env:TEMP\npm-err.txt") { $errOutput = Get-Content "$env:TEMP\npm-err.txt" -Raw if ($errOutput -and $errOutput.Trim()) { $errOutput.Split("`n") | ForEach-Object { if ($_ -match "ERR|error") { Write-ColorText " $_" -Color Red } elseif ($_ -match "WARN") { Write-ColorText " $_" -Color Yellow } } } Remove-Item "$env:TEMP\npm-err.txt" -Force -ErrorAction SilentlyContinue } if ($process.ExitCode -ne 0) { throw "npm install failed with exit code: $($process.ExitCode)" } } catch { Write-Error2 "Failed to install Claude Code: $_" Write-Info "Try running manually: npm install -g @anthropic-ai/claude-code" return $false } Write-Host "" # Verify installation $claudePath = "$env:APPDATA\npm\claude.cmd" if (Test-Path $claudePath) { Write-Success "Claude Code installed successfully!" Write-Info "Location: $claudePath" return $true } else { # Check if claude is in PATH $claudeInPath = Get-Command claude -ErrorAction SilentlyContinue if ($claudeInPath) { Write-Success "Claude Code installed successfully!" Write-Info "Location: $($claudeInPath.Source)" return $true } else { Write-Warning2 "Claude Code may have been installed but is not in PATH." Write-Info "Try restarting your terminal or running: refreshenv" return $true } } } #------------------------------------------------------------------------------- # Permission Configuration #------------------------------------------------------------------------------- function Set-ClaudePermissions { Write-Section "🛡 Permission Configuration" Write-Host " Claude Code can run with different permission levels:" Write-Host "" Write-BoxTop Write-BoxEmpty # Option 1 - Normal Mode Write-BoxLineMultiColor -Parts @( @{Text="1."; Color="Cyan"}, @{Text=" Normal Mode"; Color="White"}, @{Text=" (Recommended for most users)"; Color="DarkGray"} ) Write-BoxLine -Text "Claude will ask permission before file edits and commands" -Color DarkGray -Indent 4 Write-BoxLineMultiColor -Parts @( @{Text="✓ Safe ✓ Interactive ✓ Full control"; Color="Green"} ) -Indent 4 Write-BoxEmpty # Option 2 - Auto-Accept Edits Write-BoxLineMultiColor -Parts @( @{Text="2."; Color="Cyan"}, @{Text=" Auto-Accept Edits"; Color="White"} ) Write-BoxLine -Text "Automatically accept file edits, ask for commands" -Color DarkGray -Indent 4 Write-BoxLineMultiColor -Parts @( @{Text="⚡ Faster editing ✓ Command safety"; Color="Yellow"} ) -Indent 4 Write-BoxEmpty # Option 3 - Full Auto Mode Write-BoxLineMultiColor -Parts @( @{Text="3."; Color="Cyan"}, @{Text=" Full Auto Mode"; Color="White"}, @{Text=" (--dangerously-skip-permissions)"; Color="DarkGray"} ) Write-BoxLine -Text "Skip all permission prompts (use with caution!)" -Color DarkGray -Indent 4 Write-BoxLineMultiColor -Parts @( @{Text="⚠ No confirmations ⚠ Full system access"; Color="Red"} ) -Indent 4 Write-BoxEmpty # Option 4 - Don't start Write-BoxLineMultiColor -Parts @( @{Text="4."; Color="Cyan"}, @{Text=" Don't start Claude"; Color="White"} ) Write-BoxLine -Text "Exit installer without starting Claude" -Color DarkGray -Indent 4 Write-BoxEmpty Write-BoxBottom Write-Host "" while ($true) { Write-ColorText " ? " -Color Yellow -NoNewline Write-ColorText "Select permission mode [" -Color White -NoNewline Write-ColorText "1" -Color Green -NoNewline Write-ColorText "/" -Color White -NoNewline Write-ColorText "2" -Color Cyan -NoNewline Write-ColorText "/" -Color White -NoNewline Write-ColorText "3" -Color Red -NoNewline Write-ColorText "/" -Color White -NoNewline Write-ColorText "4" -Color White -NoNewline Write-ColorText "]: " -Color White -NoNewline $choice = Read-Host switch ($choice) { "1" { $script:PermissionMode = "normal" $script:ClaudeCmd = "claude" Write-Success "Selected: Normal Mode" return } "2" { $script:PermissionMode = "auto-edit" $script:ClaudeCmd = "claude --auto-accept-edits" Write-Success "Selected: Auto-Accept Edits" return } "3" { $script:PermissionMode = "full-auto" Write-Host "" Write-Warning2 "⚠️ WARNING: Full Auto Mode gives Claude unrestricted access!" Write-ColorText " This mode will:" -Color Red Write-ColorText " • Execute commands without confirmation" -Color Red Write-ColorText " • Modify files without asking" -Color Red Write-ColorText " • Have full access to your system" -Color Red Write-Host "" if (Confirm-Action "Are you sure you want to use Full Auto Mode?" -DefaultYes $false) { $script:ClaudeCmd = "claude --dangerously-skip-permissions" Write-Success "Selected: Full Auto Mode" return } else { Write-Host "" Write-Info "Please select a different mode." Write-Host "" } } "4" { $script:PermissionMode = "exit" $script:ClaudeCmd = "" Write-Info "Installation complete. You can start Claude anytime with: claude" return } default { Write-Error2 "Invalid choice. Please enter 1, 2, 3, or 4." } } } } #------------------------------------------------------------------------------- # Launch Claude Code #------------------------------------------------------------------------------- function Start-Claude { if ($PermissionMode -eq "exit") { Write-Section "✓ Installation Complete!" Write-ColorText " Claude Code has been successfully installed!" -Color Green Write-Host "" Write-ColorText " To start Claude Code, open a new terminal and run:" -Color White Write-Host "" Write-ColorText " claude" -Color Cyan -NoNewline Write-ColorText " # Normal mode" -Color DarkGray Write-ColorText " claude --auto-accept-edits" -Color Cyan -NoNewline Write-ColorText " # Auto-accept file edits" -Color DarkGray Write-ColorText " claude --dangerously-skip-permissions" -Color Cyan -NoNewline Write-ColorText " # Full auto mode" -Color DarkGray Write-Host "" Write-Info "If 'claude' is not recognized, restart your terminal to refresh PATH." Write-Host "" Write-Success "Thank you for installing Claude Code!" return } Write-Section "🚀 Launching Claude Code" Write-ColorText " Starting Claude Code with: " -Color White -NoNewline Write-ColorText $ClaudeCmd -Color Cyan Write-Host "" Write-ColorText " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -Color DarkGray Write-Host "" Start-Sleep -Seconds 1 # Ensure PATH is set $npmPath = "$env:APPDATA\npm" $env:Path = "$npmPath;$env:Path" # Launch Claude try { if ($PermissionMode -eq "normal") { & claude } elseif ($PermissionMode -eq "auto-edit") { & claude --auto-accept-edits } else { & claude --dangerously-skip-permissions } } catch { Write-Error2 "Failed to start Claude Code." Write-Info "Try opening a new terminal and running: $ClaudeCmd" } } #------------------------------------------------------------------------------- # Main Script Execution #------------------------------------------------------------------------------- function Main { # Check Windows version if ([Environment]::OSVersion.Platform -ne "Win32NT") { Write-Error2 "This script is designed for Windows only." exit 1 } # Display banner Write-Banner Write-ColorText " Welcome to the Claude Code Installer!" -Color White Write-Host "" Write-ColorText " This script will:" -Color DarkGray Write-ColorText " 1. Detect your Windows system" -Color DarkGray Write-ColorText " 2. Check/install Node.js 20 LTS" -Color DarkGray Write-ColorText " 3. Install Claude Code" -Color DarkGray Write-ColorText " 4. Configure permissions" -Color DarkGray Write-Host "" if (-not (Confirm-Action "Ready to begin installation?")) { Write-Host "" Write-Info "Installation cancelled. Goodbye!" exit 0 } # Run installation steps Get-SystemInfo Test-NodeInstallation if (-not (Test-NodeVerification)) { exit 1 } if (-not (Install-ClaudeCode)) { exit 1 } Set-ClaudePermissions Start-Claude } # Run main function Main