Public/Invoke-LocalPilot.ps1
|
function Invoke-LocalPilot { <# .SYNOPSIS Local zero-cloud workstation provisioner and Machine-as-Code engine. .DESCRIPTION Configures, debloats, hardens, tunes, and installs software stacks on fresh Windows installations, hypervisor lab VMs, or personal gaming rigs without requiring Entra ID join or cloud Intune licenses. .PARAMETER Persona Predefined persona blueprint. Options: DevWorkstation, HomelabVM, GamingMinimal, FamilyClean. .PARAMETER RecipePath Path to a custom JSON recipe file. .PARAMETER Debloat Removes pre-installed consumer AppX bloat while preserving essential system apps. .PARAMETER HardenPrivacy Hardens telemetry, disables Bing start menu search, and disables silent app suggestions. .PARAMETER ConfigurePerformance Enables high performance power plans and tunes responsiveness. .PARAMETER InstallWingetPackages Additional or override Winget package IDs to install unattended. .PARAMETER EnableFeatures Windows optional features to enable (e.g. WSL, Hyper-V). .PARAMETER BirthCertificate Generates a post-provision hardware manifest & Markdown birth certificate. .PARAMETER BirthCertificatePath Path to save the generated birth certificate markdown file. .EXAMPLE Invoke-LocalPilot -Persona DevWorkstation -BirthCertificate .EXAMPLE Start-LocalPilot -Persona GamingMinimal -Debloat -HardenPrivacy -ConfigurePerformance #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Position = 0)] [ValidateSet('DevWorkstation', 'HomelabVM', 'GamingMinimal', 'FamilyClean')] [string]$Persona = 'DevWorkstation', [Parameter()] [string]$RecipePath, [Parameter()] [switch]$Debloat, [Parameter()] [switch]$HardenPrivacy, [Parameter()] [switch]$ConfigurePerformance, [Parameter()] [string[]]$InstallWingetPackages, [Parameter()] [string[]]$EnableFeatures, [Parameter()] [switch]$BirthCertificate, [Parameter()] [string]$BirthCertificatePath = ".\Workstation-BirthCertificate-$($env:COMPUTERNAME).md" ) Write-Host "" Write-Host "==========================================================" -ForegroundColor Cyan Write-Host " 🚀 LocalPilot v1.0.0 - Local Workstation Provisioner " -ForegroundColor Cyan Write-Host "==========================================================" -ForegroundColor Cyan Write-Host "" # Load recipe $recipe = if ($RecipePath) { Write-Host " [LocalPilot] Loading custom recipe from: $RecipePath" -ForegroundColor Gray Get-LocalPilotRecipe -Path $RecipePath } else { Write-Host " [LocalPilot] Applying persona blueprint: $Persona" -ForegroundColor Gray Get-LocalPilotRecipe -Persona $Persona } $shouldDebloat = $Debloat.IsPresent -or $recipe.Debloat $shouldHarden = $HardenPrivacy.IsPresent -or $recipe.HardenPrivacy $shouldPerf = $ConfigurePerformance.IsPresent -or $recipe.ConfigurePerformance $packagesToInstall = if ($InstallWingetPackages) { $InstallWingetPackages } else { $recipe.WingetPackages } $featuresToEnable = if ($EnableFeatures) { $EnableFeatures } else { $recipe.WindowsFeatures } # 1. Debloat if ($shouldDebloat) { if ($PSCmdlet.ShouldProcess("System", "Remove consumer bloatware AppX packages")) { Write-Host " [LocalPilot] Debloating consumer AppX packages..." -ForegroundColor Yellow $bloatPatterns = @( '*Clipchamp*', '*BingNews*', '*BingWeather*', '*MicrosoftSolitaireCollection*', '*Xbox*', '*GamingApp*', '*YourPhone*', '*People*', '*FeedbackHub*', '*GetHelp*', '*Getstarted*', '*OfficeHub*', '*SkypeApp*', '*ZuneMusic*', '*ZuneVideo*', '*SpotifyAB.SpotifyMusic*', '*TikTok*', '*Disney*', '*Instagram*', '*Facebook*' ) foreach ($pattern in $bloatPatterns) { $apps = Get-AppxPackage -Name $pattern -ErrorAction SilentlyContinue foreach ($app in $apps) { Write-Host " [-] Removing AppX: $($app.Name)" -ForegroundColor DarkGray Remove-AppxPackage -Package $app.PackageFullName -ErrorAction SilentlyContinue } # If running elevated, remove provisioned package $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if ($isAdmin) { Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like $pattern } | ForEach-Object { Write-Host " [-] De-provisioning: $($_.DisplayName)" -ForegroundColor DarkGray Remove-AppxProvisionedPackage -Online -PackageName $_.PackageName -ErrorAction SilentlyContinue | Out-Null } } } } } # 2. Privacy & Registry Hardening if ($shouldHarden) { if ($PSCmdlet.ShouldProcess("Registry", "Harden telemetry and disable Start search web injection")) { Write-Host " [LocalPilot] Hardening privacy and explorer registry settings..." -ForegroundColor Yellow # Disable Bing web search in Start Menu $searchPolicyPath = 'HKCU:\Software\Policies\Microsoft\Windows\Explorer' if (-not (Test-Path $searchPolicyPath)) { New-Item -Path $searchPolicyPath -Force | Out-Null } Set-ItemProperty -Path $searchPolicyPath -Name 'DisableSearchBoxSuggestions' -Value 1 -Type DWord -Force # Show known file extensions $explorerAdv = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' if (Test-Path $explorerAdv) { Set-ItemProperty -Path $explorerAdv -Name 'HideFileExt' -Value 0 -Type DWord -Force } # Disable Consumer Cloud Content & Silent Installs $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if ($isAdmin) { $cloudContentPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent' if (-not (Test-Path $cloudContentPath)) { New-Item -Path $cloudContentPath -Force | Out-Null } Set-ItemProperty -Path $cloudContentPath -Name 'DisableWindowsConsumerFeatures' -Value 1 -Type DWord -Force # Restrict Telemetry to Security / Minimum $dataCollectionPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection' if (-not (Test-Path $dataCollectionPath)) { New-Item -Path $dataCollectionPath -Force | Out-Null } Set-ItemProperty -Path $dataCollectionPath -Name 'AllowTelemetry' -Value 0 -Type DWord -Force } Write-Host " [+] Privacy and Explorer tweaks applied." -ForegroundColor DarkGray } } # 3. Performance Tuning if ($shouldPerf) { if ($PSCmdlet.ShouldProcess("System", "Configure high performance power plan & responsiveness")) { Write-Host " [LocalPilot] Configuring performance optimizations..." -ForegroundColor Yellow try { # High Performance power scheme GUID & powercfg -setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 2>$null Write-Host " [+] Power scheme set to High Performance." -ForegroundColor DarkGray } catch { Write-Verbose "Could not switch power scheme: $_" } } } # 4. Windows Features if ($featuresToEnable -and $featuresToEnable.Count -gt 0) { $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if ($isAdmin) { foreach ($feature in $featuresToEnable) { if ($PSCmdlet.ShouldProcess("Feature: $feature", "Enable Windows Optional Feature")) { Write-Host " [LocalPilot] Enabling feature: $feature" -ForegroundColor Cyan Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart -ErrorAction SilentlyContinue | Out-Null } } } else { Write-Warning " [LocalPilot] Administrator privileges required to enable Windows Features ($($featuresToEnable -join ', ')). Skipping." } } # 5. Winget Packages if ($packagesToInstall -and $packagesToInstall.Count -gt 0) { $wingetCmd = Get-Command -Name 'winget' -ErrorAction SilentlyContinue if ($wingetCmd) { Write-Host " [LocalPilot] Installing Winget software stack ($($packagesToInstall.Count) packages)..." -ForegroundColor Cyan foreach ($pkgId in $packagesToInstall) { if ($PSCmdlet.ShouldProcess("Package: $pkgId", "Install via Winget")) { Write-Host " --> Installing $pkgId..." -ForegroundColor White & winget install --id $pkgId --exact --silent --accept-source-agreements --accept-package-agreements 2>&1 | Out-Null } } } else { Write-Warning " [LocalPilot] Winget CLI not detected in current path. Skipping software installs." } } # 6. Birth Certificate if ($BirthCertificate.IsPresent) { Write-Host " [LocalPilot] Generating Workstation Birth Certificate..." -ForegroundColor Green New-WorkstationBirthCertificate -OutputPath $BirthCertificatePath } Write-Host "" Write-Host "==========================================================" -ForegroundColor Green Write-Host " ✨ LocalPilot Provisioning Complete! " -ForegroundColor Green Write-Host "==========================================================" -ForegroundColor Green Write-Host "" } |