Skip to content
Browse docs

Interfaces

Web console

Start the console stack and understand its authenticated RPC and narrow HTTP boundaries.

On this page+

Start the stack

The stack launcher checks Docker, starts or restarts the gateway, rebuilds stale SPA assets, builds sandbox-console, and starts it with the current gateway token.

Shell
bin/start-sandbox-console-stack
# open http://127.0.0.1:7880

Use --skip-gateway to keep an existing gateway, --skip-spa to keep packaged assets, or --bind HOST:PORT to change the console listener. The default remains loopback because browser authentication is out of scope.

Browser to gateway RPC

The browser never invokes a CLI or MCP server. Management, command, file read/write/edit/blame, and observability requests go to POST /api/rpc. The console validates the route against the public catalog, keeps the gateway token server-side, and forwards authenticated RPC through the shared operation client.

Console routePurpose
POST /api/rpcSingle public operation; SSE when requested for streamed logs
GET /api/catalogMerged public management, runtime, and observability catalogs
GET /api/sandboxes/<id>/healthProxy a daemon liveness probe
POST /api/sandboxes/<id>/files/listProxy the HTTP-only directory listing

Limited daemon HTTP

Every sandbox has a daemon_http endpoint separate from authenticated daemon RPC. Its exact allowlist is GET /health, POST /files/list, and application forwarding below /forward/.

Direct HTTP paths for file read/write/edit/blame, observability, and export return 404. file_list is the single HTTP-only operation exception; use gateway RPC through CLI, MCP, or /api/rpc for the public catalogs.

Access a sandbox server from the host

Suppose a ready sandbox is serving a webpage on port 8000. First inspect the sandbox to discover the daemon HTTP endpoint published on the host, then start the server in a shared command session. This example requires python3 in the sandbox image and jq on the host.

Shell
export SANDBOX_ID=eos-abc

DAEMON_HTTP=$(
  sandbox-manager-cli inspect_sandbox --sandbox-id "$SANDBOX_ID" |
    jq -er '.daemon_http | select(. != null) | "http://\(.host):\(.port)"'
)

SERVER=$(
  sandbox-runtime-cli --sandbox-id "$SANDBOX_ID" \
    exec_command --yield-time-ms 1000 \
    "python3 -m http.server 8000 --bind 127.0.0.1 --directory ."
)

COMMAND_SESSION_ID=$(
  printf '%s\n' "$SERVER" | jq -er '.command_session_id'
)

On the host, open the daemon endpoint with the shared forwarding prefix. The daemon removes that prefix before passing the request to the sandbox server, so the application receives / here.

Shell
APP_URL="$DAEMON_HTTP/forward/shared/8000/"

curl --fail --show-error "$APP_URL"
printf 'Open in a browser: %s\n' "$APP_URL"

Do not open http://127.0.0.1:8000/ on the host; that targets the host itself. Use the random daemon_http port returned by inspect_sandbox and the /forward/shared/8000/ path. Stop the example server by sending Ctrl-C to its command session:

Shell
sandbox-runtime-cli --sandbox-id "$SANDBOX_ID" \
  write_command_stdin --command-session-id "$COMMAND_SESSION_ID" \
  --yield-time-ms 1000 $'\003'

Shared servers may bind to 127.0.0.1 or 0.0.0.0. A server attached to an isolated workspace session must bind to 0.0.0.0 and use /forward/isolated=<workspace-session-id>/<port>/ instead.

Preview routing

Shared previews use /s/<id>/shared/<port>/.... Workspace-isolated previews use /s/<id>/isolated=<workspace-id>/<port>/.... The console rewrites these to the daemon’s forwarding allowlist and supports streaming bodies and protocol upgrades.

Configuration and security

--config-yaml outranks SANDBOX_CONSOLE_CONFIG_YAML when selecting an optional console section. Bind and assets resolve with flag, then environment, then YAML/default precedence. Gateway socket and token discovery is separate.

Preview documents have an opaque origin and cannot call /api/*. The token stays outside the browser. See configuration for defaults and the namespace architecture for the runtime boundary.

58 results