feat: add NSIS installer and classroom admin checklist

Closes #1983

- Add scripts/installer/codewhale.nsi: NSIS installer that installs both
  codewhale.exe and codewhale-tui.exe to %LOCALAPPDATA%\Programs\CodeWhale\bin,
  adds to current-user PATH, and includes an uninstaller that cleans PATH
- Add docs/CLASSROOM_INSTALL.md: step-by-step checklist for IT admins
  deploying CodeWhale in labs/classrooms, covering silent install, manual
  fallback, API key provisioning, imaging notes, and troubleshooting
- Update docs/INSTALL.md: add Windows NSIS Installer section referencing
  the new installer and classroom checklist
This commit is contained in:
songzhenrui
2026-05-25 10:36:19 +08:00
committed by Hunter B
parent c92f3c350b
commit c2c36cca11
3 changed files with 417 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
# CodeWhale Classroom / Lab Install Checklist
A step-by-step checklist for IT admins deploying CodeWhale on lab or classroom
machines running Windows.
> **Audience**: IT staff, teaching assistants, lab managers.
> **Prereq**: Each target machine runs Windows 10 (1809+) or Windows 11.
---
## Pre-install checklist (run once per machine)
| # | Task | Done? |
|---|------|-------|
| 1 | Confirm Windows version: `winver` → 10 build 17763+ or 11 | ☐ |
| 2 | Ensure the user account is a **standard user** (not a local admin). The installer does not require elevation. | ☐ |
| 3 | Verify outbound HTTPS (port 443) is open to `api.openai.com` (or whichever LLM provider the course uses). | ☐ |
| 4 | Obtain the installer: download `CodeWhaleSetup.exe` from the [latest release](https://github.com/Hmbown/CodeWhale/releases/latest) or from your department mirror. | ☐ |
| 5 | (Optional) Verify SHA-256 hash matches the published manifest. | ☐ |
---
## Installation
### Option A — Silent install (recommended for imaging / SCCM / Intune)
```powershell
# Run as admin or via deployment tool
CodeWhaleSetup.exe /S
```
The silent installer:
- Installs to `%LOCALAPPDATA%\Programs\CodeWhale\bin`
- Adds the bin directory to the **current user** PATH
- Registers in Windows "Apps & Features" for uninstall
### Option B — Interactive install
1. Double-click `CodeWhaleSetup.exe`.
2. Accept the license.
3. Choose the install directory (default is fine for most setups).
4. Click **Install**.
### Option C — Manual fallback (no installer)
If the NSIS installer is blocked by group policy, install manually:
```powershell
# 1. Create directory
$binDir = "$env:LOCALAPPDATA\Programs\CodeWhale\bin"
New-Item -ItemType Directory -Force -Path $binDir
# 2. Download binaries (adjust URL to your mirror or release tag)
$tag = "v0.9.0" # replace with desired version
Invoke-WebRequest -Uri "https://github.com/Hmbown/CodeWhale/releases/download/$tag/codewhale-x64.exe" -OutFile "$binDir\codewhale.exe"
Invoke-WebRequest -Uri "https://github.com/Hmbown/CodeWhale/releases/download/$tag/codewhale-tui-x64.exe" -OutFile "$binDir\codewhale-tui.exe"
# 3. Add to user PATH (persistent)
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($currentPath -notlike "*$binDir*") {
[Environment]::SetEnvironmentVariable("Path", "$currentPath;$binDir", "User")
}
# 4. Refresh current session PATH
$env:Path = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
```
---
## Post-install verification
Run these on **each machine** (or spot-check a sample):
| # | Command | Expected output | Done? |
|---|---------|-----------------|-------|
| 1 | `codewhale --version` | Prints version string | ☐ |
| 2 | `codewhale doctor` | All checks pass | ☐ |
| 3 | `codewhale-tui --version` | Prints version string | ☐ |
If `codewhale` is not found, the user may need to open a **new** terminal window for PATH changes to take effect.
---
## API key provisioning
Each student needs an API key. Options:
| Method | Pros | Cons |
|--------|------|------|
| **Per-student key** | Individual usage tracking | More key management |
| **Shared lab key** | Simple to deploy | Harder to audit; rate limits shared |
### Deploying a shared key via environment variable
```powershell
# Set for current user (persists across reboots)
[Environment]::SetEnvironmentVariable("OPENAI_API_KEY", "sk-...", "User")
```
Or create a `config.toml` in `%APPDATA%\codewhale\`:
```toml
[provider]
api_key = "sk-..."
base_url = "https://api.openai.com/v1"
```
### Deploying per-student keys with Intune / GPO
Use a Group Policy Preference or Intune PowerShell script to set the
`OPENAI_API_KEY` environment variable per user. The variable name depends on
your LLM provider — see [CONFIGURATION.md](CONFIGURATION.md).
---
## Uninstall
### Silent uninstall
```powershell
& "$env:LOCALAPPDATA\Programs\CodeWhale\Uninstall.exe" /S
```
### Manual uninstall (if installer was not used)
```powershell
$binDir = "$env:LOCALAPPDATA\Programs\CodeWhale\bin"
Remove-Item -Recurse -Force (Split-Path $binDir)
# Remove from PATH
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
$newPath = ($currentPath -split ";" | Where-Object { $_ -ne $binDir }) -join ";"
[Environment]::SetEnvironmentVariable("Path", $newPath, "User")
```
---
## Troubleshooting
| Symptom | Fix |
|---------|-----|
| `codewhale` not found after install | Open a **new** terminal. If still missing, check PATH: `echo $env:Path` |
| `MISSING_COMPANION_BINARY` | Ensure both `codewhale.exe` and `codewhale-tui.exe` are in the same directory |
| `TLS handshake` errors | Check proxy settings or use the CNB mirror (see [INSTALL.md](INSTALL.md)) |
| Antivirus quarantines binaries | Add the install directory to AV exclusions |
| `codewhale doctor` fails API check | Verify `OPENAI_API_KEY` is set or `config.toml` exists |
---
## Imaging / Golden Image Notes
If building a golden image (WIM/FFU):
1. Install CodeWhale using Option A (silent) or Option C (manual).
2. Do **not** set API keys in the image — these are per-user/per-student.
3. The install directory (`%LOCALAPPDATA%\Programs\CodeWhale\bin`) is per-user,
so it will be present for the user who installed it. For other users on the
same machine, run the installer again or use Option C.
4. Alternatively, install to a shared location like `C:\Tools\CodeWhale\bin`
and add it to the **machine** PATH:
```powershell
[Environment]::SetEnvironmentVariable("Path", "$env:Path;C:\Tools\CodeWhale\bin", "Machine")
```
---
## Quick Reference: All file paths
| Item | Default location |
|------|-----------------|
| Binaries | `%LOCALAPPDATA%\Programs\CodeWhale\bin\` |
| User config | `%APPDATA%\codewhale\config.toml` |
| Uninstaller | `%LOCALAPPDATA%\Programs\CodeWhale\Uninstall.exe` |
| PATH entry | `HKCU\Environment\Path` (current user) |
---
*Last updated: 2026-05-25*
+37
View File
@@ -299,6 +299,43 @@ Scoop manifests are maintained outside this repository's release workflow and
can lag GitHub/npm/Cargo releases. Use npm or manual GitHub release downloads
when you need the newest version immediately.
### Windows NSIS Installer
A standalone NSIS-based installer is available for Windows users who prefer a
traditional double-click setup (no npm, no Scoop, no Cargo required).
**Download** `CodeWhaleSetup.exe` from the
[Releases page](https://github.com/Hmbown/CodeWhale/releases/latest).
**Install** by double-clicking the setup executable. The installer:
- Installs `codewhale.exe` and `codewhale-tui.exe` side-by-side into
`%LOCALAPPDATA%\Programs\CodeWhale\bin`
- Adds the install directory to the **current user** `PATH`
- Registers in Windows **Apps & Features** for easy uninstall
**Silent install** (for IT admins, SCCM, Intune):
```powershell
CodeWhaleSetup.exe /S
```
**Build the installer yourself** (requires [NSIS](https://nsis.sourceforge.io)):
```powershell
cd scripts\installer
# Place codewhale.exe and codewhale-tui.exe here, then:
makensis /DVERSION=0.9.0 codewhale.nsi
```
**Manual fallback** — if the installer is blocked by group policy, see the
[CLASSROOM_INSTALL.md](CLASSROOM_INSTALL.md) guide for step-by-step PowerShell
commands.
> **Deploying to a classroom or lab?** See the full
> [Classroom Install Checklist](CLASSROOM_INSTALL.md) for silent install,
> API key provisioning, imaging notes, and troubleshooting.
---
## 7. Build from source
+202
View File
@@ -0,0 +1,202 @@
; codewhale.nsi — NSIS installer for CodeWhale (Windows)
;
; Requirements (see https://github.com/Hmbown/CodeWhale/issues/1983):
; - Install codewhale.exe and codewhale-tui.exe side-by-side
; - Default to %LOCALAPPDATA%\Programs\CodeWhale\bin
; - Add install dir to current-user PATH
; - Uninstaller removes the PATH entry
;
; Usage:
; 1. Place both .exe files next to this script:
; codewhale.exe
; codewhale-tui.exe
; 2. Build:
; makensis codewhale.nsi
; 3. Output: CodeWhaleSetup.exe (in current directory)
;
; You can override version at build time:
; makensis /DVERSION=1.2.3 codewhale.nsi
;--------------------------------
; Includes
;--------------------------------
!include "MUI2.nsh"
!include "FileFunc.nsh"
!include "StrFunc.nsh"
${StrStr}
;--------------------------------
; General
;--------------------------------
!ifndef VERSION
!define VERSION "0.0.0"
!endif
!define PRODUCT_NAME "CodeWhale"
!define PRODUCT_PUBLISHER "Hmbown"
!define PRODUCT_WEB_SITE "https://github.com/Hmbown/CodeWhale"
Name "${PRODUCT_NAME} ${VERSION}"
OutFile "CodeWhaleSetup.exe"
InstallDir "$LOCALAPPDATA\Programs\CodeWhale"
RequestExecutionLevel user
BrandingText "${PRODUCT_NAME} Installer"
;--------------------------------
; Interface Settings
;--------------------------------
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
;--------------------------------
; Pages
;--------------------------------
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\..\LICENSE"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
; Languages
;--------------------------------
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "SimpChinese"
;--------------------------------
; Installer Sections
;--------------------------------
Section "Install" SecInstall
SetOutPath "$INSTDIR\bin"
; Copy binaries
File "codewhale.exe"
File "codewhale-tui.exe"
; Write uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
; Add to current-user PATH
; Read existing PATH, append if not already present
ReadRegStr $0 HKCU "Environment" "Path"
${StrStr} $1 $0 "$INSTDIR\bin"
StrCmp $1 "" 0 path_already_set
; Not found — append
StrCmp $0 "" empty_path
WriteRegExpandStr HKCU "Environment" "Path" "$0;$INSTDIR\bin"
Goto path_done
empty_path:
WriteRegExpandStr HKCU "Environment" "Path" "$INSTDIR\bin"
path_done:
; Notify the system about the environment change
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
path_already_set:
; Store install directory for uninstaller
WriteRegStr HKCU "Software\${PRODUCT_NAME}" "InstallDir" "$INSTDIR"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "${PRODUCT_PUBLISHER}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayVersion" "${VERSION}"
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1
; Calculate and store installed size
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "EstimatedSize" "$0"
SectionEnd
;--------------------------------
; Uninstaller Section
;--------------------------------
Section "Uninstall"
; Remove binaries
Delete "$INSTDIR\bin\codewhale.exe"
Delete "$INSTDIR\bin\codewhale-tui.exe"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR\bin"
RMDir "$INSTDIR"
; Remove from current-user PATH
ReadRegStr $0 HKCU "Environment" "Path"
${StrStr} $1 $0 "$INSTDIR\bin"
StrCmp $1 "" path_clean_done
; Remove the entry
; Build new PATH without the install dir
; This handles: "...\path;$INSTDIR\bin" and "$INSTDIR\bin;...\path" and standalone
Push "$0"
Push "$INSTDIR\bin"
Call un.RemoveFromPath
Pop $0
WriteRegExpandStr HKCU "Environment" "Path" "$0"
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
path_clean_done:
; Remove registry keys
DeleteRegKey HKCU "Software\${PRODUCT_NAME}"
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
SectionEnd
;--------------------------------
; Helper: Remove a directory from PATH
; Input: PATH string (on stack), directory to remove (on stack)
; Output: cleaned PATH (on stack)
;--------------------------------
Function un.RemoveFromPath
Exch $R0 ; directory to remove
Exch
Exch $R1 ; original PATH
Push $R2
Push $R3
Push $R4
StrCpy $R2 ""
StrCpy $R3 ""
loop:
${StrStr} $R4 $R1 $R0
StrCmp $R4 "" done
; Found — get substring before match
StrLen $R4 $R4
StrLen $R3 $R1
IntOp $R3 $R3 - $R4
StrCpy $R2 $R1 $R3
; Get substring after match + dir length
StrLen $R3 $R0
IntOp $R4 $R4 - $R3
StrCpy $R3 $R1 "" $R4
; Strip leading semicolon from remainder
StrCpy $R4 $R3 1
StrCmp $R4 ";" 0 +2
StrCpy $R3 $R3 "" 1
; Strip trailing semicolon from prefix
StrLen $R4 $R2
IntOp $R4 $R4 - 1
StrCpy $R4 $R2 1 $R4
StrCmp $R4 ";" 0 +2
StrCpy $R2 $R2 $R4
; Concatenate
StrCmp $R2 "" 0 +2
StrCpy $R2 $R3
Goto done
StrCmp $R3 "" 0 +2
StrCpy $R1 $R2
Goto done
StrCpy $R1 "$R2;$R3"
Goto done
done:
Pop $R4
Pop $R3
Pop $R2
Pop $R0
Exch $R1
FunctionEnd