Skip to content

feat: VS Code / Cursor preview extension#18

Open
exilis wants to merge 13 commits into
masterfrom
feat/vscode-extension
Open

feat: VS Code / Cursor preview extension#18
exilis wants to merge 13 commits into
masterfrom
feat/vscode-extension

Conversation

@exilis

@exilis exilis commented Jul 10, 2026

Copy link
Copy Markdown
Owner

What

Adds a VS Code / Cursor extension (new self-contained npm project under editor/vscode/) that opens the existing reefdoc preview inside an editor panel instead of a separate browser tab.

It's a thin launcher + embedder: on the reefdoc: Open Preview command it picks a free port, spawns the bundled reefdoc binary (reefdoc --addr 127.0.0.1:<port> <workspaceRoot>), waits until it serves, and frames that localhost server in a webview panel. The Go backend and JS frontend are reused verbatimmain.go is untouched (the --addr flag it needed already existed). One extension works in both VS Code and Cursor.

How it's structured

  • src/server.ts — pure Node (no vscode import, unit-testable): per-platform binary resolution, free-port selection, spawn/poll/stop lifecycle.
  • src/panel.ts — webview panel with a full-bleed iframe and a CSP scoped to the server's exact origin.
  • src/extension.ts — wires the command: single-instance, error notifications (no workspace / unsupported platform / start failure), kills the child on panel dispose and on deactivate.
  • scripts/bundle-binaries.mjs — cross-compiles the binary for darwin-arm64, darwin-x64, linux-arm64, linux-x64, win32-x64 into bin/; npm run package produces a local .vsix (no marketplace).

Testing

  • cd editor/vscode && npm test → 6/6 pass. Includes a smoke test that builds the real Go binary, spawns it, and asserts GET / → 200 — plus a regression test that startServer rejects (not crashes) on a bad binary path.
  • Config: reefdoc.binaryPath (override bundled binary) and reefdoc.host (default 127.0.0.1).

Not yet done (needs a human at a GUI — can't run headless)

  • Interactive Extension Development Host check (F5 → open folder → run command → confirm tree renders, live reload fires, process dies on panel close).
  • Install the produced .vsix via "Install from VSIX…" and confirm the bundled binary is used with no reefdoc.binaryPath set.

Follow-ups (non-blocking)

  • No CI wiring for the extension's own npm project yet.
  • IPv6 reefdoc.host (e.g. ::1) would need a bracketed URL — currently unreachable (server probe fails first).

Design & plan

  • Spec: docs/specs/2026-07-10-vscode-extension-design.md
  • Plan: docs/superpowers/plans/2026-07-10-vscode-extension.md

Built via subagent-driven development: each task TDD'd, task-reviewed, with a final whole-branch review (verdict: ready to merge). Three review findings were caught and fixed — spawn-error host crash, a double-invocation double-spawn race, and the reefdoc.host/CSP inconsistency.

🤖 Generated with Claude Code

exilis and others added 13 commits July 10, 2026 14:43
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
startServer attached no 'error' listener on the spawned child. When spawn
fails to launch the binary (bad/missing binaryPath, ENOENT, permissions),
Node emits an 'error' event with no listener, producing an uncaught
exception that crashes the host process; 'exit' never fires so the existing
early-exit detection never engaged.

Add a child.on('error') listener that marks the child as exited and records
the error, and surface it in the rejection ("reefdoc failed to start: ...").
Add a regression test asserting startServer rejects (rather than crashing)
on a bad binary path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e failure

Derive the webview CSP frame-src from the actual server URL origin instead
of a hardcoded loopback allowlist, so a non-loopback reefdoc.host doesn't
get silently blocked. Thread the host into findFreePort so the port probe
binds the same interface the server will use. Also stop the spawned server
if panel creation throws, so the child process doesn't leak.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant