Platform
macOS
Operating system version
macOS Tahoe 26.5.1 (25F80)
System architecture
ARM64 (M1, M2, etc)
PolyScope Version
0.24.1
Bug description
Bug description
When connected to a remote Polyscope server, the embedded preview correctly starts the expose tunnel and shows the tunnel URL. Opening that same preview in the system browser (⌘-click on the preview URL) instead hands the browser the raw preview.url from polyscope.json.
On a remote setup that URL is unreachable by definition — it only resolves and only listens on the server machine — so the browser lands on an error page while a perfectly good tunnel is already running.
Expected: the system browser opens the active tunnel URL (https://<subdomain>.<server>.sharedwithexpose.com), the same one the embedded preview is using.
Actual: the system browser opens https://<workspace>.test, which does not resolve on the client machine (and would not be reachable even if it did — Herd's nginx listens on 127.0.0.1 only).
Setup
- Server: desktop app embedded server (
polyscope-server serve) on a Mac mini, with Laravel Herd serving the sites.
- Client: Polyscope desktop app on a MacBook, connected to the mini through the relay (Servers list).
- Account:
subscribed: true; /api/user returns a valid expose_token and 6 expose_servers.
- Repo
polyscope.json:
{
"preview": {
"url": "https://{{folder}}.test"
}
}
No preview.tunnel: false opt-out is set.
Everything else in the chain works
This is not a tunnel failure. While the embedded preview is open, the expose process is alive on the server machine and the tunnel URL loads the site correctly from the client when pasted into the browser by hand. The token, the expose binary download, the relay connection and the tunnel itself are all fine — only the URL handed to the system browser is wrong.
Suggested fix
In the open-in-system-browser action, resolve the URL through the same path the embedded preview uses: if a tunnel is active for the worktree (getTunnelUrl), open that; otherwise fall back to the raw preview.url. Optionally start the tunnel on demand when the client is remote, so ⌘-click works even if the embedded preview was never opened.
Note
The tunnel subdomain is regenerated on every tunnel start (crypto.randomBytes(8).toString("hex")), so the tunnel URL is not stable across restarts — which rules out bookmarking it as a workaround.
Steps to reproduce
Steps to reproduce
- Run Polyscope on machine A (the server) with a workspace whose
polyscope.json defines a preview.url that is only reachable on machine A — e.g. a Herd/Valet .test host.
- From machine B, connect to that server through the relay (Servers list).
- Open the embedded preview for the workspace. ✅ A tunnel starts and the embedded browser shows the expose URL — this part works correctly.
- With that tunnel still running, ⌘-click the preview URL to open it in the system browser.
- ❌ The system browser opens
https://<workspace>.test instead of the tunnel URL, and fails to load.
Relevant log output
## Relevant log output
[tunnel] starting tunnel for <worktreeId> → https://<workspace>.test:443 (provider: expose)
[tunnel:expose] running: /Users/<user>/.polyscope/bin/expose-darwin-arm64 share https://<workspace>.test:443 --subdomain=<REDACTED> --auth=<REDACTED> --server=free --server-host=eu-2.sharedwithexpose.com
[tunnel:expose] tunnel ready at https://<REDACTED>.eu-2.sharedwithexpose.com
Confirmed on the server machine while the embedded preview was open — the tunnel process is alive
and serving:
$ ps -o args= -p <pid>
/Users/<user>/.polyscope/bin/expose-darwin-arm64 share https://<workspace>.test:443 \
--subdomain=<REDACTED> --auth=<REDACTED> --server=free --server-host=eu-2.sharedwithexpose.com
The ⌘-click happens after these lines and produces no further tunnel log entries — it never queries
the tunnel it already has.
Platform
macOS
Operating system version
macOS Tahoe 26.5.1 (25F80)
System architecture
ARM64 (M1, M2, etc)
PolyScope Version
0.24.1
Bug description
Bug description
When connected to a remote Polyscope server, the embedded preview correctly starts the expose tunnel and shows the tunnel URL. Opening that same preview in the system browser (⌘-click on the preview URL) instead hands the browser the raw
preview.urlfrompolyscope.json.On a remote setup that URL is unreachable by definition — it only resolves and only listens on the server machine — so the browser lands on an error page while a perfectly good tunnel is already running.
Expected: the system browser opens the active tunnel URL (
https://<subdomain>.<server>.sharedwithexpose.com), the same one the embedded preview is using.Actual: the system browser opens
https://<workspace>.test, which does not resolve on the client machine (and would not be reachable even if it did — Herd's nginx listens on127.0.0.1only).Setup
polyscope-server serve) on a Mac mini, with Laravel Herd serving the sites.subscribed: true;/api/userreturns a validexpose_tokenand 6expose_servers.polyscope.json:{ "preview": { "url": "https://{{folder}}.test" } }No
preview.tunnel: falseopt-out is set.Everything else in the chain works
This is not a tunnel failure. While the embedded preview is open, the expose process is alive on the server machine and the tunnel URL loads the site correctly from the client when pasted into the browser by hand. The token, the expose binary download, the relay connection and the tunnel itself are all fine — only the URL handed to the system browser is wrong.
Suggested fix
In the open-in-system-browser action, resolve the URL through the same path the embedded preview uses: if a tunnel is active for the worktree (
getTunnelUrl), open that; otherwise fall back to the rawpreview.url. Optionally start the tunnel on demand when the client is remote, so ⌘-click works even if the embedded preview was never opened.Note
The tunnel subdomain is regenerated on every tunnel start (
crypto.randomBytes(8).toString("hex")), so the tunnel URL is not stable across restarts — which rules out bookmarking it as a workaround.Steps to reproduce
Steps to reproduce
polyscope.jsondefines apreview.urlthat is only reachable on machine A — e.g. a Herd/Valet.testhost.https://<workspace>.testinstead of the tunnel URL, and fails to load.Relevant log output