Files
moltbot/scripts/install.ps1
Hiren Thakore 193ad2f4f0 fix: handle PowerShell execution policy on Windows install (#24794)
* fix: add Arch Linux support to install.sh (GH#8051)

* fix: handle PowerShell execution policy on Windows install (GH#24784)
2026-03-02 11:09:01 -06:00

330 lines
10 KiB
PowerShell

# OpenClaw Installer for Windows (PowerShell)
# Usage: iwr -useb https://openclaw.ai/install.ps1 | iex
# Or: & ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
param(
[string]$InstallMethod = "npm",
[string]$Tag = "latest",
[string]$GitDir = "$env:USERPROFILE\openclaw",
[switch]$NoOnboard,
[switch]$NoGitUpdate,
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
# Colors
$ACCENT = "`e[38;2;255;77;77m" # coral-bright
$SUCCESS = "`e[38;2;0;229;204m" # cyan-bright
$WARN = "`e[38;2;255;176;32m" # amber
$ERROR = "`e[38;2;230;57;70m" # coral-mid
$MUTED = "`e[38;2;90;100;128m" # text-muted
$NC = "`e[0m" # No Color
function Write-Host {
param([string]$Message, [string]$Level = "info")
$msg = switch ($Level) {
"success" { "$SUCCESS$NC $Message" }
"warn" { "$WARN!$NC $Message" }
"error" { "$ERROR$NC $Message" }
default { "$MUTED·$NC $Message" }
}
Microsoft.PowerShell.Host\Write-Host $msg
}
function Write-Banner {
Write-Host ""
Write-Host "${ACCENT} 🦞 OpenClaw Installer$NC" -Level info
Write-Host "${MUTED} All your chats, one OpenClaw.$NC" -Level info
Write-Host ""
}
function Get-ExecutionPolicyStatus {
$policy = Get-ExecutionPolicy
if ($policy -eq "Restricted" -or $policy -eq "AllSigned") {
return @{ Blocked = $true; Policy = $policy }
}
return @{ Blocked = $false; Policy = $policy }
}
function Test-Admin {
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Ensure-ExecutionPolicy {
$status = Get-ExecutionPolicyStatus
if ($status.Blocked) {
Write-Host "PowerShell execution policy is set to: $($status.Policy)" -Level warn
Write-Host "This prevents scripts like npm.ps1 from running." -Level warn
Write-Host ""
# Try to set execution policy for current process
try {
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -ErrorAction Stop
Write-Host "Set execution policy to RemoteSigned for current process" -Level success
return $true
} catch {
Write-Host "Could not automatically set execution policy" -Level error
Write-Host ""
Write-Host "To fix this, run:" -Level info
Write-Host " Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process" -Level info
Write-Host ""
Write-Host "Or run PowerShell as Administrator and execute:" -Level info
Write-Host " Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine" -Level info
return $false
}
}
return $true
}
function Get-NodeVersion {
try {
$version = node --version 2>$null
if ($version) {
return $version -replace '^v', ''
}
} catch { }
return $null
}
function Get-NpmVersion {
try {
$version = npm --version 2>$null
if ($version) {
return $version
}
} catch { }
return $null
}
function Install-Node {
Write-Host "Node.js not found" -Level info
Write-Host "Installing Node.js..." -Level info
# Try winget first
if (Get-Command winget -ErrorAction SilentlyContinue) {
Write-Host " Using winget..." -Level info
try {
winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements 2>&1 | Out-Null
# Refresh PATH
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Write-Host " Node.js installed via winget" -Level success
return $true
} catch {
Write-Host " Winget install failed: $_" -Level warn
}
}
# Try chocolatey
if (Get-Command choco -ErrorAction SilentlyContinue) {
Write-Host " Using chocolatey..." -Level info
try {
choco install nodejs-lts -y 2>&1 | Out-Null
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Write-Host " Node.js installed via chocolatey" -Level success
return $true
} catch {
Write-Host " Chocolatey install failed: $_" -Level warn
}
}
# Try scoop
if (Get-Command scoop -ErrorAction SilentlyContinue) {
Write-Host " Using scoop..." -Level info
try {
scoop install nodejs-lts 2>&1 | Out-Null
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Write-Host " Node.js installed via scoop" -Level success
return $true
} catch {
Write-Host " Scoop install failed: $_" -Level warn
}
}
Write-Host "Could not install Node.js automatically" -Level error
Write-Host "Please install Node.js 22+ manually from: https://nodejs.org" -Level info
return $false
}
function Ensure-Node {
$nodeVersion = Get-NodeVersion
if ($nodeVersion) {
$major = [int]($nodeVersion -split '\.')[0]
if ($major -ge 22) {
Write-Host "Node.js v$nodeVersion found" -Level success
return $true
}
Write-Host "Node.js v$nodeVersion found, but need v22+" -Level warn
}
return Install-Node
}
function Get-GitVersion {
try {
$version = git --version 2>$null
if ($version) {
return $version
}
} catch { }
return $null
}
function Install-Git {
Write-Host "Git not found" -Level info
if (Get-Command winget -ErrorAction SilentlyContinue) {
Write-Host " Installing Git via winget..." -Level info
try {
winget install Git.Git --accept-package-agreements --accept-source-agreements 2>&1 | Out-Null
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Write-Host " Git installed" -Level success
return $true
} catch {
Write-Host " Winget install failed" -Level warn
}
}
Write-Host "Please install Git for Windows from: https://git-scm.com" -Level error
return $false
}
function Ensure-Git {
$gitVersion = Get-GitVersion
if ($gitVersion) {
Write-Host "$gitVersion found" -Level success
return $true
}
return Install-Git
}
function Install-OpenClawNpm {
param([string]$Version = "latest")
Write-Host "Installing OpenClaw (openclaw@$Version)..." -Level info
try {
# Use -ExecutionPolicy Bypass to handle restricted execution policy
npm install -g openclaw@$Version --no-fund --no-audit 2>&1
Write-Host "OpenClaw installed" -Level success
return $true
} catch {
Write-Host "npm install failed: $_" -Level error
return $false
}
}
function Install-OpenClawGit {
param([string]$RepoDir, [switch]$Update)
Write-Host "Installing OpenClaw from git..." -Level info
if (!(Test-Path $RepoDir)) {
Write-Host " Cloning repository..." -Level info
git clone https://github.com/openclaw/openclaw.git $RepoDir 2>&1
} elseif ($Update) {
Write-Host " Updating repository..." -Level info
git -C $RepoDir pull --rebase 2>&1
}
# Install pnpm if not present
if (!(Get-Command pnpm -ErrorAction SilentlyContinue)) {
Write-Host " Installing pnpm..." -Level info
npm install -g pnpm 2>&1
}
# Install dependencies
Write-Host " Installing dependencies..." -Level info
pnpm install --dir $RepoDir 2>&1
# Build
Write-Host " Building..." -Level info
pnpm --dir $RepoDir build 2>&1
# Create wrapper
$wrapperDir = "$env:USERPROFILE\.local\bin"
if (!(Test-Path $wrapperDir)) {
New-Item -ItemType Directory -Path $wrapperDir -Force | Out-Null
}
@"
@echo off
node "%~dp0..\openclaw\dist\entry.js" %*
"@ | Out-File -FilePath "$wrapperDir\openclaw.cmd" -Encoding ASCII -Force
Write-Host "OpenClaw installed" -Level success
return $true
}
function Add-ToPath {
param([string]$Path)
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($currentPath -notlike "*$Path*") {
[Environment]::SetEnvironmentVariable("Path", "$currentPath;$Path", "User")
Write-Host "Added $Path to user PATH" -Level info
}
}
# Main
function Main {
Write-Banner
Write-Host "Windows detected" -Level success
# Check and handle execution policy FIRST, before any npm calls
if (!(Ensure-ExecutionPolicy)) {
Write-Host ""
Write-Host "Installation cannot continue due to execution policy restrictions" -Level error
exit 1
}
if (!(Ensure-Node)) {
exit 1
}
if ($InstallMethod -eq "git") {
if (!(Ensure-Git)) {
exit 1
}
if ($DryRun) {
Write-Host "[DRY RUN] Would install OpenClaw from git to $GitDir" -Level info
} else {
Install-OpenClawGit -RepoDir $GitDir -Update:(-not $NoGitUpdate)
}
} else {
# npm method
if (!(Ensure-Git)) {
Write-Host "Git is required for npm installs. Please install Git and try again." -Level warn
}
if ($DryRun) {
Write-Host "[DRY RUN] Would install OpenClaw via npm (tag: $Tag)" -Level info
} else {
if (!(Install-OpenClawNpm -Version $Tag)) {
exit 1
}
}
}
# Try to add npm global bin to PATH
try {
$npmPrefix = npm config get prefix 2>$null
if ($npmPrefix) {
Add-ToPath -Path "$npmPrefix"
}
} catch { }
if (!$NoOnboard -and !$DryRun) {
Write-Host ""
Write-Host "Run 'openclaw onboard' to complete setup" -Level info
}
Write-Host ""
Write-Host "🦞 OpenClaw installed successfully!" -Level success
}
Main