Skip to content

Commit b4cecae

Browse files
hlsitechioclaude
andcommitted
feat: upgrade install.ps1 with auto-update support
- Auto-detect existing T3 Code installation via registry - Version comparison: skip download if already on latest - Update mode: upgrades deps via winget/choco, npm CLI tools - Same iex command works for both install and update - Graceful fallback: don't exit if MSI not found (deps still useful) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 48918be commit b4cecae

1 file changed

Lines changed: 146 additions & 72 deletions

File tree

install.ps1

Lines changed: 146 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,70 @@
11
#Requires -Version 5.1
22
<#
33
.SYNOPSIS
4-
One-shot installer for T3 Code desktop app.
4+
One-shot installer & updater for T3 Code desktop app.
55
66
.DESCRIPTION
7-
Downloads and installs the latest T3 Code MSI, plus all required
8-
dependencies (Node.js, Git, GitHub CLI, provider CLIs) via winget
9-
or Chocolatey. Supports future updates through both package managers.
7+
Downloads and installs (or updates) the latest T3 Code MSI, plus all
8+
required dependencies (Node.js, Git, GitHub CLI, provider CLIs) via
9+
winget or Chocolatey.
10+
11+
Run the same command for both install and update — it auto-detects.
1012
1113
.EXAMPLE
14+
# Fresh install or update:
1215
iex (irm https://raw.githubusercontent.com/hlsitechio/t3code/main/install.ps1)
1316
#>
1417

1518
$ErrorActionPreference = "Stop"
16-
$ProgressPreference = "SilentlyContinue"
19+
$ProgressPreference = "SilentlyContinue"
1720

18-
$repo = "hlsitechio/t3code"
21+
$repo = "hlsitechio/t3code"
1922
$appName = "T3 Code"
2023

24+
# ---------------------------------------------------------------------------
25+
# Output helpers
26+
# ---------------------------------------------------------------------------
27+
2128
function Write-Step($msg) { Write-Host " > $msg" -ForegroundColor Cyan }
2229
function Write-Ok($msg) { Write-Host " + $msg" -ForegroundColor Green }
2330
function Write-Skip($msg) { Write-Host " - $msg" -ForegroundColor DarkGray }
2431
function Write-Err($msg) { Write-Host " x $msg" -ForegroundColor Red }
2532
function Write-Warn($msg) { Write-Host " ! $msg" -ForegroundColor Yellow }
2633

34+
# ---------------------------------------------------------------------------
35+
# Detect existing T3 Code installation
36+
# ---------------------------------------------------------------------------
37+
38+
function Get-InstalledT3Version {
39+
# Check registry for MSI-installed version
40+
$paths = @(
41+
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
42+
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
43+
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
44+
)
45+
foreach ($path in $paths) {
46+
try {
47+
$entry = Get-ItemProperty $path -ErrorAction SilentlyContinue |
48+
Where-Object { $_.DisplayName -match "T3.?Code" } |
49+
Select-Object -First 1
50+
if ($entry) {
51+
return $entry.DisplayVersion
52+
}
53+
} catch {}
54+
}
55+
return $null
56+
}
57+
58+
$installedVersion = Get-InstalledT3Version
59+
$isUpdate = $null -ne $installedVersion
60+
2761
Write-Host ""
2862
Write-Host " ========================================" -ForegroundColor White
29-
Write-Host " T3 Code Installer " -ForegroundColor White
63+
if ($isUpdate) {
64+
Write-Host " T3 Code Updater (v$installedVersion) " -ForegroundColor White
65+
} else {
66+
Write-Host " T3 Code Installer " -ForegroundColor White
67+
}
3068
Write-Host " ========================================" -ForegroundColor White
3169
Write-Host ""
3270

@@ -65,34 +103,37 @@ function Refresh-Path {
65103
}
66104

67105
# ---------------------------------------------------------------------------
68-
# Universal package installer (winget > choco > manual)
106+
# Universal package installer/updater (winget > choco > manual)
69107
# ---------------------------------------------------------------------------
70108

71109
function Install-Dep {
72110
param(
73111
[string]$Name,
74112
[string]$WingetId,
75113
[string]$ChocoId,
76-
[string]$ManualUrl
114+
[string]$ManualUrl,
115+
[switch]$ForceUpgrade
77116
)
78117

79118
# Try winget first
80119
if ($hasWinget) {
81-
Write-Step "Installing $Name via winget..."
82-
$result = winget install --id $WingetId --accept-package-agreements --accept-source-agreements --disable-interactivity --silent 2>&1
83-
if ($LASTEXITCODE -eq 0 -or "$result" -match "already installed") {
84-
Write-Ok "$Name installed (winget)"
120+
$action = if ($ForceUpgrade) { "upgrade" } else { "install" }
121+
Write-Step "$( if ($ForceUpgrade) { 'Updating' } else { 'Installing' } ) $Name via winget..."
122+
$result = winget $action --id $WingetId --accept-package-agreements --accept-source-agreements --disable-interactivity --silent 2>&1
123+
if ($LASTEXITCODE -eq 0 -or "$result" -match "already installed" -or "$result" -match "No available upgrade") {
124+
Write-Ok "$Name up to date (winget)"
85125
Refresh-Path
86126
return $true
87127
}
88128
}
89129

90130
# Fallback to Chocolatey
91131
if ($hasChoco) {
92-
Write-Step "Installing $Name via Chocolatey..."
93-
choco install $ChocoId -y --no-progress 2>$null
132+
$action = if ($ForceUpgrade) { "upgrade" } else { "install" }
133+
Write-Step "$( if ($ForceUpgrade) { 'Updating' } else { 'Installing' } ) $Name via Chocolatey..."
134+
choco $action $ChocoId -y --no-progress 2>$null
94135
if ($LASTEXITCODE -eq 0) {
95-
Write-Ok "$Name installed (Chocolatey)"
136+
Write-Ok "$Name up to date (Chocolatey)"
96137
Refresh-Path
97138
return $true
98139
}
@@ -114,23 +155,35 @@ Write-Host " -----------------------" -ForegroundColor DarkGray
114155
# Node.js
115156
if (Test-Command "node") {
116157
$nodeVer = & node --version 2>$null
117-
Write-Ok "Node.js $nodeVer (already installed)"
158+
if ($isUpdate) {
159+
Install-Dep -Name "Node.js LTS" -WingetId "OpenJS.NodeJS.LTS" -ChocoId "nodejs-lts" -ManualUrl "https://nodejs.org" -ForceUpgrade
160+
} else {
161+
Write-Ok "Node.js $nodeVer (already installed)"
162+
}
118163
} else {
119164
Install-Dep -Name "Node.js LTS" -WingetId "OpenJS.NodeJS.LTS" -ChocoId "nodejs-lts" -ManualUrl "https://nodejs.org"
120165
}
121166

122167
# Git
123168
if (Test-Command "git") {
124169
$gitVer = & git --version 2>$null
125-
Write-Ok "$gitVer (already installed)"
170+
if ($isUpdate) {
171+
Install-Dep -Name "Git" -WingetId "Git.Git" -ChocoId "git" -ManualUrl "https://git-scm.com" -ForceUpgrade
172+
} else {
173+
Write-Ok "$gitVer (already installed)"
174+
}
126175
} else {
127176
Install-Dep -Name "Git" -WingetId "Git.Git" -ChocoId "git" -ManualUrl "https://git-scm.com"
128177
}
129178

130179
# GitHub CLI
131180
if (Test-Command "gh") {
132181
$ghVer = & gh --version 2>$null | Select-Object -First 1
133-
Write-Ok "$ghVer (already installed)"
182+
if ($isUpdate) {
183+
Install-Dep -Name "GitHub CLI" -WingetId "GitHub.cli" -ChocoId "gh" -ManualUrl "https://cli.github.com" -ForceUpgrade
184+
} else {
185+
Write-Ok "$ghVer (already installed)"
186+
}
134187
} else {
135188
Install-Dep -Name "GitHub CLI" -WingetId "GitHub.cli" -ChocoId "gh" -ManualUrl "https://cli.github.com"
136189
}
@@ -152,7 +205,17 @@ if (Test-Command "npm") {
152205

153206
foreach ($tool in $npmPkgs) {
154207
if (Test-Command $tool.Cmd) {
155-
Write-Skip "$($tool.Name) (already installed)"
208+
if ($isUpdate) {
209+
Write-Step "Updating $($tool.Name)..."
210+
npm update -g $tool.Pkg 2>$null
211+
if ($LASTEXITCODE -eq 0) {
212+
Write-Ok "$($tool.Name) updated"
213+
} else {
214+
Write-Warn "$($tool.Name) update failed (run: npm update -g $($tool.Pkg))"
215+
}
216+
} else {
217+
Write-Skip "$($tool.Name) (already installed)"
218+
}
156219
} else {
157220
Write-Step "Installing $($tool.Name)..."
158221
npm install -g $tool.Pkg 2>$null
@@ -169,7 +232,7 @@ if (Test-Command "npm") {
169232
}
170233

171234
# ---------------------------------------------------------------------------
172-
# 3. Download & install T3 Code MSI
235+
# 3. Download & install/update T3 Code MSI
173236
# ---------------------------------------------------------------------------
174237

175238
Write-Host ""
@@ -179,7 +242,7 @@ Write-Host " -------------------------" -ForegroundColor DarkGray
179242
Write-Step "Fetching latest release from GitHub..."
180243

181244
try {
182-
$headers = @{ "User-Agent" = "T3CodeInstaller/1.0" }
245+
$headers = @{ "User-Agent" = "T3CodeInstaller/2.0" }
183246
$release = $null
184247
$msiAsset = $null
185248

@@ -202,63 +265,70 @@ try {
202265
if (-not $msiAsset) {
203266
Write-Err "No MSI found in releases at github.com/$repo"
204267
Write-Warn "Visit https://github.com/$repo/releases to download manually."
205-
exit 1
206-
}
207-
208-
$msiUrl = $msiAsset.browser_download_url
209-
$msiName = $msiAsset.name
210-
$sizeMB = [math]::Round($msiAsset.size / 1MB, 1)
211-
$tempDir = Join-Path $env:TEMP "t3code-install"
212-
$msiPath = Join-Path $tempDir $msiName
268+
# Don't exit — deps were still installed successfully
269+
} else {
270+
$latestVersion = $release.tag_name -replace '^v', ''
271+
$msiUrl = $msiAsset.browser_download_url
272+
$msiName = $msiAsset.name
273+
$sizeMB = [math]::Round($msiAsset.size / 1MB, 1)
274+
275+
# Compare versions — skip download if already on latest
276+
if ($installedVersion -and $installedVersion -eq $latestVersion) {
277+
Write-Ok "T3 Code v$installedVersion is already the latest version"
278+
} else {
279+
$tempDir = Join-Path $env:TEMP "t3code-install"
280+
$msiPath = Join-Path $tempDir $msiName
213281

214-
if (-not (Test-Path $tempDir)) { New-Item -ItemType Directory -Path $tempDir -Force | Out-Null }
282+
if (-not (Test-Path $tempDir)) { New-Item -ItemType Directory -Path $tempDir -Force | Out-Null }
215283

216-
Write-Step "Downloading $msiName ($sizeMB MB)..."
217-
Invoke-WebRequest -Uri $msiUrl -OutFile $msiPath -UseBasicParsing
284+
if ($isUpdate) {
285+
Write-Step "Downloading update: v$installedVersion -> v$latestVersion ($sizeMB MB)..."
286+
} else {
287+
Write-Step "Downloading $msiName ($sizeMB MB)..."
288+
}
289+
Invoke-WebRequest -Uri $msiUrl -OutFile $msiPath -UseBasicParsing
290+
291+
Write-Step "Installing T3 Code (admin prompt may appear)..."
292+
# MSI /i handles both install and upgrade automatically
293+
$proc = Start-Process msiexec.exe -ArgumentList "/i `"$msiPath`" /qb /norestart" -Wait -Verb RunAs -PassThru
294+
if ($proc.ExitCode -eq 0) {
295+
if ($isUpdate) {
296+
Write-Ok "T3 Code updated to v$latestVersion!"
297+
} else {
298+
Write-Ok "T3 Code v$latestVersion installed!"
299+
}
300+
} else {
301+
Write-Err "MSI install returned exit code $($proc.ExitCode)"
302+
}
218303

219-
Write-Step "Installing T3 Code (admin prompt may appear)..."
220-
$proc = Start-Process msiexec.exe -ArgumentList "/i `"$msiPath`" /qb /norestart" -Wait -Verb RunAs -PassThru
221-
if ($proc.ExitCode -eq 0) {
222-
Write-Ok "T3 Code $($release.tag_name) installed!"
223-
} else {
224-
Write-Err "MSI install returned exit code $($proc.ExitCode)"
304+
# Cleanup
305+
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
306+
}
225307
}
226-
227-
# Cleanup
228-
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
229-
230308
} catch {
231309
Write-Err "Download/install failed: $_"
232310
Write-Warn "Visit https://github.com/$repo/releases to download manually."
233-
exit 1
234311
}
235312

236313
# ---------------------------------------------------------------------------
237-
# 4. Update channel setup
314+
# 4. Update channel info
238315
# ---------------------------------------------------------------------------
239316

240317
Write-Host ""
241318
Write-Host " [4/4] Update Channels" -ForegroundColor White
242319
Write-Host " ---------------------" -ForegroundColor DarkGray
243320

244-
# T3 Code has built-in auto-update via electron-updater (checks GitHub Releases).
245-
# Additionally, register with system package managers for CLI updates.
321+
Write-Ok "Auto-update: T3 Code checks GitHub Releases on every launch"
322+
Write-Ok "Manual update: re-run this same command anytime"
246323

247324
if ($hasWinget) {
248-
Write-Ok "winget: T3 Code will appear in 'winget upgrade' once published to winget-pkgs"
249-
Write-Skip " Future: winget upgrade --id T3Tools.T3Code"
325+
Write-Skip " winget upgrade --all (updates core deps)"
250326
}
251-
252327
if ($hasChoco) {
253-
Write-Ok "Chocolatey: T3 Code will appear in 'choco upgrade' once published"
254-
Write-Skip " Future: choco upgrade t3code -y"
328+
Write-Skip " choco upgrade all -y (updates core deps)"
255329
}
256-
257-
Write-Ok "Auto-update: T3 Code checks GitHub Releases on every launch"
258-
259-
# npm tools can be updated with:
260330
if (Test-Command "npm") {
261-
Write-Skip "Update CLI tools anytime: npm update -g @openai/codex @anthropic-ai/claude-code @google/gemini-cli"
331+
Write-Skip " npm update -g @openai/codex @anthropic-ai/claude-code @google/gemini-cli"
262332
}
263333

264334
# ---------------------------------------------------------------------------
@@ -267,22 +337,26 @@ if (Test-Command "npm") {
267337

268338
Write-Host ""
269339
Write-Host " ========================================" -ForegroundColor Green
270-
Write-Host " Installation Complete! " -ForegroundColor Green
340+
if ($isUpdate) {
341+
Write-Host " Update Complete! " -ForegroundColor Green
342+
} else {
343+
Write-Host " Installation Complete! " -ForegroundColor Green
344+
}
271345
Write-Host " ========================================" -ForegroundColor Green
272346
Write-Host ""
273-
Write-Host " Launch T3 Code from the Start Menu or Desktop shortcut." -ForegroundColor White
274-
Write-Host ""
275-
Write-Host " Quick start:" -ForegroundColor DarkGray
276-
Write-Host " 1. Sign in with your AI providers (ChatGPT, Claude, Gemini)" -ForegroundColor DarkGray
277-
Write-Host " 2. Connect your GitHub account" -ForegroundColor DarkGray
278-
Write-Host " 3. Start coding!" -ForegroundColor DarkGray
279-
Write-Host ""
280-
Write-Host " Update everything:" -ForegroundColor DarkGray
281-
if ($hasWinget) {
282-
Write-Host " winget upgrade --all" -ForegroundColor DarkGray
283-
}
284-
if ($hasChoco) {
285-
Write-Host " choco upgrade all -y" -ForegroundColor DarkGray
347+
348+
if (-not $isUpdate) {
349+
Write-Host " Launch T3 Code from the Start Menu or Desktop shortcut." -ForegroundColor White
350+
Write-Host ""
351+
Write-Host " Quick start:" -ForegroundColor DarkGray
352+
Write-Host " 1. Sign in with your AI providers (ChatGPT, Claude, Gemini)" -ForegroundColor DarkGray
353+
Write-Host " 2. Connect your GitHub account" -ForegroundColor DarkGray
354+
Write-Host " 3. Start coding!" -ForegroundColor DarkGray
355+
} else {
356+
Write-Host " Restart T3 Code to use the latest version." -ForegroundColor White
286357
}
287-
Write-Host " npm update -g @openai/codex @anthropic-ai/claude-code @google/gemini-cli" -ForegroundColor DarkGray
358+
359+
Write-Host ""
360+
Write-Host " Run this command anytime to update:" -ForegroundColor DarkGray
361+
Write-Host " iex (irm https://raw.githubusercontent.com/$repo/main/install.ps1)" -ForegroundColor DarkGray
288362
Write-Host ""

0 commit comments

Comments
 (0)