Last active
October 29, 2025 06:19
-
-
Save robertsinfosec/36227f5b4c1a7ec45a2526070358f47b to your computer and use it in GitHub Desktop.
Add LLM CLI's via PowerShell. This first installs the Node Version Manager (NVM), then installs the latest NodeJS. Then, this installs: Google Gemini CLI, Anthropic Claude CLI, GitHub Copilot CLI, OpenCode (for running against Ollama), and OpenAI's Codex CLI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Install-LlmClis.ps1 | |
| Set-StrictMode -Version Latest | |
| $ErrorActionPreference = 'Stop' | |
| # --- 0) Require Administrator --- | |
| $IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() | |
| ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) | |
| if (-not $IsAdmin) { throw "This script must be run from an Administrator PowerShell." } | |
| # --- 1) Ensure winget --- | |
| if (-not (Get-Command winget -ErrorAction SilentlyContinue)) { | |
| throw "winget is required. Install 'App Installer' from Microsoft Store, then re-run." | |
| } | |
| function Install-WinGetPackage { | |
| param([Parameter(Mandatory=$true)][string]$Id) | |
| $null = winget list --exact --id $Id --accept-source-agreements --accept-package-agreements 2>$null | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Host "✓ $Id already installed." | |
| return | |
| } | |
| winget install --exact --id $Id --source winget ` | |
| --accept-source-agreements --accept-package-agreements --silent | |
| } | |
| # --- 2) Prereqs --- | |
| Install-WinGetPackage -Id "Git.Git" | |
| Install-WinGetPackage -Id "CoreyButler.NVMforWindows" | |
| # --- 3) Locate nvm.exe robustly (FIXED) --- | |
| function Get-NvmExe { | |
| # Prefer what's on PATH | |
| $cmd = Get-Command nvm.exe -ErrorAction SilentlyContinue | |
| if ($cmd) { return $cmd.Source } | |
| # Common install locations | |
| $candidates = @( | |
| (Join-Path $env:ProgramFiles "nvm\nvm.exe"), | |
| (Join-Path ${env:ProgramFiles(x86)} "nvm\nvm.exe"), | |
| (Join-Path $env:LOCALAPPDATA "nvm\nvm.exe"), | |
| (Join-Path $env:LOCALAPPDATA "Programs\nvm\nvm.exe") | |
| ) | Where-Object { $_ -and (Test-Path $_) } | |
| if ($candidates -and $candidates.Count -gt 0) { return $candidates[0] } | |
| # Last resort: bounded search | |
| $roots = @($env:ProgramFiles, ${env:ProgramFiles(x86)}, $env:LOCALAPPDATA) | Where-Object { $_ } | |
| foreach ($r in $roots) { | |
| $found = Get-ChildItem -Path $r -Filter 'nvm.exe' -File -Recurse -ErrorAction SilentlyContinue | | |
| Select-Object -First 1 | |
| if ($found) { return $found.FullName } | |
| } | |
| return $null | |
| } | |
| $NvmExe = Get-NvmExe | |
| if (-not $NvmExe) { | |
| throw "nvm.exe not found after install. Close and reopen an **Administrator** PowerShell and re-run. If it persists, verify the nvm-windows install." | |
| } | |
| Write-Host "nvm.exe: $NvmExe" | |
| # --- 4) Discover latest Node LTS and activate it --- | |
| try { | |
| $index = Invoke-RestMethod -UseBasicParsing -Uri "https://nodejs.org/dist/index.json" | |
| $latestLts = ($index | Where-Object { $_.lts -ne $false } | Select-Object -First 1).version.TrimStart('v') | |
| } catch { | |
| throw "Failed to query Node releases. Check network and try again." | |
| } | |
| & $NvmExe install $latestLts | Out-Null | |
| & $NvmExe use $latestLts | Out-Null | |
| # --- 5) Resolve node/npm from the active toolchain (no hardcoded paths) --- | |
| function Resolve-Cmd([string]$name) { | |
| $cmd = Get-Command $name -ErrorAction SilentlyContinue | |
| if ($cmd) { return $cmd.Source } | |
| $path = (& where.exe $name) 2>$null | Select-Object -First 1 | |
| if ($path) { return $path } | |
| return $null | |
| } | |
| $NodeExe = Resolve-Cmd "node.exe" | |
| $NpmCmd = Resolve-Cmd "npm.cmd" | |
| if (-not $NodeExe) { throw "Node not found in PATH after 'nvm use'. Open a NEW Admin PowerShell and re-run." } | |
| if (-not $NpmCmd) { throw "npm not found in PATH after 'nvm use'. Open a NEW Admin PowerShell and re-run." } | |
| Write-Host ("node: {0} | npm: {1}" -f (& $NodeExe -v), (& $NpmCmd -v)) | |
| # --- 6) Global CLI installs (safe to re-run) --- | |
| $packages = @( | |
| "@google/gemini-cli@latest", | |
| "@anthropic-ai/claude-code@latest", | |
| "@github/copilot@latest", | |
| "opencode-ai@latest", | |
| "@openai/codex@latest" | |
| ) | |
| foreach ($pkg in $packages) { | |
| Write-Host "Installing $pkg ..." | |
| & $NpmCmd install -g $pkg | |
| } | |
| # --- 7) Quick sanity (non-fatal) --- | |
| $cmds = @("gemini", "claude", "copilot", "opencode", "codex") | |
| foreach ($c in $cmds) { | |
| try { & $c --version 2>$null | Out-Host } catch { } | |
| } | |
| Write-Host "✅ Done. If commands aren't found, open a NEW Admin PowerShell and try again." | |
| Write-Host " Note: Codex CLI on Windows is experimental; WSL (Ubuntu) is recommended if you hit issues." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment