You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
On Linux the hub and the coder's browser cannot reach the app running in the sandbox #71
What happened. After the first build finished, the Live Preview stayed on "Starting the app" indefinitely, while its log showed the server and Vite had started. The coder had finished and was waiting on the person to try the app, which they could not open.
Why. On Linux, @anthropic-ai/sandbox-runtime wraps every command in bubblewrap with --unshare-net, so each sandboxed command has its own network namespace and its own loopback. The dev app started by executor.app() in apps/hub/src/builds/posix-sandbox.ts listens at http://127.0.0.1:<CLIENT_PORT> inside its namespace. The live-app host (apps/hub/src/live-app/host.ts, answers(app.url)) and the preview proxy (live-app/proxy.ts) fetch that URL from the hub's namespace, get connection refused, and report "starting" every second forever.
Verified in the Compose hub on 2026-11-02: the hub's /proc/1/ns/net was 4026532382; the live-app host's bun run dev and bun --watch src/index.ts were in 4026532474; the coder sandbox's own dev app was in 4026532739. Nothing in the hub's namespace listened on the app's ports.
The coder's Playwright browser is started by executor.browser() in a separate wrap, so it is in yet another namespace and cannot reach the app either; check-app passes because it starts the server and the browser inside one sandbox. On macOS the Seatbelt sandbox shares the host loopback, which is why this never showed.
Expected. The preview serves the app and the coder's browser can open it, on Linux as on macOS, without weakening the network policy.
Proposed fix. The executor already keeps a socket directory (sockets) that is writable inside every wrap, is bound into them, and that the hub can reach, and on Linux Unix sockets are allowed there (allowAllUnixSockets). Use it as the bridge, the same way the runtime bridges its own proxy ports:
The app's wrap also runs socat UNIX-LISTEN:<sockets>/app.sock,fork,reuseaddr TCP:127.0.0.1:<CLIENT_PORT>, so the app is reachable from outside through the socket.
DevApp carries the socket path; the live-app host's answers() and the proxy's fetch connect through it (Bun's fetch accepts unix), and the proxy's WebSocket relay for Vite HMR does the same.
The browser's wrap runs the reverse relay, socat TCP-LISTEN:<CLIENT_PORT>,fork,reuseaddr UNIX-CONNECT:<sockets>/app.sock, so http://127.0.0.1:<CLIENT_PORT> works inside it too.
Related: #66 (sandbox fixes for the Compose hub), #67 (stale specialist runs).
Fixed on main by #81: the dev app is relayed through a Unix socket between the sandbox's network namespaces, so the hub, the browser and the coder's tools all reach it. The Compose port range that completes the preview is #91.
Activity
brianjfox commentedon Nov 2, 2026
Fixed on main by #81: the dev app is relayed through a Unix socket between the sandbox's network namespaces, so the hub, the browser and the coder's tools all reach it. The Compose port range that completes the preview is #91.