Skip to content

cloudcli sandbox: WebUI shows "Offline" immediately after launch — server process killed when sbx exec exits #791

@NoahHahm

Description

@NoahHahm

Summary

Running cloudcli sandbox or cloudcli sandbox start results in the WebUI at http://127.0.0.1:/ showing "Offline — Please check your connection." immediately or shortly after launch,
even though the sandbox container is running and port forwarding is active.

The root cause is that cloudcli is started inside the sandbox using a bare & background operator with no nohup or disown. When sbx exec terminates its session, the shell sends SIGHUP to all background jobs,
killing the server process instantly.


Steps to Reproduce

cloudcli sandbox ~/my-project --port 8080
or
cloudcli sandbox start my-project

  1. The CLI reports "CloudCLI is ready!" and opens the browser.
  2. The WebUI at http://127.0.0.1:8080/ immediately shows "Offline — Please check your connection."
  3. Checking processes inside the sandbox confirms no server is running:
    sbx exec my-project bash -c 'pgrep -fa node || echo "PROCESS DEAD"'
    → PROCESS DEAD
  4. No log file exists at /tmp/cloudcli-ui.log.

Root Cause

server/cli.js, create case (line 557) and start case (line 458):

// Before (broken)
sbx(['exec', opts.name, 'bash', '-c', 'cloudcli start --port 3001 &']);

sbx exec creates a new session and runs bash -c '...'. The & operator backgrounds the cloudcli process, but bash -c exits immediately after spawning it. When sbx exec tears down that session, the shell sends
SIGHUP to all background jobs — killing cloudcli before it can serve a single request.

Verified reproduction:
Replicating exactly what cli.js does:
sbx exec sandbox bash -c 'cloudcli start --port 3001 &'
sleep 3
sbx exec sandbox bash -c 'pgrep -fa node || echo "PROCESS DEAD"'
→ PROCESS DEAD

With the fix applied:

sbx exec sandbox bash -c 'nohup cloudcli start --port 3001 > /tmp/cloudcli-ui.log 2>&1 & disown'
sleep 3
sbx exec sandbox bash -c 'pgrep -fa node || echo "PROCESS DEAD"'
→ 1555 node /usr/local/share/npm-global/bin/cloudcli start --port 3001


Fix

Add nohup and disown so the server process is fully detached from the sbx exec session:

// After (fixed) — both create and start cases
sbx(['exec', opts.name, 'bash', '-c', 'nohup cloudcli start --port 3001 > /tmp/cloudcli-ui.log 2>&1 & disown']);

  • nohup — prevents SIGHUP from reaching the process when the controlling terminal/session ends.
  • disown — removes the process from the shell's job table so it is not signalled on shell exit.
  • /tmp/cloudcli-ui.log 2>&1 — ensures logs are always written (required for cloudcli sandbox logs to work).

This pattern is already used correctly in docker/shared/start-cloudcli.sh:
nohup cloudcli start --port 3001 > /tmp/cloudcli-ui.log 2>&1 &
disown


Environment

  • cloudcli version: 1.31.2 / 1.32.0
  • sbx CLI version: v0.30.0
  • OS: macOS (Darwin 25.3.0)
  • Sandbox template: docker.io/cloudcliai/sandbox:claude-code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions