diff --git a/CLAUDE.md b/CLAUDE.md index 7426221b..14cb5d8f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,13 +18,14 @@ plannotator/ ├── packages/ │ ├── server/ # Shared server implementation │ │ ├── index.ts # startPlannotatorServer(), handleServerReady() +│ │ ├── storage.ts # Plan saving to disk (getPlanDir, savePlan, etc.) │ │ ├── remote.ts # isRemoteSession(), getServerPort() │ │ ├── browser.ts # openBrowser() │ │ ├── integrations.ts # Obsidian, Bear integrations │ │ └── project.ts # Project name detection for tags │ ├── ui/ # Shared React components │ │ ├── components/ # Viewer, Toolbar, Settings, etc. -│ │ ├── utils/ # parser.ts, sharing.ts, storage.ts +│ │ ├── utils/ # parser.ts, sharing.ts, storage.ts, planSave.ts, agentSwitch.ts │ │ ├── hooks/ # useSharing.ts │ │ └── types.ts │ └── editor/ # Main App.tsx @@ -80,15 +81,18 @@ Deny → stdout: {"hookSpecificOutput":{"decision":{"behavior":"deny","messag ## Server API -| Endpoint | Method | Purpose | -| -------------- | ------ | --------------------------------- | -| `/api/plan` | GET | Returns plan markdown as JSON | -| `/api/approve` | POST | User approved the plan | -| `/api/deny` | POST | User denied with feedback in body | +| Endpoint | Method | Purpose | +| --------------------- | ------ | ------------------------------------------ | +| `/api/plan` | GET | Returns `{ plan, origin }` | +| `/api/approve` | POST | Approve plan (body: planSave, agentSwitch, obsidian, bear, feedback) | +| `/api/deny` | POST | Deny plan (body: feedback, planSave) | +| `/api/image` | GET | Serve image by path query param | +| `/api/upload` | POST | Upload image, returns temp path | +| `/api/obsidian/vaults`| GET | Detect available Obsidian vaults | -**Location:** `packages/server/index.ts` (shared), `apps/hook/server/index.ts` (Claude Code entry), `apps/opencode-plugin/index.ts` (OpenCode entry) +**Location:** `packages/server/index.ts` -Both plugins use the shared `startPlannotatorServer()` from `packages/server`. The server handles remote detection, port configuration, and all API routes. Port is random locally (`port: 0`) or fixed (`19432`) in remote mode. +Both plugins use `startPlannotatorServer()` from `packages/server`. Port is random locally or fixed (`19432`) in remote mode. ## Data Types @@ -188,9 +192,9 @@ type ShareableAnnotation = ## Settings Persistence -**Location:** `packages/ui/utils/storage.ts` +**Location:** `packages/ui/utils/storage.ts`, `planSave.ts`, `agentSwitch.ts` -Uses cookies instead of localStorage because each hook invocation runs on a random port, and localStorage is scoped by origin (including port). Cookies are scoped by domain only. +Uses cookies (not localStorage) because each hook invocation runs on a random port. Settings include identity, plan saving (enabled/custom path), and agent switching (OpenCode only). ## Syntax Highlighting diff --git a/apps/hook/.claude-plugin/plugin.json b/apps/hook/.claude-plugin/plugin.json index 00fc8ba6..9873d5f0 100644 --- a/apps/hook/.claude-plugin/plugin.json +++ b/apps/hook/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "plannotator", "description": "Interactive Plan Review: Mark up and refine your plans using a UI, easily share for team collaboration, automatically integrates with plan mode hooks.", - "version": "0.4.9", + "version": "0.4.10", "author": { "name": "backnotprop" }, diff --git a/apps/opencode-plugin/package.json b/apps/opencode-plugin/package.json index 3cf19e33..cfeddf23 100644 --- a/apps/opencode-plugin/package.json +++ b/apps/opencode-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@plannotator/opencode", - "version": "0.4.9", + "version": "0.4.10", "description": "Plannotator plugin for OpenCode - interactive plan review with visual annotation", "author": "backnotprop", "license": "BSL-1.1", diff --git a/package.json b/package.json index 82926bd9..653dafc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plannotator", - "version": "0.4.9", + "version": "0.4.10", "private": true, "description": "Interactive Plan Review for Claude Code - annotate plans visually, share with team, automatically send feedback", "author": "backnotprop", diff --git a/packages/server/package.json b/packages/server/package.json index a0143df1..b8ddb864 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@plannotator/server", - "version": "0.4.8", + "version": "0.4.10", "private": true, "description": "Shared server implementation for Plannotator plugins", "main": "index.ts", diff --git a/packages/ui/utils/agentSwitch.ts b/packages/ui/utils/agentSwitch.ts index d292a658..4d10c9c3 100644 --- a/packages/ui/utils/agentSwitch.ts +++ b/packages/ui/utils/agentSwitch.ts @@ -44,10 +44,3 @@ export function getAgentSwitchSettings(): AgentSwitchSettings { export function saveAgentSwitchSettings(settings: AgentSwitchSettings): void { storage.setItem(STORAGE_KEY, settings.switchTo); } - -/** - * Check if agent switching is enabled - */ -export function isAgentSwitchEnabled(): boolean { - return getAgentSwitchSettings().switchTo !== 'disabled'; -} diff --git a/packages/ui/utils/planSave.ts b/packages/ui/utils/planSave.ts index 3548e850..3786792e 100644 --- a/packages/ui/utils/planSave.ts +++ b/packages/ui/utils/planSave.ts @@ -47,10 +47,3 @@ export function savePlanSaveSettings(settings: PlanSaveSettings): void { storage.removeItem(STORAGE_KEY_PATH); } } - -/** - * Check if plan saving is enabled - */ -export function isPlanSaveEnabled(): boolean { - return getPlanSaveSettings().enabled; -}