#1357 made the panel defer to the app's stored theme mode and seeded
System only when no mode was stored. That helped first-time panels and
nobody else: every panel opened before it already stored `dark`, written
by ThemeProvider on its first mount rather than chosen by anyone, so the
seed never fired and the panel stayed dark in a light IDE. That is issue
#1053 exactly, still broken for the users who reported it.
There is no provenance in the store to read: it is one flat cookie string
in globalState with no timestamps and no per-cookie metadata, and the app
writes the same `plannotator-theme=dark` whether the user picked Dark or
never opened the theme settings. The migration leans on the three signals
that do exist. `light` and `system` are values the auto-seed cannot
produce, so they are choices and are never touched. A new
`plannotator-vscode-seed` marker, written on every load, makes the
re-seed run at most once per store, so a Dark picked afterwards is
permanent. And a mode the user actually picked is recorded server-side in
~/.plannotator/config.json by configStore.set, which configStore.init
applies over the cookie and writes back, so a real choice outranks the
seed and re-asserts itself in the same page load.
What remains is a Dark that exists only as a cookie with nothing in
config.json behind it. That is indistinguishable from the auto-seed and
is reset once: invisible in a dark IDE, and in a light IDE one re-pick
makes it stick for good.
Also fixes the type error #1357 shipped in applyPanelCookieDefaults and
adds the extension's own tsc to CI, which had never run there.
Co-authored-by: Michael Ramos <backnotprop@gmail.com>
The theme bridge wrote VS Code's colors as inline custom properties on
<html>, the same element ThemeProvider stamps `theme-<palette>` and
`light` on, and it forced the `light` class to the IDE's theme kind. An
inline property outranks every `.theme-*` rule, so picking Light in a
dark IDE produced dark VS Code tokens sitting under a `.light` class,
and any palette chosen in Plannotator's settings was painted over.
The bridge now reconciles instead of applying once on arrival: VS Code
colors are only painted while the user is on the default palette and the
app is already rendering the IDE's light/dark side, anything it painted
is removed the moment that stops holding, and it no longer writes the
`light` class except to map System onto the IDE's theme kind.
Panels that have never stored a mode seed System, so a first-time user
in a light IDE still gets a light panel now that the bridge does not
force the mode.
Reported by @it-sha.
The Plannotator app runs in a nested cross-origin iframe inside the VS Code
webview, where two input paths break:
- Clipboard: the iframe document never holds focus, so the async Clipboard
API is rejected ("Document is not focused") and native copy/cut/paste
events never fire. Copy, cut, and paste all silently fail.
- Keybindings: keydown events don't cross the iframe boundary, so VS Code
never sees global shortcuts (Cmd+P, etc.) while a Plannotator tab is focused.
Fix both off the one input signal the iframe still receives — keydown:
- Route clipboard reads/writes through the extension host, which owns the
system clipboard via vscode.env.clipboard. The injected script overrides
navigator.clipboard and handles Cmd+C/X/V, relaying through the wrapper to
an onDidReceiveMessage handler and back.
- Forward all other keystrokes to the wrapper, which re-dispatches a synthetic
KeyboardEvent on the webview document so VS Code can resolve its keybindings.
Undo/redo/select-all stay native.
Fixes#864Fixes#969
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: add PLANNOTATOR_DATA_DIR env var to customize data directory
* fix: update missed hardcoded paths to use PLANNOTATOR_DATA_DIR
OpenCode plugin and VS Code extension still used hardcoded
~/.plannotator paths, causing the IPC registry and plan backing
file to diverge from the server when PLANNOTATOR_DATA_DIR is set.
Also exports data-dir from @plannotator/shared and documents the
new env var in AGENTS.md.
Co-authored-by: Chris Werner Rau <14326070+cwrau@users.noreply.github.com>
Co-authored-by: João O. Santos <34689526+Joao-O-Santos@users.noreply.github.com>
* fix: vendor data-dir.ts into Pi extension and rewrite imports
The Pi extension copies shared/server modules into generated/ at
build time. Without vendoring data-dir.ts and rewriting the
parent-relative imports, typecheck fails on all generated files
that import getPlannotatorDataDir.
* refactor: eliminate duplicated data-dir logic and clean up call sites
- VS Code extension: replace inlined getPlannotatorDataDir() copy with
import from the canonical packages/shared/data-dir.ts (esbuild bundles
it, so no runtime dependency needed)
- storage.ts: hoist repeated getPlannotatorDataDir() calls to a
module-level DATA_DIR constant, matching the pattern config.ts uses
- data-dir.ts: remove inaccurate docstring claim about relative path
resolution (the code does not call resolve())
- improvement-hooks.ts: hoist to DATA_DIR constant, clarify comments
on the two-level hook lookup (hooks/ subdir vs root fallback)
* fix: resolve relative PLANNOTATOR_DATA_DIR to absolute path
A relative value like ./data would break readArchivedPlan's path
traversal guard, which compares a resolve()'d absolute path against
the still-relative planDir prefix. Always return an absolute path
so all callers get consistent path shapes.
* fix: use @plannotator/shared/data-dir imports in server package
Switch from relative ../shared/data-dir imports to the package
export, matching the convention every other server file follows.
Update Pi vendor script sed rules to match the new import style.
* fix: use package imports in server and respect data dir in compound skill
Server modules: switch from relative ../shared/data-dir imports to
@plannotator/shared/data-dir, matching the convention every other
server file follows. Update Pi vendor script sed rules to match.
Compound skill: update hardcoded ~/.plannotator paths to check
PLANNOTATOR_DATA_DIR first, so the skill reads plans and writes
the improvement hook to the correct location when users set a
custom data directory.
Co-authored-by: Chris Werner Rau <14326070+cwrau@users.noreply.github.com>
Co-authored-by: João O. Santos <34689526+Joao-O-Santos@users.noreply.github.com>
* fix: remove remaining hardcoded ~/.plannotator assumptions
- Settings UI: replace hardcoded path in label and placeholder with
generic text that doesn't assume a specific data directory
- quickLabels: update agent tip to reference PLANNOTATOR_DATA_DIR
so the agent checks the correct plans directory
- codex-review: hoist getPlannotatorDataDir() to module-level DATA_DIR
constant, eliminating redundant per-call resolution in debugLog()
- Tests: make submit-plan and storage tests resilient to
PLANNOTATOR_DATA_DIR being set in the environment
- Install scripts (sh, ps1, cmd): check PLANNOTATOR_DATA_DIR before
falling back to ~/.plannotator for config.json attestation lookup
* fix: expand tilde in install script and update test assertions
install.sh: PLANNOTATOR_DATA_DIR set to ~/... stays literal inside
double quotes, so the config file check silently failed. Add case
statement to expand ~ the same way the runtime data-dir.ts does.
install.test.ts: update three assertions that checked for hardcoded
~/.plannotator paths — now verify PLANNOTATOR_DATA_DIR awareness
instead.
* docs: add PLANNOTATOR_DATA_DIR to env var reference with VS Code note
Document the new env var on the marketing site's environment
variables reference page. Include a footnote about ensuring
VS Code inherits the variable when launched from the Dock.
---------
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
Co-authored-by: Chris Werner Rau <14326070+cwrau@users.noreply.github.com>
Co-authored-by: João O. Santos <34689526+Joao-O-Santos@users.noreply.github.com>
* fix: add retry + auto-reload to VS Code proxy for SSH race condition (#321)
When opening plannotator over VS Code SSH Remote, the webview could show
a "proxy error" because the cookie proxy connected before the upstream
Bun server was ready. Two layers of defense:
1. Retry with exponential backoff (200/400/800ms) in the cookie proxy,
buffering the request body so retries can replay it
2. Silent iframe auto-reload in the webview wrapper if no "ready" signal
is received within 3 seconds (max 1 reload to prevent loops)
Bump vscode extension to 0.5.2.
* fix: file-based IPC registry for VS Code extension discovery (#321)
VS Code's environmentVariableCollection only injects PLANNOTATOR_BROWSER
into interactive terminal shells — background processes spawned by Claude
Code hooks don't inherit it. In SSH Remote sessions this meant
openBrowser() was never called (handleServerReady skipped it when
isRemote=true and PLANNOTATOR_BROWSER was unset).
- Extension writes IPC port to ~/.plannotator/vscode-ipc.json keyed by
workspace path; cleans up on deactivate
- openBrowser() falls back to IPC registry when shell-based open fails,
using longest-prefix workspace match for multi-window support
- handleServerReady() always calls openBrowser() since the IPC fallback
handles the remote case
Persist the IPC port in workspaceState and try to rebind to it on
activation so restored terminals still have a valid PLANNOTATOR_VSCODE_PORT.
Falls back to a random port if the preferred one is taken.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add shared EditorAnnotation type
Single source of truth for the editor annotation interface,
imported by both @plannotator/server and @plannotator/ui.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: editor annotation server endpoints
In-memory store with POST/GET/DELETE endpoints for editor annotations.
The array lives in the handler closure and dies with the server session.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: editor annotation UI — polling hook, card, panel, and export
- useEditorAnnotations hook with auto-disable polling (500ms interval)
- EditorAnnotationCard with file path, code preview, and comment
- AnnotationPanel conditionally renders editor annotation section
- exportEditorAnnotations formats annotations for Claude feedback
- App.tsx wires hook, includes in output memo and send feedback gate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: VS Code extension editor annotation command
Cmd+Shift+. or right-click to capture selected text as an annotation.
POSTs through the cookie proxy to the plannotator server. Adds amber
left-border decorations on annotated lines, cleared on panel close.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: inline comment threads, lightbulb menu, and stronger decorations
Replace showInputBox with VS Code CommentController for inline annotation
threads anchored to selected code. Add CodeActionProvider for lightbulb
discoverability. Stronger decoration styling with gutter icon.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: VS Code theme integration for webview
Bridge VS Code CSS variables to Plannotator's CSS variable system via
postMessage between wrapper page and proxied iframe. Automatically adopts
the active VS Code color theme (dark/light/custom) without touching any
UI components or CSS files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: gate editor annotation polling behind VS Code detection
Only poll /api/editor-annotations when running inside a VS Code webview
(window.__PLANNOTATOR_VSCODE). Browser and shared URL users now have
zero network cost from the editor annotations feature. Also fixes poll
interval from 500ms to 2000ms.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: faster polling, prevent unnecessary re-renders, unify HTTP helper
- Poll interval 2s → 500ms for snappier annotation pickup
- Shallow equality check on annotation IDs prevents React re-renders
when poll data is unchanged
- Merge postToProxy/deleteFromProxy into single requestProxy function
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: editor annotations support in code review
Wire existing editor annotation infrastructure into the review flow
so VS Code users can annotate files outside the diff during code review.
- Add editor annotation endpoints to review server (same 3-line pattern)
- Call useEditorAnnotations hook in review App.tsx
- Display editor annotations in ReviewPanel with "Editor" divider
- Include editor annotations in feedback export and gating logic
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* 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>