* feat: integrate VS Code extension from community (7tg/plannotator-vscode)
Opens Plannotator plan reviews, code reviews, and annotations inside VS Code
tabs instead of an external browser. Intercepts PLANNOTATOR_BROWSER via env
var injection in integrated terminals, with cookie persistence and auto-close.
Original repository: https://github.com/7tg/plannotator-vscodeCloses#91
Co-Authored-By: Barbaros Gören <tayyipgoren@gmail.com>
* chore: adapt VS Code extension for monorepo
- Update package.json: publisher → backnotprop, repo → plannotator, add private
- Replace node -e URL encoding with curl --data-urlencode in router script
- Simplify panel-manager tests to keep only behavioral tests
- Add dev:vscode, build:vscode, package:vscode scripts to root
- Add *.vsix to .gitignore
- Update bun.lock with new workspace member
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review and duplicate panel issue
- Fix macOS browser: detect script paths in PLANNOTATOR_BROWSER and
invoke directly instead of via 'open -a' (which only accepts app
names/.app bundles)
- Update CLAUDE.md: add vscode-extension to project structure,
development, and build sections
- Fix command title: 'Simple Browser' -> 'Open URL in Editor'
- Add 1s debounce to panel opens: Claude Code fires ExitPlanMode hook
twice, spawning two plannotator processes on different ports that
both hit the IPC server simultaneously
- Add .vscode/launch.json + tasks.json for F5 debugging
---------
Co-authored-by: Barbaros Gören <tayyipgoren@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: auto-save annotation drafts to survive server crashes
Adds server-side draft persistence so annotations are not lost when the
server process dies. Drafts are saved to ~/.plannotator/drafts/ keyed by
a SHA-256 content hash, debounced at 500ms. On reload, a dialog prompts
the user to restore or dismiss. Drafts are auto-deleted on approve/deny/feedback.
Closes#212
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove duplicate imports and update CLAUDE.md for draft feature
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wrap handleRestoreDraft in useCallback and update shared-handlers comment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Obsidian vault browser sidebar tab (#207)
Add a third sidebar tab that lets users browse their Obsidian vault's
file tree, click any markdown file to open and annotate it as part of
plan feedback. Includes wikilink support for navigating between vault
files.
- New /api/reference/obsidian/files and /api/reference/obsidian/doc endpoints
- useVaultBrowser hook and VaultBrowser sidebar component
- Wikilink [[filename]] and [[filename|display]] detection in Viewer
- "Vault Browser" toggle in Settings > Obsidian
- Bare filename search for wikilink resolution within vault
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update docs and clear vault state on disable
- Add new reference endpoints to CLAUDE.md API table
- Update stale doc comments referencing "two tabs" in sidebar files
- Clear vaultPath and activeFile when vault browser is disabled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: simplify vault browser prop passing and derived state
- Move VaultNode to packages/ui/types.ts (shared type location)
- Pass useVaultBrowser return as single object prop through SidebarContainer
- Replace showVaultTab/vaultPath useState with useMemo derivations
- Extract buildVaultDocUrl helper to deduplicate URL template
- Wrap onVaultFetchTree in useCallback
- Fix toggle switch size to match existing toggles (h-6 w-11)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Deploy paste service with end-to-end encryption (zero-knowledge)
Add AES-256-GCM client-side encryption to the short URL sharing flow.
Plans are encrypted in the browser before upload — the paste service
stores only ciphertext it cannot read. The decryption key lives only
in the URL fragment (#key=...) and never leaves the browser.
- New packages/shared/crypto.ts with encrypt/decrypt via Web Crypto API
- Encrypt before POST in createShortShareUrl, decrypt on load
- Parse #key= fragment in useSharing.ts for both direct and import URLs
- Deploy Cloudflare Worker with KV namespaces to workers.dev
- Add deploy-paste CI/CD job to deploy.yml
- Fix Cache-Control from public to private, no-store
- Update ExportModal strings with encryption messaging
- Update README, docs, and blog with zero-knowledge encryption details
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address code review: fix short URL fallthrough and regex anchor
- Return false early when paste fetch fails on /p/<id> path instead of
falling through to parseShareHash() (which can never succeed since the
hash contains #key=, not plan data)
- Add end-anchor to importFromShareUrl regex to prevent false matches on
URLs with extra path segments (regression from PR #188)
- Remove demo plan NOTE from README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add short URL sharing via paste service to fix URL truncation on Slack/messaging apps
Share URLs for large plans can be 10-40KB+ because the entire plan + annotations
are compressed into the URL hash. Services like Slack, WhatsApp, and Twitter
truncate these URLs, making shared plans unviewable (related: #142).
This adds an optional paste-service backend that stores compressed payloads and
returns short ~60-char URLs (e.g. share.plannotator.ai/p/aBcDeFgH).
Changes:
- Add Cloudflare Worker paste service (apps/paste-worker/) with KV storage
and 90-day TTL for stored plans
- Add createShortShareUrl() and loadFromPasteId() to sharing utils
- Update useSharing hook to auto-generate short URLs with 1s debounce
- Update ExportModal to show short URL as primary copy target with
full hash URL as backup
- Portal automatically supports /p/<id> paths via useSharing hook
- Fully backward compatible: hash-based URLs continue to work unchanged
- Graceful degradation: falls back to hash URLs if paste service is unavailable
* Fix critical bugs found during code review of short URL feature
- Worker: return only { id } so client constructs URL with its own
shareBaseUrl (fixes self-hosted deployments)
- importFromShareUrl: handle /p/<id> short URLs in addition to hash
URLs (fixes teammate import via short links)
- Anchor /p/<id> regex with ^ to prevent false matches on nested paths
- Pass shareBaseUrl to loadFromPasteId (was always defaulting)
- replaceState preserves base path instead of hardcoding /
- Clear stale shortShareUrl immediately on debounce to prevent showing
outdated link during the 1s delay
- Add shareBaseUrl to dependency arrays for loadFromHash and
importFromShareUrl callbacks
- Remove unused url field fallback from paste API response parsing
* Fix pasteApiUrl/shareBaseUrl confusion and add remote session share URLs
Bug fix (addresses @backnotprop's code review):
- useSharing hook now accepts separate `pasteApiUrl` parameter instead of
incorrectly passing `shareBaseUrl` to `loadFromPasteId`. These are
different domains (share portal vs paste backend). When omitted, the
default `https://paste.plannotator.ai` is used correctly.
- Fixed in all three call sites: loadFromHash, importFromShareUrl, and
generateShortUrl (via createShortShareUrl options).
Remote session share URLs (implements #192):
- When running on a remote instance (SSH, devcontainer), Plannotator now
generates a share.plannotator.ai URL and prints it to stderr so the
user can open the plan review in their local browser.
- Works for all three modes: plan review, code review, and annotate.
- Uses the same deflate-raw + base64url encoding as the client.
- Fails silently if URL generation fails — port forwarding still works.
- New server utility: packages/server/share-url.ts
* Address code review findings: fix spread limit, CORS, deps array
- share-url.ts: Replace btoa(String.fromCharCode(...compressed)) with
a loop to avoid RangeError on plans >65K compressed bytes
- share-url.ts: Add cross-reference comment noting the server-side
SharePayload is an intentional subset of the canonical UI type
- paste-worker: Only return CORS headers for allowed origins; disallowed
origins get no CORS headers instead of misleading partial headers
- useSharing.ts: Remove unused shareBaseUrl from loadFromHash dependency
array (loadFromHash only uses pasteApiUrl, not shareBaseUrl)
* Restructure paste service with pluggable storage, fix consent flow and security issues
Replaces monolithic paste-worker with multi-target paste-service architecture:
- Core logic (handler, storage interface, CORS) separated from deployment targets
- Filesystem store (self-hosted), KV store (Cloudflare), S3 stub (future)
- Bun binary target + Cloudflare Worker target
- Fix auto-upload removed: short URLs only created on explicit user click
- Clear stale short URL state when content changes
- Fix require('fs') in ESM module, add path-traversal guard in FsPasteStore
- Return 400 (not 500) for malformed JSON in both targets
- Fix compress() spread limit for large plans
- Updated docs: self-hosting guide, sharing guide, env vars, API endpoints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Simplify paste service: extract shared router, remove TOCTOU patterns
- Extract duplicated HTTP routing from bun.ts and cloudflare.ts into
handleRequest() in core/handler.ts — targets are now thin wrappers
- Move ID_PATTERN regex to core (was duplicated in both targets)
- Remove existsSync guard before mkdirSync({recursive:true}) in fs.ts
- Remove file.exists() check before file.json() in fs.ts get() — the
try/catch already handles missing files
- Extract DEFAULT_SHARE_BASE constant in sharing.ts (was hardcoded twice)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Deduplicate compression, image parsing, and remote share URL logic
- Create packages/shared/ with compress/decompress (single source of truth)
— both @plannotator/server and @plannotator/ui import from here
- Export parseShareableImages from sharing.ts, remove duplicate
parseGlobalAttachments from useSharing.ts
- Extract writeRemoteShareLink() helper in share-url.ts, replace 3
near-identical blocks in apps/hook/server/index.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix modulo bias in paste ID generation and remove nonexistent doc artifacts
- Use rejection sampling in generateId() to eliminate modulo bias
(bytes >= 248 discarded, uniform distribution over 62 chars)
- Remove references to install-paste.sh and Docker image that don't
exist yet; point self-hosting docs to GitHub Releases binaries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: open linked .md files in read-only tabs with TOC navigation
When a plan references local .md files via markdown links, they now open
in a new browser tab using the full Plannotator viewer in read-only mode.
Changes:
- server: add /api/doc?path= endpoint with 4-strategy path resolution
(absolute, relative to project root, bare filename search). Returns 400
with match list on ambiguous filenames, 404 when not found, 403 on
path traversal. Only resolves files within process.cwd().
- Viewer: detect local .md links in InlineMarkdown and route them to
/?doc=<path>&readonly=true with a new-tab icon. Add isReadOnly prop
that guards the web-highlighter init (prevents phantom highlights) and
suppresses annotation toolbars.
- App: parse ?doc= URL param on load and fetch from /api/doc instead of
/api/plan. Set isReadOnly mode which shows a read-only banner, hides
approve/deny/feedback buttons, ModeSwitcher, Settings, AnnotationPanel,
and annotation panel toggle. Shows an error view (not a silent fallback)
when the document cannot be found or is ambiguous. Opens the sidebar to
the TOC tab automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: upgrade linked docs to same-view annotatable navigation with aggregated feedback
Replace the new-tab read-only approach with same-view navigation: clicking a
.md link swaps the plan content in-place, preserving all annotations via a
docCache. Users can annotate linked docs and all feedback (plan + linked docs)
is aggregated into the deny/approve payload sent to Claude.
Key changes:
- New useLinkedDoc hook for state swapping, caching, and highlight restoration
- React key on Viewer forces clean unmount/remount (fixes web-highlighter DOM crash)
- exportLinkedDocAnnotations() aggregates linked doc feedback with filepath context
- UI: 2px primary border, "Linked File" badge, "Copy file" button, TOC filepath
indicator with back-to-plan button
- Fix Tailwind v4 cascade: move * { border-color } to @layer base so utility
classes like border-primary actually override it
- Compact TOC spacing (padding, gaps, line-height) without affecting Version Browser
- Exclude node_modules/.git from /api/doc bare filename glob
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: harden /api/doc endpoint and align linked doc annotation output
Restrict /api/doc to .md/.mdx files only, fix heading hierarchy and
sorting in exportLinkedDocAnnotations, and update CLAUDE.md docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: complete linked doc annotations in getDocAnnotations and fix useMemo deps
- getDocAnnotations() now includes the active linked doc's live
annotations alongside the cache, removing the implicit requirement
to call back() before reading
- Remove unstable linkedDocHook object from annotationsOutput useMemo
dependency array (was defeating memoization every render)
- Guard Cmd+Enter shortcut against linkedDocHook.isActive to prevent
accidental approve/deny while viewing a linked doc
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: include linked doc annotations in approve feedback gate
The handleApprove gate only checked plan-level annotations, silently
dropping linked-doc-only feedback on "approve with notes" (OpenCode).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add getDocAnnotations to annotationsOutput useMemo deps
Ensures memo recomputes when navigating to/from linked docs, preventing
stale annotation output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
* Add feature plan for VS Code diff viewer button
Scoping document for a new PlanDiffViewer button that opens
the plan diff in VS Code's native diff viewer via `code --diff`.
https://claude.ai/code/session_01FYcJkGsWfuiGy53x3pwCSW
* feat: add "Open in VS Code" button to plan diff viewer
Add a button in the PlanDiffViewer toolbar that opens the current
plan diff in VS Code's native side-by-side diff viewer. The server
writes both versions to temp files and spawns `code --diff`.
- New POST /api/plan/vscode-diff endpoint in packages/server/index.ts
- VS Code button with loading/error states in PlanDiffViewer.tsx
- Wire currentPlan/basePlan/baseVersion props from App.tsx
https://claude.ai/code/session_01FYcJkGsWfuiGy53x3pwCSW
* chore: update bun.lock after install
https://claude.ai/code/session_01FYcJkGsWfuiGy53x3pwCSW
* refactor: server reads plan versions directly instead of receiving from client
The server already has the current plan in its closure and can read
any version from disk via getPlanVersion(). No need to send plan
text from the UI — just send baseVersion.
https://claude.ai/code/session_01FYcJkGsWfuiGy53x3pwCSW
* chore: remove plan.md scoping document from repo
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract editor diff logic into shared packages/server/editor.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: use official VS Code SVG icon in plan diff viewer button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use history file paths directly for VS Code diff instead of writing temp files
Both plan versions already exist on disk in ~/.plannotator/history/.
Eliminates redundant file writes, fixes UPLOAD_DIR semantic misuse,
and corrects HTTP status codes for editor errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: rename editor.ts to ide.ts to avoid confusion with plan editor UI
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add ide.ts and vscode-diff endpoint to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add plan diff UI with sidebar, badge, and dual view modes
Shows what changed between plan iterations when Claude revises after
feedback. Adds a +N/-M badge below repo info that toggles the diff view,
a shared left sidebar with TOC and Version Browser tabs, and two diff
modes: rendered (color-coded borders) and raw markdown (+/- lines).
Closes#138, closes#111
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update CLAUDE.md project structure and align first-run dialog labels
- Add plan-diff/ and sidebar/ component subdirectories to CLAUDE.md
- Add new hooks and utils to CLAUDE.md project structure
- Rename "Table of Contents" to "Auto-open Sidebar" in UIFeaturesSetup
to match Settings.tsx label
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review findings for plan diff UX
- Fix badge stats mixing block counts with line counts (modifications
now fold into additions/deletions)
- Gate hasPreviousVersion on diffBasePlan being loaded to prevent
"Show Changes" no-op and ModeSwitcher disappearing
- Make sidebar reactive to Settings toggle (useEffect on tocEnabled)
- Match PlanDiffViewer badge layout to Viewer (flex-col) so badge
doesn't jump position on toggle
- Add "Exit Diff" label to the close button in diff view
- Remove dead CSS (plan-diff-removed-marker, plan-diff-modified)
- Clean up stale header comment and unused lines prop
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: second-round review cleanup for plan diff UX
- Fix stale "amber border" JSDoc in PlanCleanDiffView (actually green)
- Rename sidebar tab from "diff" to "versions" for clarity
- Gate VersionBrowser fetch on versionInfo being available
- Move .sidebar-tab-flag CSS into its own Sidebar section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add loading state for version selection in sidebar
Add isSelectingVersion to selectBaseVersion, mirroring the existing
isLoadingVersions pattern. Shows "Loading..." on the selected version
button while the fetch is in progress.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address third-round code review findings
- Fix duplicate border/backdrop on TOC inside sidebar (className override)
- Fix loading indicator targeting wrong version button (fetchingVersion state)
- Fix "Show Changes" button silent no-op (gate on hasPreviousVersion)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: move date to slug suffix, improve Other Plans UX
- Slug format changed from YYYY-MM-DD-{heading} to {heading}-YYYY-MM-DD
- Other Plans: single "coming soon" banner instead of per-item labels
- Strip date suffix from plan names in sidebar for readability
- Remove cursor-not-allowed from Other Plans items
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Plan Diff section to CLAUDE.md, alert on version fetch failure
- Document plan diff feature: engine, view modes, state management, sidebar
- Update slug format documentation to {heading}-YYYY-MM-DD
- Show native alert when version fetch fails instead of silent swallow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add table rendering to clean diff view
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add plan version history (backend + API)
Save plan versions to ~/.plannotator/history/{project}/{slug}/ on every
plan arrival. Serves previousPlan and versionInfo via /api/plan, and adds
GET /api/plan/version?v=N for fetching any historical version. Enables
future diff UI. Deduplicates identical resubmissions.
Closes#138, closes#111
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add version listing and project history APIs
Add GET /api/plan/versions to list all versions of the current plan with
timestamps, and GET /api/plan/history to list all plans in the current
project. Both endpoints available in shared server and pi extension.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add version history section and API endpoints to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: rename misleading "diff" terminology to "annotations" in plan review context
The plan review flow used "diff" naming (exportDiff, diffOutput, .diff.md,
"Raw Diff", "Download .diff") for what is actually user annotations/feedback
on a plan. This was confusing since the code review flow legitimately uses
"diff" for actual git diffs. Renames all plan-review-context "diff" references
to "annotations" across code, UI labels, file extensions, and docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update stale exportDiff references in ANNOTATE.md
Missed during the diff→annotations rename. Updates two references
to exportDiff() → exportAnnotations() in the annotate flow docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: rename remaining "Download Diff" label and tab type in App.tsx
The quick-save dropdown button still showed "Download Diff" and the
initialExportTab state type still used 'diff' instead of 'annotations'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Migrate marketing site from Vite React SPA to Astro 5 with documentation (15 pages) and blog. Preserves landing page design, OKLCH design system, and S3/CloudFront deploy pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: named image references and annotate command (#67, #109)
Add human-readable names to image attachments throughout the annotation
pipeline, and add a new `plannotator annotate <file.md>` command for
annotating arbitrary markdown files.
Image names: ImageAttachment type replaces plain string paths, upload
endpoints return originalName, editable name inputs under thumbnails,
[name] path format in exported feedback, backward-compatible sharing.
Annotate command: new server module reusing plan editor HTML with
mode:"annotate", CLI subcommand, slash commands for Claude Code and
OpenCode, annotate mode UI (hides Approve, shows Send Annotations).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: move image name input to ImageAnnotator screen
The name input now appears on the full-screen annotator modal that opens
immediately when uploading/pasting an image, pre-populated from the
filename. Removes the disruptive inline name editing from thumbnails.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: stale closure in paste handler, update CLAUDE.md for new features
Fix race condition where globalAttachments was captured as empty array
in the paste event listener (missing dependency). Also update CLAUDE.md
to document ImageAttachment type, annotate server/flow, updated sharing
format with image support, and new slash commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add PLANNOTATOR_SHARE_URL env var so users can point share links at
their own self-hosted portal instance instead of share.plannotator.ai.
Threads the base URL through the same path as sharingEnabled: env var →
server options → API response → editor state → useSharing hook →
generateShareUrl(). Includes self-hosting guide and documentation.
Closes#12
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
Complete code review system for reviewing git diffs with annotations.
### Features
- Interactive diff viewer with split/unified views
- Line-level annotation system
- Diff type selector (uncommitted, last commit, vs main branch)
- Dynamic default branch detection
- Empty state handling
- Simplified UX with streamlined feedback flow
Closes#51Closes#56
Allow users to specify which browser opens plan files via environment variable.
Default behavior unchanged - only activates when env var is set.
- macOS: Set to app name ("Google Chrome") or path
- Linux/Windows: Set to executable path
Closes#42
- Update CLAUDE.md with new APIs and file structure
- Remove unused helper functions (isAgentSwitchEnabled, isPlanSaveEnabled)
- Sync all package versions to 0.4.10
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Refactor: shared server package with PLANNOTATOR_REMOTE env var
- Create packages/server/ with shared server implementation
- Add PLANNOTATOR_REMOTE=1 env var for devcontainer/SSH mode
- Deprecate SSH_CONNECTION detection (still works with warning)
- Both Claude Code and OpenCode now use identical server logic
- OpenCode gains Obsidian/Bear integrations and remote detection
- Update documentation with environment variables section
Fixes#27🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove PLANNOTATOR_ORIGIN env var, fix onReady callback timing
- Remove PLANNOTATOR_ORIGIN hack from Claude Code hook (hardcode "claude-code")
- Fix onReady callback to pass port directly (was referencing undefined server)
- Create tests/manual/test-server.ts for testing either origin
- Update test-hook-2.sh to use new test server with opencode origin
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add devcontainer test setup, reduce logging verbosity
- Add tests/devcontainer/ with devcontainer.json for testing remote mode
- Add tests/opencode-local/ for local OpenCode testing
- Update package.json build script for proper bundling
- Remove verbose multi-line error messages, keep useful errors
- Clean up unused deprecationWarned variable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add devcontainer support and documentation
- Add PLANNOTATOR_REMOTE env var for container/remote detection
- Remove console logging (silent operation)
- Add devcontainer.md with full setup instructions
- Add devcontainer section to OpenCode plugin README
- Add port-only test setup to reproduce common misconfiguration
- Update test devcontainers to forward port 4096 for opencode web
- Bump version to 0.4.1
Fixes#27🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update CLAUDE.md: legacy SSH detection, not deprecated
Removed incorrect mention of deprecation warning - SSH_TTY/SSH_CONNECTION
detection is silent by design.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix OpenCode agent switching after plan approval
After approving a plan, the conversation context stayed in "plan" mode
even though the TUI showed "build". This caused edits to fail because
the plan agent has edit permissions denied.
The fix uses session.prompt() to inject a message with agent: "build",
which triggers a new agentic loop with proper build agent permissions.
Fixes#29🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add global comments annotation capability
- Add GLOBAL_COMMENT type to AnnotationType enum
- Add "Global comment" button next to "Copy plan" in Viewer header
- Implement inline input form for entering global comments
- Update AnnotationPanel to display global comments with purple styling
- Update exportDiff to include global comments in feedback output
- Update sharing utils to serialize/deserialize global comments with 'G' prefix
* Add fallback for unknown annotation types and update docs
- Add fallback config in AnnotationPanel for forward compatibility
(prevents crash when portal encounters unknown annotation types)
- Update CLAUDE.md with GLOBAL_COMMENT enum value
- Update CLAUDE.md with 'G' ShareableAnnotation variant
A React-based annotation tool that intercepts Claude Code's ExitPlanMode
to provide visual plan review with collaborative features.
Features:
- Markdown plan rendering with syntax highlighting
- Text selection annotations (delete, replace, insert, comment)
- Redline mode for quick deletion marking
- URL-based sharing via compressed hash (no server storage)
- Tater identity system for anonymous collaboration
- Export to diff format
- Dark/light theme support
- Tater sprite easter egg
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>