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
- The CLI reports "CloudCLI is ready!" and opens the browser.
- The WebUI at http://127.0.0.1:8080/ immediately shows "Offline — Please check your connection."
- Checking processes inside the sandbox confirms no server is running:
sbx exec my-project bash -c 'pgrep -fa node || echo "PROCESS DEAD"'
→ PROCESS DEAD
- 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
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
sbx exec my-project bash -c 'pgrep -fa node || echo "PROCESS DEAD"'
→ PROCESS DEAD
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']);
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