Guide
How do I preview the dev server my agent is running?
Forward the port to your own machine, as you would with an SSH tunnel to a VPS. In Sanbox, an admin allows the port on the Computer's template, and sanbox ports forward <run-id> 3000:5173 serves the agent's dev server at http://127.0.0.1:3000 on your laptop, with nothing made public. Page loads, API calls and server-sent events (SSE) work; WebSockets don't, so hot reload won't connect and you refresh the page to see changes.
Run this with your agent
Read https://sanbox.cloud/kb/parallel-work/preview-your-agents-dev-server.md and follow it to preview my agent's dev server.
If the Sanbox CLI is missing, install it with `npm install -g @sanlabs/sanbox-cli@latest`
and sign in with `sanbox login`. Show me each command before you create, stop or delete a Computer.
How does port access work?
Port access is off by default. A template's inbound rules list the ports that authenticated port connections may reach, and optionally which public IPs or CIDRs may call. Nothing becomes public: every caller needs a short-lived token, or goes through the CLI's local forwarder, which handles the token for you.
It works for an OpenCode Computer where the agent runs npm run dev, and for a container in a Docker Computer. Port access needs CLI 0.0.20 or later.
Steps
1. Allow the port on the template
An organisation admin adds the port when creating the template:
sanbox templates create --name "Web dev" --type opencode-computer \
--model-provider <provider-id> --model <model-id> \
--network-policy policy.json --inbound-port 5173 --json
Or on an existing template, replacing its rules:
sanbox templates inbound set <template-id> --port 5173 --json
Add --source <ip-or-cidr> to accept only listed public addresses. Each run keeps the rules it was created with, so a template change applies only to new Computers you start from the template afterwards, not to existing ones you resume. A few ports are reserved for Sanbox, and the CLI rejects them.
2. Start a Computer
sanbox run --template <template-id> --json
3. Start the dev server inside it
The server must listen on the allowed port, on 127.0.0.1 or 0.0.0.0. Ask the agent to start it, or run it yourself in the console terminal, where the session keeps running after you close the tab. From your machine:
sanbox exec <run-id> --cwd /workspace/app --detach --timeout 86400 \
--request-key <key> --json -- 'npm run dev -- --host 127.0.0.1 --port 5173'
That example passes Vite's --host and --port options; use your dev server's equivalents. Commands stop at their timeout, which is 3,600 seconds unless you raise it, so pass --timeout for a long-lived server. In a Docker Computer, publish the container's port on loopback:
sanbox exec <run-id> -- docker run -d -p 127.0.0.1:8080:8080 <image>
4. Forward it to your machine
sanbox ports forward <run-id> 3000:5173
Open http://127.0.0.1:3000. The local port comes first, like ssh -L. The forwarder creates its own token, renews it before it expires, and revokes it when you press Ctrl-C. It listens only on 127.0.0.1, ::1 or localhost, and refuses requests from web pages on other sites. Keep it running while you use the preview.
5. Call it from a server instead
For a backend, a test runner or a teammate's service, create a connection and use its URL and token:
sanbox ports connect <run-id> --port 5173 --expires 1h --json
curl -N -H "Authorization: Bearer $PORT_TOKEN" "$PORT_URL/api/health"
The response holds data.url and a one-time data.access_token. Treat the token as a secret. It works only for that run, those ports and the current boot, and expires after 1 minute to 1 day (1 hour by default).
Why doesn't hot reload work?
Port connections carry HTTP requests and streamed responses such as SSE. They don't carry WebSockets, HTTP/2, gRPC or raw TCP. Vite, for example, uses a WebSocket for hot module replacement, so the page loads but live updates don't arrive.
- Refresh by hand after the agent changes code.
- Turn hot reload off if the failed connection gets in the way. In Vite,
server.hmr: falsedisables it.
What else should I know?
- A
ports connectURL is an API proxy, not a preview site. Sanbox strips the URL prefix, so the service receives/api/healthfor$PORT_URL/api/health, and pages with absolute links break. Useports forwardfor pages. - A browser
EventSourcecan't send the token. Call connection URLs from a server. - Headers within 30 seconds. The service must start its response in time. The body can then stream while the token works.
- Every request appears to come from
127.0.0.1. Don't let the dev server treat loopback callers as trusted. - Sanbox removes
AuthorizationandCookieheaders before requests reach the service, and dropsSet-Cookiefrom responses, so cookie-based logins in the app won't stick. - Resume ends old connections. Old tokens return
410 port_connection_ended. Forward again after a resume. A fork needs its own connection.
Common errors
| Error | What it means |
|---|---|
409 port_access_disabled | The run allows no ports. Allow the port on the template, then start a new Computer. |
400 port_not_allowed | The port isn't in the run's inbound rules. |
403 port_connection_source_denied | No rule admits the caller's address. The message names the address Sanbox saw. |
502 port_unreachable | Nothing listens on that port. Check the server is running on 127.0.0.1 or 0.0.0.0. |
409 port_access_unsupported | The run's image predates port access. Start a new Computer from the template. |
429 port_connection_busy | The Computer already has 64 open requests through Sanbox. |
Snapshot it
Computers started from a snapshot or warm pool keep the ports of the Computer the snapshot came from. If the snapshot predates your inbound rule, start a Computer from the updated template, prepare it, and take a new snapshot.
What this doesn't do
- No public URL. Every caller needs a token or the local forwarder.
- No WebSockets, HTTP/2, gRPC or raw TCP.
- No changes to existing Computers. New inbound rules apply only to new Computers started from the template after you save them.
Related
- How do I run Docker Compose inside an AI agent's sandbox?
- How do I run OpenCode as a server on a remote computer?
- How do I restrict which domains an AI agent can reach?
Sources
- Vite, Server options: server.hmr and server.ws, checked 2026-11-06
- Vite, Command line interface: --host and --port, checked 2026-11-06