Saltar para o conteúdo

Forward ports from a terminal

Este conteúdo ainda não está disponível no seu idioma.

A server you start in a conversation’s terminal is published only for that space. The ports panel notices listeners this app started there, maps them, and gives you an address for every place you might want to reach them from. Two spaces can both listen on 5173; their maps never mix.

Nothing here opens the machine up: every path is created by the server, on request, and dies with the terminal or rig.

  1. Open the conversation’s Terminal (VM) or host-shell (in a space or on a PR page).
  2. Start your server — pnpm dev, python -m http.server 8000, anything.
  3. Within a few seconds the plug icon in the terminal’s top-right corner gets a dot. Click it.

The panel lists every listening port with the process that owns it, as 3000 → 3000: the port the process bound on the left, the port it answers on locally on the right (the same number whenever it was free on your machine). Each row also says whether desktop localhost, the Browser (VM), and Android can reach it.

Discovery is contained: a Terminal (VM) is polled inside that guest; a host-shell is polled from that session’s PTY process tree. Other spaces, and other processes on your Mac, are not listed.

New ports in this terminal are forwarded automatically. Turn Auto-forward ports off in the same panel if you want only the ones you add yourself.

Use Copy local URL on the row — http://localhost:3000. The forward listens on loopback only, so nothing else on your network can see it.

If two spaces both expose guest 5173 and your machine already holds 127.0.0.1:5173, the second space keeps guest 5173 and gets an ephemeral local port. Copy URL uses the right-hand number.

On a host-shell, the process is already on your machine. Mapping the same local port is a no-op; picking a different local port binds a loopback proxy to the one you chose.

--host (or binding 0.0.0.0) does not make an enclosed Browser (VM) able to reach a server on the Mac. The guest has its own loopback; the server plants a tunnel into that guest when the Browser tab is in the same space.

Open the enclosed browser in the same conversation. Type localhost:<left-hand port> — the number the process bound. A remap (5173 → 3000) also answers at the right-hand number in that browser, so Copy URL works there too. An agent’s browser_use can navigate to either. A server in Space A never appears as localhost:5173 in Space B’s browser.

Use localhost, not a LAN IP and not --host. The guest has its own loopback; the tunnel listens there on both IPv4 and IPv6.

Pages that open many connections at once (dozens of assets, a live reload socket) share that same tunnel. The Browser (VM) multiplexes them onto one persistent exec, so a burst of fetches is not one process spawn per connection and does not time out as a white page.

Inside one space, a Terminal (VM) forward wins over a host-shell on the same number. Across spaces there is no precedence — they are separate maps.

Open that space’s Android tab. The emulator’s localhost:<port> is then reversed to this space’s published port (adb reverse). One emulator is device-global: attaching Space B retargets :5173 to B and drops A’s. Close the tab and the reverses this rig planted are removed.

iOS Simulator already is the Mac — no reverse. A physical iPhone still needs a LAN share.

⋯ → Share on local network publishes the port at <server-ip>:<random port> — useful for opening the page on your phone, or when the server runs on another machine.

  • The LAN port is always OS-assigned, never the guest’s number, so exposure is a deliberate, visible address rather than a guessable one.
  • It stays private (loopback-only) until you flip it, and ⋯ → Local only takes it back off the network.

⋯ → Set a browser domain (.test) assigns the port a dev domain such as myapp.test. Inside the Browser (VM), https://myapp.test then loads your server with a valid padlock — useful for anything that behaves differently on a named origin or a secure context (cookies, service workers, OAuth callbacks).

  • Domains must end in .test or .localhost — the two TLDs reserved for development, so a dev name can never shadow a real site.
  • Domain names are unique on the server; port numbers are not. Two spaces may both use 5173, but they cannot both claim myapp.test.
  • The certificate comes from a local authority minted on your server the first time it is needed. Its keys live under the server’s data directory and never enter any guest; the enclosed browser trusts exactly that one key, so TLS to the real internet still validates normally.
  • The domain resolves inside the Browser (VM) only. Your own browser on the host uses localhost:<port> instead.
  • Plain http://myapp.test works too.

Add port at the bottom of the panel maps a port before (or whether or not) anything is listening on it. A manual forward keeps its address while your server restarts — the row shows not listening until it comes back — where auto-forwards disappear when their port does. On a host-shell you can also set a different local port.

Ports are keyed by workspace and space. The hypervisor’s own port map is fixed when a machine boots, so a Terminal (VM) rides two narrow channels the server controls: one pre-created inbound lane into the guest that refuses to connect to any port the guest is not actually listening on, and reverse tunnels the server holds open for the Browser (VM) and Android. A host-shell never scans the whole machine. No listener is ever created inside a guest that the server did not put there, and everything is torn down with the terminal or rig. The design is explained in Rigs and enclosures; the exact reserved ports and domain rules are in the rigs reference.