# ============================================================================== # AI Skills Bundle Installer for Windows PowerShell # The Agentic Engineering Spine for AI Agents # https://dmg-skills.pages.dev # ============================================================================== [CmdletBinding()] param( [switch]$Local, [string]$TargetDir = "", [string]$Version = "latest", [switch]$Force, [switch]$DryRun, [switch]$Uninstall, [switch]$Help ) $ErrorActionPreference = 'Stop' $InstallerVersion = "1.0.0" $BaseUrl = "https://dmg-skills.pages.dev" if ($env:SKILLS_BASE_URL) { $BaseUrl = $env:SKILLS_BASE_URL } if ($Help) { Write-Host @" AI Skills Bundle Installer for Windows (PowerShell) Usage: irm https://dmg-skills.pages.dev/install.ps1 | iex powershell -ExecutionPolicy Bypass -File install.ps1 [OPTIONS] Parameters: -Local Install into .\.agents\skills in current folder -TargetDir Install into custom target directory -Version Install specific version (Default: latest) -Force Overwrite existing skill files without prompting -DryRun Simulate installation without making changes -Uninstall Remove the installed skills bundle -Help Display this help message Examples: irm https://dmg-skills.pages.dev/install.ps1 | iex & { [scriptblock]::Create((irm https://dmg-skills.pages.dev/install.ps1)) } -Local & { [scriptblock]::Create((irm https://dmg-skills.pages.dev/install.ps1)) } -DryRun "@ exit 0 } Write-Host " ___ ____ _____ __ _ ____ " -ForegroundColor Cyan Write-Host " / | / _/ / ___// /__(_) / /____ " -ForegroundColor Cyan Write-Host "/ /| | / / \__ \/ //_/ / / / ___/ " -ForegroundColor Cyan Write-Host "/ ___ |_/ / ___/ / ,< / / / (__ ) " -ForegroundColor Cyan Write-Host "/_/ |_/___/ /____/_/|_/_/_/_/____/ " -ForegroundColor Cyan Write-Host " The Agentic Engineering Spine for AI Agents (v$InstallerVersion)" -ForegroundColor DarkGray Write-Host " https://dmg-skills.pages.dev`n" -ForegroundColor DarkGray function Select-InstallScope { param( [string]$WorkspacePath ) $options = @( @{ Label = "Global (~/.agents/skills)"; Desc = "Recommended (available across all projects)"; Value = "Global" }, @{ Label = "Local (./.agents/skills)"; Desc = "Current workspace only ($WorkspacePath\.agents\skills)"; Value = "Local" } ) $selected = 0 try { if (-not [Environment]::UserInteractive -or [Console]::IsInputRedirected) { return "Global" } } catch { return "Global" } try { [Console]::CursorVisible = $false } catch {} Write-Host "? Select installation target scope (Use [Up/Down] arrows, press [Enter]):" -ForegroundColor Cyan $startTop = [Console]::CursorTop $done = $false while (-not $done) { for ($i = 0; $i -lt $options.Count; $i++) { $opt = $options[$i] if ($i -eq $selected) { Write-Host " > " -ForegroundColor Green -NoNewline Write-Host "$($opt.Label)" -ForegroundColor Green -NoNewline Write-Host " - $($opt.Desc)" -ForegroundColor DarkGray } else { Write-Host " $($opt.Label) - $($opt.Desc)" -ForegroundColor Gray } } try { $key = [Console]::ReadKey($true) if ($key.Key -eq [ConsoleKey]::UpArrow) { $selected = ($selected - 1 + $options.Count) % $options.Count } elseif ($key.Key -eq [ConsoleKey]::DownArrow) { $selected = ($selected + 1) % $options.Count } elseif ($key.Key -eq [ConsoleKey]::Enter) { $done = $true } elseif ($key.KeyChar -eq '1') { $selected = 0 $done = $true } elseif ($key.KeyChar -eq '2') { $selected = 1 $done = $true } } catch { $done = $true } if (-not $done) { try { [Console]::SetCursorPosition(0, $startTop) } catch { $done = $true } } } try { [Console]::CursorVisible = $true } catch {} Write-Host "" return $options[$selected].Value } if (-not $Local -and $TargetDir -eq "" -and -not $env:SKILLS_DIR -and -not $Uninstall -and -not $DryRun -and -not $Force) { $currentLoc = (Get-Location).Path $chosenScope = Select-InstallScope -WorkspacePath $currentLoc if ($chosenScope -eq "Local") { $Local = $true } } $ResolvedDir = "$HOME\.agents\skills" $Mode = "Global" if ($Local) { $ResolvedDir = Join-Path (Get-Location) ".agents\skills" $Mode = "Local" } elseif ($TargetDir -ne "") { $ResolvedDir = $TargetDir $Mode = "Custom" } elseif ($env:SKILLS_DIR) { $ResolvedDir = $env:SKILLS_DIR $Mode = "Custom (env)" } if ($Uninstall) { Write-Host "==> Uninstall requested for target: $ResolvedDir" -ForegroundColor Cyan if (Test-Path $ResolvedDir) { if ($DryRun) { Write-Host "[DRY-RUN] Would remove folder: $ResolvedDir" -ForegroundColor Yellow } else { Remove-Item -Path $ResolvedDir -Recurse -Force Write-Host " [OK] Skills bundle removed successfully from $ResolvedDir" -ForegroundColor Green } } else { Write-Host " [!] Target folder does not exist: $ResolvedDir" -ForegroundColor Yellow } exit 0 } Write-Host "==> Target installation directory: $ResolvedDir ($Mode)" -ForegroundColor Cyan Write-Host "==> Fetching skills release bundle..." -ForegroundColor Cyan if ($DryRun) { Write-Host "[DRY-RUN] Dry run mode enabled. No changes will be written to disk." -ForegroundColor Yellow } $TempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("skills-install-" + [System.Guid]::NewGuid().ToString("N")) New-Item -ItemType Directory -Path $TempDir -Force | Out-Null try { $ZipUrl = "$BaseUrl/skills-bundle.zip" $ZipFile = Join-Path $TempDir "skills-bundle.zip" Write-Host "==> Downloading $ZipUrl..." -ForegroundColor DarkGray Invoke-WebRequest -Uri $ZipUrl -OutFile $ZipFile -UseBasicParsing if (-not (Test-Path $ZipFile) -or (Get-Item $ZipFile).Length -eq 0) { throw "Downloaded archive is empty or invalid." } $StageDir = Join-Path $TempDir "staged" Expand-Archive -Path $ZipFile -DestinationPath $StageDir -Force $SourceDir = Join-Path $StageDir "skills" if (-not (Test-Path $SourceDir)) { $SourceDir = $StageDir } $SkillFolders = Get-ChildItem -Path $SourceDir -Directory $SkillCount = $SkillFolders.Count Write-Host "==> Discovered $SkillCount AI skills in bundle." -ForegroundColor Cyan if ($DryRun) { Write-Host "`nSkills that would be installed:" -ForegroundColor Cyan foreach ($folder in $SkillFolders) { Write-Host " + $($folder.Name) (to $ResolvedDir\$($folder.Name))" -ForegroundColor Green } Write-Host "`n[OK] [DRY-RUN] Simulation completed successfully." -ForegroundColor Green return } if (-not (Test-Path $ResolvedDir)) { New-Item -ItemType Directory -Path $ResolvedDir -Force | Out-Null } foreach ($item in (Get-ChildItem -Path $SourceDir)) { $destPath = Join-Path $ResolvedDir $item.Name if ($item.PSIsContainer) { if (Test-Path $destPath) { Remove-Item -Path $destPath -Recurse -Force } Copy-Item -Path $item.FullName -Destination $destPath -Recurse -Force Write-Host " [OK] Installed $($item.Name)" -ForegroundColor Green } else { Copy-Item -Path $item.FullName -Destination $destPath -Force Write-Host " [OK] Installed $($item.Name)" -ForegroundColor DarkGray } } Write-Host "`n* Installation Complete!" -ForegroundColor Green Write-Host "Installed $SkillCount skills to $ResolvedDir`n" -ForegroundColor White Write-Host "Quick Start Guide:" -ForegroundColor Cyan Write-Host " 1. Initialize repository settings: /init-skills" -ForegroundColor Yellow Write-Host " 2. Shape an idea or architecture: /grill-with-docs" -ForegroundColor Yellow Write-Host " 3. Generate formal specification: /to-spec" -ForegroundColor Yellow Write-Host " 4. Break down tracer tickets: /to-tickets" -ForegroundColor Yellow Write-Host " 5. Implement with TDD seams: /implement" -ForegroundColor Yellow Write-Host " 6. Multi-axis code review: /code-review" -ForegroundColor Yellow Write-Host "`nFor documentation and guides, visit: https://dmg-skills.pages.dev" -ForegroundColor DarkGray } finally { if (Test-Path $TempDir) { Remove-Item -Path $TempDir -Recurse -Force -ErrorAction SilentlyContinue } }