Skip to content

auto-forward: honor onAutoForward openBrowser/openPreview (host browser open) #193

Description

@pofallon

Tracked deferral from up --auto-forward (spec 015-auto-forward-ports, task T059; shipped in #188). v1 honors onAutoForward values ignore/silent/notify; openBrowser/openPreview are accepted but treated as notify.

Goal / acceptance

portsAttributes.onAutoForward: openBrowser (and openPreview) trigger opening the forwarded http://127.0.0.1:<host_port> URL on the host when the port becomes active.

Background

to_resolved() in crates/core/src/port_forward/daemon.rs currently collapses OpenBrowser/OpenPreview → Notify. The forward still happens and is reported; nothing is auto-opened.

Hidden issues / gotchas

  • The forwarder is a detached, headless background process (stdio redirected to a log; setsid). It has no display/session context, so naively shelling xdg-open/open from the daemon may target the wrong session, fail silently, or do nothing on a headless server / SSH host. This is the core reason it's awkward.
  • "openPreview" has no meaning outside an IDE. It's a VS Code in-editor webview concept. A CLI can at best treat it like openBrowser; true preview belongs to an editor integration, not deacon.
  • Cross-platform divergence: xdg-open (Linux), open (macOS), start/rundll32 (Windows) — and none of them are right on a remote/headless host.
  • Risk in CI/automation: must be a no-op (not an error) when there's no usable browser/display ($DISPLAY unset, $SSH_CONNECTION set, $BROWSER empty, CI), and must never block or fail up/the daemon. Hard to assert meaningfully in hermetic tests beyond "doesn't crash / no-ops headlessly."
  • Should likely respect the $BROWSER env var and be suppressible.

Recommended path forward

  1. Implement openBrowser (map openPreview → same, with a doc note that true preview is editor-only): on first activation of such a port, best-effort launch the host browser via $BROWSER else platform default (xdg-open/open/start).
  2. Guard hard: skip silently when headless/remote/CI (!$DISPLAY && !$WAYLAND_DISPLAY on Linux, $SSH_CONNECTION set, CI set) or no opener found — log at debug, never error.
  3. Add a kill-switch (e.g. --no-open / honor $BROWSER="").
  4. Tests: unit-test the decision logic (which value → open vs notify, headless → no-op); integration just asserts the forward still works and nothing blocks.

Notes

Low effort, low risk if the headless guard is strict. Lowest-value of the set on a server/SSH workflow (where you'd open the SSH-tunneled URL on your laptop yourself).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions