-
Notifications
You must be signed in to change notification settings - Fork 403
Expand file tree
/
Copy pathinstall.ps1
More file actions
225 lines (183 loc) · 8.19 KB
/
install.ps1
File metadata and controls
225 lines (183 loc) · 8.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# Plannotator Windows Installer
$ErrorActionPreference = "Stop"
$repo = "backnotprop/plannotator"
$installDir = "$env:LOCALAPPDATA\plannotator"
# Detect architecture
$arch = if ([Environment]::Is64BitOperatingSystem) {
if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "x64" }
} else {
Write-Error "32-bit Windows is not supported"
exit 1
}
$platform = "win32-$arch"
$binaryName = "plannotator-$platform.exe"
# Clean up old install locations that may take precedence in PATH
$oldLocations = @(
"$env:USERPROFILE\.local\bin\plannotator.exe",
"$env:USERPROFILE\.local\bin\plannotator"
)
foreach ($oldPath in $oldLocations) {
if (Test-Path $oldPath) {
Write-Host "Removing old installation at $oldPath..."
Remove-Item -Force $oldPath -ErrorAction SilentlyContinue
}
}
Write-Host "Fetching latest version..."
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest"
$latestTag = $release.tag_name
if (-not $latestTag) {
Write-Error "Failed to fetch latest version"
exit 1
}
Write-Host "Installing plannotator $latestTag..."
$binaryUrl = "https://github.com/$repo/releases/download/$latestTag/$binaryName"
$checksumUrl = "$binaryUrl.sha256"
# Create install directory
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
$tmpFile = [System.IO.Path]::GetTempFileName()
# Use -UseBasicParsing to avoid security prompts and ensure consistent behavior
Invoke-WebRequest -Uri $binaryUrl -OutFile $tmpFile -UseBasicParsing
# Verify checksum
# Note: In Windows PowerShell 5.1, Invoke-WebRequest returns .Content as byte[] for non-HTML responses.
# We must handle both byte[] (PS 5.1) and string (PS 7+) for cross-version compatibility.
$checksumResponse = Invoke-WebRequest -Uri $checksumUrl -UseBasicParsing
if ($checksumResponse.Content -is [byte[]]) {
$checksumContent = [System.Text.Encoding]::UTF8.GetString($checksumResponse.Content)
} else {
$checksumContent = $checksumResponse.Content
}
$expectedChecksum = $checksumContent.Split(" ")[0].Trim().ToLower()
$actualChecksum = (Get-FileHash -Path $tmpFile -Algorithm SHA256).Hash.ToLower()
if ($actualChecksum -ne $expectedChecksum) {
Remove-Item $tmpFile -Force
Write-Error "Checksum verification failed!"
exit 1
}
Move-Item -Force $tmpFile "$installDir\plannotator.exe"
Write-Host ""
Write-Host "plannotator $latestTag installed to $installDir\plannotator.exe"
# Add to PATH if not already there
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$installDir*") {
Write-Host ""
Write-Host "$installDir is not in your PATH. Adding it..."
[Environment]::SetEnvironmentVariable("Path", "$userPath;$installDir", "User")
Write-Host "Added to PATH. Restart your terminal for changes to take effect."
}
# Validate plugin hooks.json if plugin is already installed
$pluginHooks = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json" } else { "$env:USERPROFILE\.claude\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json" }
if (Test-Path $pluginHooks) {
@'
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "plannotator",
"timeout": 345600
}
]
}
]
}
}
'@ | Set-Content -Path $pluginHooks
Write-Host "Updated plugin hooks at $pluginHooks"
}
# Clear OpenCode plugin cache
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\node_modules\@plannotator" -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force "$env:USERPROFILE\.bun\install\cache\@plannotator" -ErrorAction SilentlyContinue
# Update Pi extension if pi is installed
if (Get-Command pi -ErrorAction SilentlyContinue) {
Write-Host "Updating Pi extension..."
pi install npm:@plannotator/pi-extension
Write-Host "Pi extension updated."
}
# Install Claude Code slash command
$claudeCommandsDir = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\commands" } else { "$env:USERPROFILE\.claude\commands" }
New-Item -ItemType Directory -Force -Path $claudeCommandsDir | Out-Null
@"
---
description: Open interactive code review for current changes
allowed-tools: Bash(plannotator:*)
---
## Code Review Feedback
!`plannotator review`
## Your task
Address the code review feedback above. The user has reviewed your changes in the Plannotator UI and provided specific annotations and comments.
"@ | Set-Content -Path "$claudeCommandsDir\plannotator-review.md"
Write-Host "Installed /plannotator-review command to $claudeCommandsDir\plannotator-review.md"
# Install Claude Code /annotate slash command
@'
---
description: Open interactive annotation UI for a markdown file
allowed-tools: Bash(plannotator:*)
---
## Markdown Annotations
!`plannotator annotate $ARGUMENTS`
## Your task
Address the annotation feedback above. The user has reviewed the markdown file and provided specific annotations and comments.
'@ | Set-Content -Path "$claudeCommandsDir\plannotator-annotate.md"
Write-Host "Installed /plannotator-annotate command to $claudeCommandsDir\plannotator-annotate.md"
# Install OpenCode slash command
$opencodeCommandsDir = "$env:USERPROFILE\.config\opencode\command"
New-Item -ItemType Directory -Force -Path $opencodeCommandsDir | Out-Null
@"
---
description: Open interactive code review for current changes
---
The Plannotator Code Review has been triggered. Opening the review UI...
Acknowledge "Opening code review..." and wait for the user's feedback.
"@ | Set-Content -Path "$opencodeCommandsDir\plannotator-review.md"
Write-Host "Installed /plannotator-review command to $opencodeCommandsDir\plannotator-review.md"
# Install OpenCode /annotate slash command
@"
---
description: Open interactive annotation UI for a markdown file
---
The Plannotator Annotate has been triggered. Opening the annotation UI...
Acknowledge "Opening annotation UI..." and wait for the user's feedback.
"@ | Set-Content -Path "$opencodeCommandsDir\plannotator-annotate.md"
Write-Host "Installed /plannotator-annotate command to $opencodeCommandsDir\plannotator-annotate.md"
Write-Host ""
Write-Host "=========================================="
Write-Host " OPENCODE USERS"
Write-Host "=========================================="
Write-Host ""
Write-Host "Add the plugin to your opencode.json:"
Write-Host ""
Write-Host ' "plugin": ["@plannotator/opencode@latest"]'
Write-Host ""
Write-Host "Then restart OpenCode. The /plannotator-review and /plannotator-annotate commands are ready!"
Write-Host ""
Write-Host "=========================================="
Write-Host " CLAUDE CODE USERS: YOU ARE ALL SET!"
Write-Host "=========================================="
Write-Host ""
Write-Host "Install the Claude Code plugin:"
Write-Host " /plugin marketplace add backnotprop/plannotator"
Write-Host " /plugin install plannotator@plannotator"
Write-Host ""
Write-Host "The /plannotator-review and /plannotator-annotate commands are ready to use after you restart Claude Code!"
# Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution)
# Only warn when the plugin is installed — manual-only users won't have overlap
$claudeSettings = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\settings.json" } else { "$env:USERPROFILE\.claude\settings.json" }
if ((Test-Path $pluginHooks) -and (Test-Path $claudeSettings)) {
$settingsContent = Get-Content -Path $claudeSettings -Raw -ErrorAction SilentlyContinue
if ($settingsContent -match '"command".*plannotator') {
Write-Host ""
Write-Host "⚠️ ⚠️ ⚠️ WARNING: DUPLICATE HOOK DETECTED ⚠️ ⚠️ ⚠️"
Write-Host ""
Write-Host " plannotator was found in your settings.json hooks:"
Write-Host " $claudeSettings"
Write-Host ""
Write-Host " This will cause plannotator to run TWICE on each plan review."
Write-Host " Remove the plannotator hook from settings.json and rely on the"
Write-Host " plugin instead (installed automatically via marketplace)."
Write-Host ""
Write-Host "⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️"
}
}