Skip to content

Commit 806e553

Browse files
backnotpropclaude
andcommitted
feat: unified install script for all platforms
- Add Windows PowerShell install script (install.ps1) - Install slash commands for both Claude Code and OpenCode - Update OpenCode README with install script instructions - Simplify UpdateBanner to use same install command for both platforms Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 1ee40ef commit 806e553

7 files changed

Lines changed: 139 additions & 143 deletions

File tree

apps/opencode-plugin/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ Add to your `opencode.json`:
3030

3131
Restart OpenCode. The `submit_plan` tool is now available.
3232

33-
> **Existing users:** If you're stuck on an old version, clear both caches and restart:
33+
> **Slash commands:** Run the install script to get `/plannotator-review`:
3434
> ```bash
35-
> rm -rf ~/.cache/opencode/node_modules/@plannotator ~/.bun/install/cache/@plannotator
35+
> curl -fsSL https://plannotator.ai/install.sh | bash
3636
> ```
37+
> This also clears any cached plugin versions.
3738
3839
## How It Works
3940

apps/opencode-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@plannotator/opencode",
3-
"version": "0.5.3",
3+
"version": "0.5.4",
44
"description": "Plannotator plugin for OpenCode - interactive plan review with visual annotation",
55
"author": "backnotprop",
66
"license": "BSL-1.1",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "plannotator",
3-
"version": "0.5.3",
3+
"version": "0.5.4",
44
"private": true,
55
"description": "Interactive Plan Review for Claude Code - annotate plans visually, share with team, automatically send feedback",
66
"author": "backnotprop",

packages/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@plannotator/server",
3-
"version": "0.5.3",
3+
"version": "0.5.4",
44
"private": true,
55
"description": "Shared server implementation for Plannotator plugins",
66
"main": "index.ts",

packages/ui/components/UpdateBanner.tsx

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React, { useState } from 'react';
22
import { useUpdateCheck } from '../hooks/useUpdateCheck';
33

44
const INSTALL_COMMAND = 'curl -fsSL https://plannotator.ai/install.sh | bash';
5-
const OPENCODE_CACHE_COMMAND = 'rm -rf ~/.cache/opencode/node_modules/@plannotator ~/.bun/install/cache/@plannotator';
65

76
interface UpdateBannerProps {
87
origin?: 'claude-code' | 'opencode' | null;
@@ -11,7 +10,6 @@ interface UpdateBannerProps {
1110
export const UpdateBanner: React.FC<UpdateBannerProps> = ({ origin }) => {
1211
const updateInfo = useUpdateCheck();
1312
const [copied, setCopied] = useState(false);
14-
const [copiedCache, setCopiedCache] = useState(false);
1513
const [dismissed, setDismissed] = useState(false);
1614

1715
// Debug: ?preview-origin=opencode to test OpenCode-specific UI
@@ -24,24 +22,14 @@ export const UpdateBanner: React.FC<UpdateBannerProps> = ({ origin }) => {
2422

2523
const handleCopy = async () => {
2624
try {
27-
await navigator.clipboard.writeText(isOpenCode ? OPENCODE_CACHE_COMMAND : INSTALL_COMMAND);
25+
await navigator.clipboard.writeText(INSTALL_COMMAND);
2826
setCopied(true);
2927
setTimeout(() => setCopied(false), 2000);
3028
} catch (e) {
3129
console.error('Failed to copy:', e);
3230
}
3331
};
3432

35-
const handleCopyCache = async () => {
36-
try {
37-
await navigator.clipboard.writeText(OPENCODE_CACHE_COMMAND);
38-
setCopiedCache(true);
39-
setTimeout(() => setCopiedCache(false), 2000);
40-
} catch (e) {
41-
console.error('Failed to copy:', e);
42-
}
43-
};
44-
4533
const hasFeature = !!updateInfo.featureHighlight;
4634

4735
// Expanded banner for milestone releases with feature highlights
@@ -88,40 +76,25 @@ export const UpdateBanner: React.FC<UpdateBannerProps> = ({ origin }) => {
8876
You have {updateInfo.currentVersion}
8977
</p>
9078

91-
{/* OpenCode cache instructions */}
79+
{/* OpenCode extra instructions */}
9280
{isOpenCode && (
93-
<div className="mt-3 p-3 bg-muted/50 rounded-lg">
94-
<p className="text-xs text-muted-foreground mb-2">
95-
Clear cache to update:
96-
</p>
97-
<div className="flex items-center gap-2">
98-
<code className="flex-1 text-[10px] font-mono text-foreground/70 bg-background/50 px-2 py-1 rounded truncate">
99-
{OPENCODE_CACHE_COMMAND}
100-
</code>
101-
<button
102-
onClick={handleCopyCache}
103-
className="px-2 py-1 text-xs font-medium text-muted-foreground hover:text-foreground border border-border rounded hover:bg-muted transition-colors"
104-
>
105-
{copiedCache ? 'Copied!' : 'Copy'}
106-
</button>
107-
</div>
108-
</div>
81+
<p className="text-xs text-muted-foreground mt-3">
82+
Run the install script, then restart OpenCode.
83+
</p>
10984
)}
11085

11186
<div className="mt-4 flex items-center gap-2">
112-
{!isOpenCode && (
113-
<button
114-
onClick={handleCopy}
115-
className="flex-1 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity"
116-
>
117-
{copied ? 'Copied!' : 'Copy install command'}
118-
</button>
119-
)}
87+
<button
88+
onClick={handleCopy}
89+
className="flex-1 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity"
90+
>
91+
{copied ? 'Copied!' : 'Copy install command'}
92+
</button>
12093
<a
12194
href={updateInfo.releaseUrl}
12295
target="_blank"
12396
rel="noopener noreferrer"
124-
className={`px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground border border-border rounded-lg hover:bg-muted transition-colors ${isOpenCode ? 'flex-1 text-center' : ''}`}
97+
className="px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground border border-border rounded-lg hover:bg-muted transition-colors"
12598
>
12699
Release notes
127100
</a>

scripts/install.ps1

Lines changed: 87 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,126 @@
1-
param(
2-
[Parameter(Position=0)]
3-
[string]$Version = "latest"
4-
)
5-
6-
Set-StrictMode -Version Latest
1+
# Plannotator Windows Installer
72
$ErrorActionPreference = "Stop"
8-
$ProgressPreference = 'SilentlyContinue'
93

10-
$REPO = "backnotprop/plannotator"
11-
$INSTALL_DIR = "$env:USERPROFILE\.local\bin"
4+
$repo = "backnotprop/plannotator"
5+
$installDir = "$env:LOCALAPPDATA\plannotator"
126

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"
1612
exit 1
1713
}
1814

19-
# Determine platform
20-
$platform = "win32-x64"
15+
$platform = "windows-$arch"
16+
$binaryName = "plannotator-$platform.exe"
2117

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
2421

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
4225
}
4326

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
4535

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"
4839
$checksumUrl = "$binaryUrl.sha256"
4940

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
6243

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
7246

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()
7450

7551
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!"
7854
exit 1
7955
}
8056

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"
8458

85-
Write-Output ""
86-
Write-Output "plannotator $tag installed to $installPath"
59+
Write-Host ""
60+
Write-Host "plannotator $latestTag installed to $installDir\plannotator.exe"
8761

88-
# Check if install directory is in PATH
62+
# Add to PATH if not already there
8963
$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."
10169
}
10270

103-
# Install /review slash command
71+
# Install Claude Code slash command
10472
$claudeCommandsDir = "$env:USERPROFILE\.claude\commands"
10573
New-Item -ItemType Directory -Force -Path $claudeCommandsDir | Out-Null
10674

107-
$reviewCommand = @"
75+
@"
10876
---
10977
description: Open interactive code review for current changes
11078
allowed-tools: Bash(plannotator:*)
11179
---
11280
11381
## Code Review Feedback
11482
115-
!``plannotator review``
83+
!`plannotator review`
11684
11785
## Your task
11886
11987
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

Comments
 (0)