|
1 | | -param( |
2 | | - [Parameter(Position=0)] |
3 | | - [string]$Version = "latest" |
4 | | -) |
5 | | - |
6 | | -Set-StrictMode -Version Latest |
| 1 | +# Plannotator Windows Installer |
7 | 2 | $ErrorActionPreference = "Stop" |
8 | | -$ProgressPreference = 'SilentlyContinue' |
9 | 3 |
|
10 | | -$REPO = "backnotprop/plannotator" |
11 | | -$INSTALL_DIR = "$env:USERPROFILE\.local\bin" |
| 4 | +$repo = "backnotprop/plannotator" |
| 5 | +$installDir = "$env:LOCALAPPDATA\plannotator" |
12 | 6 |
|
13 | | -# Check for 32-bit Windows |
14 | | -if (-not [Environment]::Is64BitProcess) { |
15 | | - Write-Error "Plannotator does not support 32-bit Windows." |
| 7 | +# Detect architecture |
| 8 | +$arch = if ([Environment]::Is64BitOperatingSystem) { |
| 9 | + if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "x64" } |
| 10 | +} else { |
| 11 | + Write-Error "32-bit Windows is not supported" |
16 | 12 | exit 1 |
17 | 13 | } |
18 | 14 |
|
19 | | -# Determine platform |
20 | | -$platform = "win32-x64" |
| 15 | +$platform = "windows-$arch" |
| 16 | +$binaryName = "plannotator-$platform.exe" |
21 | 17 |
|
22 | | -# Create install directory |
23 | | -New-Item -ItemType Directory -Force -Path $INSTALL_DIR | Out-Null |
| 18 | +Write-Host "Fetching latest version..." |
| 19 | +$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest" |
| 20 | +$latestTag = $release.tag_name |
24 | 21 |
|
25 | | -# Get version to install |
26 | | -if ($Version -eq "latest") { |
27 | | - Write-Output "Fetching latest version..." |
28 | | - try { |
29 | | - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/$REPO/releases/latest" -ErrorAction Stop |
30 | | - $tag = $release.tag_name |
31 | | - } |
32 | | - catch { |
33 | | - Write-Error "Failed to get latest version: $_" |
34 | | - exit 1 |
35 | | - } |
36 | | -} |
37 | | -else { |
38 | | - $tag = $Version |
39 | | - if (-not $tag.StartsWith("v")) { |
40 | | - $tag = "v$tag" |
41 | | - } |
| 22 | +if (-not $latestTag) { |
| 23 | + Write-Error "Failed to fetch latest version" |
| 24 | + exit 1 |
42 | 25 | } |
43 | 26 |
|
44 | | -Write-Output "Installing plannotator $tag..." |
| 27 | +# Telemetry (non-blocking, silent) |
| 28 | +Start-Job -ScriptBlock { |
| 29 | + param($os, $arch, $version) |
| 30 | + try { |
| 31 | + $body = @{ os = $os; arch = $arch; v = $version; org = "" } | ConvertTo-Json |
| 32 | + Invoke-RestMethod -Uri "https://kivwr3ccsxtclqaaxqat5bzcpy0qrqvp.lambda-url.us-east-1.on.aws/" -Method Post -Body $body -ContentType "application/json" | Out-Null |
| 33 | + } catch {} |
| 34 | +} -ArgumentList "windows", $arch, $latestTag | Out-Null |
45 | 35 |
|
46 | | -$binaryName = "plannotator-$platform.exe" |
47 | | -$binaryUrl = "https://github.com/$REPO/releases/download/$tag/$binaryName" |
| 36 | +Write-Host "Installing plannotator $latestTag..." |
| 37 | + |
| 38 | +$binaryUrl = "https://github.com/$repo/releases/download/$latestTag/$binaryName" |
48 | 39 | $checksumUrl = "$binaryUrl.sha256" |
49 | 40 |
|
50 | | -# Download binary |
51 | | -$tempFile = Join-Path $env:TEMP "plannotator-$tag.exe" |
52 | | -try { |
53 | | - Invoke-WebRequest -Uri $binaryUrl -OutFile $tempFile -ErrorAction Stop |
54 | | -} |
55 | | -catch { |
56 | | - Write-Error "Failed to download binary: $_" |
57 | | - if (Test-Path $tempFile) { |
58 | | - Remove-Item -Force $tempFile |
59 | | - } |
60 | | - exit 1 |
61 | | -} |
| 41 | +# Create install directory |
| 42 | +New-Item -ItemType Directory -Force -Path $installDir | Out-Null |
62 | 43 |
|
63 | | -# Download and verify checksum |
64 | | -try { |
65 | | - $expectedChecksum = (Invoke-RestMethod -Uri $checksumUrl -ErrorAction Stop).Split(" ")[0].Trim() |
66 | | -} |
67 | | -catch { |
68 | | - Write-Error "Failed to download checksum: $_" |
69 | | - Remove-Item -Force $tempFile |
70 | | - exit 1 |
71 | | -} |
| 44 | +$tmpFile = [System.IO.Path]::GetTempFileName() |
| 45 | +Invoke-WebRequest -Uri $binaryUrl -OutFile $tmpFile |
72 | 46 |
|
73 | | -$actualChecksum = (Get-FileHash -Path $tempFile -Algorithm SHA256).Hash.ToLower() |
| 47 | +# Verify checksum |
| 48 | +$expectedChecksum = (Invoke-WebRequest -Uri $checksumUrl).Content.Split(" ")[0].Trim() |
| 49 | +$actualChecksum = (Get-FileHash -Path $tmpFile -Algorithm SHA256).Hash.ToLower() |
74 | 50 |
|
75 | 51 | if ($actualChecksum -ne $expectedChecksum) { |
76 | | - Write-Error "Checksum verification failed" |
77 | | - Remove-Item -Force $tempFile |
| 52 | + Remove-Item $tmpFile -Force |
| 53 | + Write-Error "Checksum verification failed!" |
78 | 54 | exit 1 |
79 | 55 | } |
80 | 56 |
|
81 | | -# Install binary |
82 | | -$installPath = Join-Path $INSTALL_DIR "plannotator.exe" |
83 | | -Move-Item -Force $tempFile $installPath |
| 57 | +Move-Item -Force $tmpFile "$installDir\plannotator.exe" |
84 | 58 |
|
85 | | -Write-Output "" |
86 | | -Write-Output "plannotator $tag installed to $installPath" |
| 59 | +Write-Host "" |
| 60 | +Write-Host "plannotator $latestTag installed to $installDir\plannotator.exe" |
87 | 61 |
|
88 | | -# Check if install directory is in PATH |
| 62 | +# Add to PATH if not already there |
89 | 63 | $userPath = [Environment]::GetEnvironmentVariable("Path", "User") |
90 | | -if ($userPath -notlike "*$INSTALL_DIR*") { |
91 | | - Write-Output "" |
92 | | - Write-Output "$INSTALL_DIR is not in your PATH." |
93 | | - Write-Output "" |
94 | | - Write-Output "Add it permanently with:" |
95 | | - Write-Output "" |
96 | | - Write-Output " [Environment]::SetEnvironmentVariable('Path', `$env:Path + ';$INSTALL_DIR', 'User')" |
97 | | - Write-Output "" |
98 | | - Write-Output "Or add it for this session only:" |
99 | | - Write-Output "" |
100 | | - Write-Output " `$env:Path += ';$INSTALL_DIR'" |
| 64 | +if ($userPath -notlike "*$installDir*") { |
| 65 | + Write-Host "" |
| 66 | + Write-Host "$installDir is not in your PATH. Adding it..." |
| 67 | + [Environment]::SetEnvironmentVariable("Path", "$userPath;$installDir", "User") |
| 68 | + Write-Host "Added to PATH. Restart your terminal for changes to take effect." |
101 | 69 | } |
102 | 70 |
|
103 | | -# Install /review slash command |
| 71 | +# Install Claude Code slash command |
104 | 72 | $claudeCommandsDir = "$env:USERPROFILE\.claude\commands" |
105 | 73 | New-Item -ItemType Directory -Force -Path $claudeCommandsDir | Out-Null |
106 | 74 |
|
107 | | -$reviewCommand = @" |
| 75 | +@" |
108 | 76 | --- |
109 | 77 | description: Open interactive code review for current changes |
110 | 78 | allowed-tools: Bash(plannotator:*) |
111 | 79 | --- |
112 | 80 |
|
113 | 81 | ## Code Review Feedback |
114 | 82 |
|
115 | | -!``plannotator review`` |
| 83 | +!`plannotator review` |
116 | 84 |
|
117 | 85 | ## Your task |
118 | 86 |
|
119 | 87 | Address the code review feedback above. The user has reviewed your changes in the Plannotator UI and provided specific annotations and comments. |
120 | | -"@ |
121 | | - |
122 | | -Set-Content -Path "$claudeCommandsDir\plannotator-review.md" -Value $reviewCommand -Encoding UTF8 |
123 | | -Write-Output "Installed /plannotator-review command to $claudeCommandsDir\plannotator-review.md" |
124 | | - |
125 | | -Write-Output "" |
126 | | -Write-Output "Test the install:" |
127 | | -Write-Output ' echo ''{"tool_input":{"plan":"# Test Plan\\n\\nHello world"}}'' | plannotator' |
128 | | -Write-Output "" |
129 | | -Write-Output "Then install the Claude Code plugin:" |
130 | | -Write-Output " /plugin marketplace add backnotprop/plannotator" |
131 | | -Write-Output " /plugin install plannotator@plannotator" |
132 | | -Write-Output "" |
133 | | -Write-Output "The /plannotator-review command is ready to use!" |
134 | | -Write-Output "" |
| 88 | +"@ | Set-Content -Path "$claudeCommandsDir\plannotator-review.md" |
| 89 | + |
| 90 | +Write-Host "Installed /plannotator-review command to $claudeCommandsDir\plannotator-review.md" |
| 91 | + |
| 92 | +# Install OpenCode slash command |
| 93 | +$opencodeCommandsDir = "$env:USERPROFILE\.config\opencode\command" |
| 94 | +New-Item -ItemType Directory -Force -Path $opencodeCommandsDir | Out-Null |
| 95 | + |
| 96 | +@" |
| 97 | +--- |
| 98 | +description: Open interactive code review for current changes |
| 99 | +--- |
| 100 | +
|
| 101 | +The Plannotator Code Review has been triggered. Opening the review UI... |
| 102 | +Acknowledge "Opening code review..." and wait for the user's feedback. |
| 103 | +"@ | Set-Content -Path "$opencodeCommandsDir\plannotator-review.md" |
| 104 | + |
| 105 | +Write-Host "Installed /plannotator-review command to $opencodeCommandsDir\plannotator-review.md" |
| 106 | + |
| 107 | +Write-Host "" |
| 108 | +Write-Host "==========================================" |
| 109 | +Write-Host " OPENCODE USERS" |
| 110 | +Write-Host "==========================================" |
| 111 | +Write-Host "" |
| 112 | +Write-Host "Add the plugin to your opencode.json:" |
| 113 | +Write-Host "" |
| 114 | +Write-Host ' "plugin": ["@plannotator/opencode@latest"]' |
| 115 | +Write-Host "" |
| 116 | +Write-Host "Then restart OpenCode. The /plannotator-review command is ready!" |
| 117 | +Write-Host "" |
| 118 | +Write-Host "==========================================" |
| 119 | +Write-Host " CLAUDE CODE USERS: YOU ARE ALL SET!" |
| 120 | +Write-Host "==========================================" |
| 121 | +Write-Host "" |
| 122 | +Write-Host "Install the Claude Code plugin:" |
| 123 | +Write-Host " /plugin marketplace add backnotprop/plannotator" |
| 124 | +Write-Host " /plugin install plannotator@plannotator" |
| 125 | +Write-Host "" |
| 126 | +Write-Host "The /plannotator-review command is ready to use after you restart Claude Code!" |
0 commit comments