Skip to content

feat(install): add rootless Windows installer (PowerShell)#18

Merged
Palbahngmiyine merged 1 commit into
solapi:mainfrom
Palbahngmiyine:worktree-delegated-growing-pearl
May 11, 2026
Merged

feat(install): add rootless Windows installer (PowerShell)#18
Palbahngmiyine merged 1 commit into
solapi:mainfrom
Palbahngmiyine:worktree-delegated-growing-pearl

Conversation

@Palbahngmiyine
Copy link
Copy Markdown
Member

Summary

  • Add scripts/install.ps1 — rootless, winget-style Windows installer (no admin required). Installs to %LOCALAPPDATA%\Programs\solactl, verifies SHA256 against checksums.txt, extracts the zip, and registers the directory on the user PATH (HKCU\Environment\Path).
  • Mirrors install.sh behavior: TLS 1.2 forced, redirect-bounded download, locked-binary fallback (solactl.exe.old), temp dir cleanup. Supports -Version and -InstallDir overrides.
  • Update README.md with separate Linux/macOS and Windows install sections, an irm | iex one-liner, and the local-execution form for pinned versions / custom paths.

Test plan

  • Run irm https://raw.githubusercontent.com/solapi/solactl/<branch>/scripts/install.ps1 | iex on Windows 11 (amd64) — verify install path, PATH entry, and solactl --version in a new shell.
  • Run powershell -ExecutionPolicy Bypass -File install.ps1 -Version v0.1.6 — verify pinned-version install succeeds.
  • Run installer while solactl.exe is in use — verify fallback to solactl.exe.old.
  • Re-run installer — verify PATH is not duplicated.
  • Run on Windows ARM64 — verify arm64 archive is selected.
  • Confirm install.sh on Linux/macOS still works unchanged (no diff to that file).

🤖 Generated with Claude Code

Adds scripts/install.ps1 mirroring install.sh for Windows: installs to
%LOCALAPPDATA%\Programs\solactl, verifies SHA256, and updates the user
PATH via HKCU — no admin rights needed (winget-style). Documents both
the irm|iex one-liner and the local-execution form with -Version /
-InstallDir options in README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a Windows installation script (install.ps1) and updates the README.md with comprehensive installation and upgrade instructions for Linux, macOS, and Windows. Feedback focuses on enhancing the PowerShell script's reliability, specifically by using throw instead of exit to avoid closing the user's terminal, improving architecture detection for 32-bit shells, handling potential file locks during the upgrade process, and ensuring clean PATH environment variable updates.

Comment thread scripts/install.ps1

function Die([string] $Message) {
Write-Host "ERROR: $Message" -ForegroundColor Red
exit 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using exit 1 in a script intended to be run via iex (Invoke-Expression) will terminate the entire PowerShell session if an error occurs. This is a poor user experience for a one-liner installer. Consider using throw instead, which stops the script execution but keeps the terminal open.

    throw $Message

Comment thread scripts/install.ps1
Comment on lines +57 to +62
$arch = switch ($env:PROCESSOR_ARCHITECTURE) {
'AMD64' { 'amd64' }
'ARM64' { 'arm64' }
'x86' { Die 'Unsupported architecture: x86 (32-bit). solactl ships amd64/arm64 only.' }
default { Die "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE" }
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current architecture detection relies solely on $env:PROCESSOR_ARCHITECTURE, which may return x86 if the user is running a 32-bit PowerShell process on a 64-bit operating system. Checking $env:PROCESSOR_ARCHITEW6432 ensures the script correctly identifies the underlying OS architecture even when running in a 32-bit shell.

$arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64' -or $env:PROCESSOR_ARCHITEW6432 -eq 'AMD64') { 'amd64' }
elseif ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64' -or $env:PROCESSOR_ARCHITEW6432 -eq 'ARM64') { 'arm64' }
else { Die "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE" }

Comment thread scripts/install.ps1
# Existing binary is likely in use by a running process.
# Park the old one so the install still succeeds.
$stash = "$dest.old"
if (Test-Path -LiteralPath $stash) { Remove-Item -LiteralPath $stash -Force }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the .old file is locked (e.g., by a previous failed installation where the process is still running), Remove-Item will throw an error and stop the script because $ErrorActionPreference is set to Stop. Adding -ErrorAction SilentlyContinue prevents a crash in this edge case.

        if (Test-Path -LiteralPath $stash) { Remove-Item -LiteralPath $stash -Force -ErrorAction SilentlyContinue }

Comment thread scripts/install.ps1
}

if (-not $alreadyOnPath) {
$newPath = if ($userPath) { "$userPath;$InstallDir" } else { $InstallDir }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current logic for constructing the new PATH string might result in double semicolons (e.g., path1;;path2) if the existing user PATH already ends with a semicolon. Using the $entries array to join the paths is cleaner and more robust.

        $newPath = ($entries + $InstallDir) -join ';'

@Palbahngmiyine Palbahngmiyine merged commit 2d2d589 into solapi:main May 11, 2026
2 checks passed
@Palbahngmiyine Palbahngmiyine deleted the worktree-delegated-growing-pearl branch May 11, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant