Techniques

Extension Development Host

The EDH window: how oxp dev spawns it, its chrome, commands, output channel, error boundary, and lifecycle.

The Extension Development Host (EDH) is the IDE window in which your in-development extension runs. It is a real, full-fidelity instance of your IDE — VS Code, Cursor, Windsurf, VSCodium, or any IntelliJ-family product — with the OXP host adapter loaded and your extension auto-attached to the running dev session.

You never spawn the EDH manually. oxp dev does it for you.

Why a Separate Window?

Running your extension in the same window where you edit its source has historically been the standard "F5" experience — but it has real costs:

  • State pollution — your dev environment (open files, debug sessions) collides with your extension's runtime state.
  • Crash blast radius — a bug in your extension can take down your editor.
  • Indistinguishable bundles — it's hard to tell what version of your extension is running.

The OXP EDH puts your extension in its own pristine window, with its own activity-bar icon, its own permissions, and a loud header indicating it's a dev session. Your source window stays untouched.

Automatic Spawn

When you run oxp dev:

  1. The CLI packs your extension.
  2. It writes an autostart marker to $OXP_HOME/edh/autostart.json (default ~/.oxp/edh/autostart.json). The marker contains: dev-server URL, project path, IDE family, host PID, and an expiry timestamp.
  3. It launches the IDE with a clean workspace (no folder, no SCM context). Example: code --new-window /tmp/oxp-edh-<sessionId>.
  4. The OXP host extension activates in the new window, reads the marker (only if its expiry is fresh and PID is alive), and connects to the dev server immediately. No command palette step. No prompt.
  5. Your extension renders in the sidebar.

If the marker is missing or expired, the new window starts as a normal editor — no auto-attach. Run oxp dev clean to clear stale markers.

Anatomy of an EDH Window

┌──────────────────────────────────────────────────────────────────┐
│ File  Edit  …                                  OXP Dev (v0.1.2) │ ← title bar tag
├───┬──────────────────────────────────────────────────────────────┤
│ ⓘ │   Your extension's sidebar view                              │
│ 🔍│   ─────────────────────────────                              │
│ 📦│   DEV: signature bypass                                      │ ← header chip
│ ▶ │                                                              │
│ 🅾 │ ◄── OXP activity-bar icon (clicked, sidebar visible)         │
│   │                                                              │
├───┴──────────────────────────────────────────────────────────────┤
│ $(plug) OXP Dev · v0.1.2 · session 4f3a   …other status items…  │ ← status bar
└──────────────────────────────────────────────────────────────────┘

Key elements:

  • Activity-bar / tool-window icon — labelled OXP. The host adds it the moment a dev session attaches.
  • Sidebar view — renders oxp-ui-v1 or hybrid-v1 UI natively. For webview-v1, an isolated webview iframe is mounted here.
  • DEV chip — always visible in dev mode; the production install path never shows this.
  • Status bar / status widget — connection state, session id, packed version (see Development Workflow for the icon legend).
  • Title-bar suffixOXP Dev (vX.Y.Z) so you can tell EDH windows apart at a glance.

Command Palette

The EDH exposes a small set of commands under the OXP: prefix:

CommandWhat it does
OXP: Restart Dev SessionDisposes the extension, reconnects to the dev server, re-loads the latest bundle
OXP: Reload BundleAsks the dev server for the current bundle and re-instantiates without reconnecting
OXP: Open Output (Dev Host)Focuses the OXP Dev Host output channel
OXP: Show ManifestOpens the active bundle's oxp.json read-only
OXP: Show Bundle InfoPops a modal with digest, size, signedBy (or unsigned (dev)), packed-at timestamp
OXP: Detach Dev SessionDisconnects but leaves the window open; useful for inspecting the last-known state

In JetBrains hosts, the same commands are reachable via Help → Find Action (Ctrl/Cmd+Shift+A).

Output Channel

The OXP Dev Host channel logs everything: file events, pack results, reload pushes, RPC call traces (at info level), and unhandled errors.

In VS Code family: View → Output → OXP Dev Host. In JetBrains: OXP Dev Host tool window (bottom dock).

Set OXP_LOG=debug before oxp dev to include per-RPC tracing.

Error Boundary

Every host call (storage/*, http/*, editor/*, …) is wrapped in an error boundary on the host side. When your extension throws:

  1. The boundary catches the error and serializes it (message, stack, RPC method, args).
  2. The sidebar view switches to an error panel showing the structured failure.
  3. The status bar turns red: $(error) OXP Dev.
  4. The error is appended to the output channel.
  5. A Restart button re-instantiates the extension without restarting the IDE.

The host extension itself never crashes. The blast radius of a misbehaving extension is exactly one sidebar view.

Hot Reload

When the dev server pushes a new bundle:

  1. The host receives the WebSocket reload message.
  2. The current extension instance's dispose() is awaited (up to 2 s).
  3. The new bundle is verified (digest match, manifest schema, policy).
  4. A new instance is constructed; activate() is invoked.
  5. The sidebar is re-rendered in place.

Total time, typical: 100–250 ms from save to visible update.

State across reload: UI form values and scroll positions are preserved for views with stable ids. In-memory JS variables are not — persist them through storage/* if you need durability.

Ending the Session

Press Ctrl+C in the terminal where oxp dev is running. The CLI:

  1. Sends a shutdown frame to every connected host.
  2. The EDH window dismisses its sidebar, removes the activity-bar icon, and closes itself.
  3. The dev server stops listening.
  4. The autostart marker is deleted.

You can also use OXP: Detach Dev Session in the EDH if you want the window to stay open after the server stops — the extension stays loaded as a frozen snapshot of the last bundle (useful for screenshots).

VS Code Family vs JetBrains

AspectVS Code / Cursor / Windsurf / VSCodiumJetBrains (any IntelliJ-Platform IDE)
Window launchcode --new-window (or cursor, windsurf, codium)idea / pycharm / webstorm / … via runtime-bin/ launcher
SidebarActivity bar, OXP iconRight tool window, OXP stripe button
Detach gestureClose window or OXP: Detach Dev SessionClose window or Tools → OXP → Detach
OutputOutput panel, OXP Dev Host channelTool window, OXP Dev Host
Restart shortcutCommand palette → OXP: Restart Dev SessionFind Action → OXP: Restart Dev Session

The contract is identical. Bundle, manifest, signature, WIT pin, RPC calls — all bit-equivalent across families.

Troubleshooting

  • Window opened but extension didn't appear — check the OXP Dev Host output channel. Most often a pack/validation error.
  • EDH won't attach — run oxp dev clean and start again. A stale autostart marker can block re-attach.
  • Wrong IDE launched — pass --host vscode or --host jetbrains explicitly.
  • Port in useoxp dev --port 8080 (or set OXP_DEV_PORT).
  • Auto-detected wrong launcher (e.g. code instead of cursor) — set OXP_IDE_LAUNCHER=cursor in your shell environment.

Next Steps