Skip to content

Commit b6bec69

Browse files
backnotpropclaude
andauthored
feat: add Pi origin support to code review UI (#263)
* feat: add Pi origin support to code review UI and update banner Pi users were seeing "OpenCode" badge and getting the wrong update command. Adds 'pi' to origin types in review/annotate servers, shows violet "Pi" badge in code review header, and copies the correct `pi install` command in the update banner. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: update Pi extension from install scripts when pi is available The install scripts now check if `pi` is on PATH and run `pi install npm:@plannotator/pi-extension` to update the extension. Silent for users without Pi installed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 709e9ff commit b6bec69

File tree

7 files changed

+45
-13
lines changed

7 files changed

+45
-13
lines changed

packages/review-editor/App.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ interface DiffData {
3535
files: DiffFile[];
3636
rawPatch: string;
3737
gitRef: string;
38-
origin?: 'opencode' | 'claude-code';
38+
origin?: 'opencode' | 'claude-code' | 'pi';
3939
diffType?: string;
4040
gitContext?: GitContext;
4141
sharingEnabled?: boolean;
@@ -139,7 +139,7 @@ const ReviewApp: React.FC = () => {
139139
const [copyFeedback, setCopyFeedback] = useState<string | null>(null);
140140
const [viewedFiles, setViewedFiles] = useState<Set<string>>(new Set());
141141
const [hideViewedFiles, setHideViewedFiles] = useState(false);
142-
const [origin, setOrigin] = useState<'opencode' | 'claude-code' | null>(null);
142+
const [origin, setOrigin] = useState<'opencode' | 'claude-code' | 'pi' | null>(null);
143143
const [diffType, setDiffType] = useState<string>('uncommitted');
144144
const [gitContext, setGitContext] = useState<GitContext | null>(null);
145145
const [isLoadingDiff, setIsLoadingDiff] = useState(false);
@@ -214,7 +214,7 @@ const ReviewApp: React.FC = () => {
214214
.then((data: {
215215
rawPatch: string;
216216
gitRef: string;
217-
origin?: 'opencode' | 'claude-code';
217+
origin?: 'opencode' | 'claude-code' | 'pi';
218218
diffType?: string;
219219
gitContext?: GitContext;
220220
sharingEnabled?: boolean;
@@ -615,9 +615,11 @@ const ReviewApp: React.FC = () => {
615615
<span className={`text-[10px] px-1.5 py-0.5 rounded font-medium hidden md:inline ${
616616
origin === 'claude-code'
617617
? 'bg-orange-500/15 text-orange-400'
618-
: 'bg-zinc-500/20 text-zinc-400'
618+
: origin === 'pi'
619+
? 'bg-violet-500/15 text-violet-400'
620+
: 'bg-zinc-500/20 text-zinc-400'
619621
}`}>
620-
{origin === 'claude-code' ? 'Claude Code' : 'OpenCode'}
622+
{origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'}
621623
</span>
622624
)}
623625
{repoInfo && (
@@ -991,10 +993,10 @@ const ReviewApp: React.FC = () => {
991993
title={submitted === 'approved' ? 'Changes Approved' : 'Feedback Sent'}
992994
subtitle={
993995
submitted === 'approved'
994-
? `${origin === 'claude-code' ? 'Claude Code' : 'OpenCode'} will proceed with the changes.`
995-
: `${origin === 'claude-code' ? 'Claude Code' : 'OpenCode'} will address your review feedback.`
996+
? `${origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'} will proceed with the changes.`
997+
: `${origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'} will address your review feedback.`
996998
}
997-
agentLabel={origin === 'claude-code' ? 'Claude Code' : 'OpenCode'}
999+
agentLabel={origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'}
9981000
/>
9991001

10001002
{/* Update notification */}

packages/server/annotate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export interface AnnotateServerOptions {
3131
/** HTML content to serve for the UI */
3232
htmlContent: string;
3333
/** Origin identifier for UI customization */
34-
origin?: "opencode" | "claude-code";
34+
origin?: "opencode" | "claude-code" | "pi";
3535
/** Whether URL sharing is enabled (default: true) */
3636
sharingEnabled?: boolean;
3737
/** Custom base URL for share links */

packages/server/review.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface ReviewServerOptions {
3434
/** HTML content to serve for the UI */
3535
htmlContent: string;
3636
/** Origin identifier for UI customization */
37-
origin?: "opencode" | "claude-code";
37+
origin?: "opencode" | "claude-code" | "pi";
3838
/** Current diff type being displayed */
3939
diffType?: DiffType;
4040
/** Git context with branch info and available diff options */

packages/ui/components/UpdateBanner.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React, { useState } from 'react';
22
import { useUpdateCheck } from '../hooks/useUpdateCheck';
33

4-
const INSTALL_COMMAND = 'curl -fsSL https://plannotator.ai/install.sh | bash';
4+
const DEFAULT_INSTALL_COMMAND = 'curl -fsSL https://plannotator.ai/install.sh | bash';
5+
const PI_INSTALL_COMMAND = 'pi install npm:@plannotator/pi-extension';
56

67
interface UpdateBannerProps {
78
origin?: 'claude-code' | 'opencode' | 'pi' | null;
@@ -16,13 +17,15 @@ export const UpdateBanner: React.FC<UpdateBannerProps> = ({ origin }) => {
1617
const urlParams = new URLSearchParams(window.location.search);
1718
const previewOrigin = urlParams.get('preview-origin');
1819
const effectiveOrigin = previewOrigin || origin;
20+
const isPi = effectiveOrigin === 'pi';
1921
const isOpenCode = effectiveOrigin === 'opencode';
22+
const installCommand = isPi ? PI_INSTALL_COMMAND : DEFAULT_INSTALL_COMMAND;
2023

2124
if (!updateInfo?.updateAvailable || dismissed) return null;
2225

2326
const handleCopy = async () => {
2427
try {
25-
await navigator.clipboard.writeText(INSTALL_COMMAND);
28+
await navigator.clipboard.writeText(installCommand);
2629
setCopied(true);
2730
setTimeout(() => setCopied(false), 2000);
2831
} catch (e) {
@@ -76,12 +79,17 @@ export const UpdateBanner: React.FC<UpdateBannerProps> = ({ origin }) => {
7679
You have {updateInfo.currentVersion}
7780
</p>
7881

79-
{/* OpenCode extra instructions */}
82+
{/* Agent-specific extra instructions */}
8083
{isOpenCode && (
8184
<p className="text-xs text-muted-foreground mt-3">
8285
Run the install script, then restart OpenCode.
8386
</p>
8487
)}
88+
{isPi && (
89+
<p className="text-xs text-muted-foreground mt-3">
90+
Run the install command, then restart Pi.
91+
</p>
92+
)}
8593

8694
<div className="mt-4 flex items-center gap-2">
8795
<button

scripts/install.cmd

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@ echo }
155155
echo Updated plugin hooks at !PLUGIN_HOOKS!
156156
)
157157

158+
REM Update Pi extension if pi is installed
159+
where pi >nul 2>&1
160+
if !ERRORLEVEL! equ 0 (
161+
echo Updating Pi extension...
162+
pi install npm:@plannotator/pi-extension
163+
echo Pi extension updated.
164+
)
165+
158166
REM Install /review slash command
159167
if defined CLAUDE_CONFIG_DIR (
160168
set "CLAUDE_COMMANDS_DIR=%CLAUDE_CONFIG_DIR%\commands"

scripts/install.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ if (Test-Path $pluginHooks) {
110110
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\node_modules\@plannotator" -ErrorAction SilentlyContinue
111111
Remove-Item -Recurse -Force "$env:USERPROFILE\.bun\install\cache\@plannotator" -ErrorAction SilentlyContinue
112112

113+
# Update Pi extension if pi is installed
114+
if (Get-Command pi -ErrorAction SilentlyContinue) {
115+
Write-Host "Updating Pi extension..."
116+
pi install npm:@plannotator/pi-extension
117+
Write-Host "Pi extension updated."
118+
}
119+
113120
# Install Claude Code slash command
114121
$claudeCommandsDir = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\commands" } else { "$env:USERPROFILE\.claude\commands" }
115122
New-Item -ItemType Directory -Force -Path $claudeCommandsDir | Out-Null

scripts/install.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ fi
110110
# Clear any cached OpenCode plugin to force fresh download on next run
111111
rm -rf "$HOME/.cache/opencode/node_modules/@plannotator" "$HOME/.bun/install/cache/@plannotator" 2>/dev/null || true
112112

113+
# Update Pi extension if pi is installed
114+
if command -v pi &>/dev/null; then
115+
echo "Updating Pi extension..."
116+
pi install npm:@plannotator/pi-extension
117+
echo "Pi extension updated."
118+
fi
119+
113120
# Install /review slash command
114121
CLAUDE_COMMANDS_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/commands"
115122
mkdir -p "$CLAUDE_COMMANDS_DIR"

0 commit comments

Comments
 (0)