Starts an httpgd::hgd() graphics device bound to all interfaces and returns a URL that is reachable from another device, such as an iPad running a terminal over SSH or mosh.

serve_plots(
  host = NULL,
  port = 0,
  bind = "0.0.0.0",
  token = TRUE,
  quiet = FALSE,
  ...
)

Arguments

host

Hostname to advertise in the URL. If NULL, resolved from configuration and from the Tailscale node name (see Details).

port

Port to bind. The default 0 lets the operating system pick a free port, which avoids clashing with other local servers.

bind

Address to bind the server to. Defaults to "0.0.0.0" so the device answers on every interface; use "127.0.0.1" to keep it local.

token

Access token, passed to httpgd::hgd(). TRUE (default) generates one and embeds it in the returned URL.

quiet

If TRUE, do not message the URL.

...

Further arguments passed to httpgd::hgd(), such as width, height, zoom, or bg.

Value

The plot URL, invisibly, as a character scalar.

Details

httpgd advertises its server under the local mDNS name (for example machine.local). That name only resolves through multicast on the same physical network, so it is useless from a tablet connected over a VPN and is the usual reason a pasted URL loads nothing. serve_plots() replaces that hostname with one the remote device can actually resolve.

The advertised hostname is resolved in this order:

  1. the host argument;

  2. the MISC_PLOTS_HOST environment variable;

  3. options(misc.plots_host = "...");

  4. the Tailscale MagicDNS name of this machine, read from tailscale status --json;

  5. the httpgd default, with a warning that it may not resolve remotely.

The device lives as long as the R session. Call grDevices::dev.off() to stop it, or serve_plots_url() to recover the URL of a running device.

Binding to 0.0.0.0 exposes the device to every machine that can reach this host on that port. Keep token = TRUE unless the network is trusted.

Troubleshooting a 404

httpgd serves the plot viewer at /live and nothing else, so the URL has to be opened whole. A bare host:port, a trailing slash after /live, or a URL clipped by a terminal that wrapped it all answer 404 Not Found; a missing or stale token answers 401 Unauthorized instead. The URL is therefore messaged on a line of its own, so tapping it in a wrapped terminal does not hand the browser a fragment, and it is probed once before being returned: an HTTP error from this machine is reported as a warning rather than left for the browser to find.

Pinning port and token keeps the URL stable across sessions, which is worth doing when the remote browser bookmarks it: serve_plots(port = 7070, token = "plots").

Examples

# \donttest{
if (interactive()) {
  serve_plots()
  plot(1:10)

  # pin the hostname when Tailscale is not in use
  serve_plots(host = "192.168.0.10")
}
# }