Skip to content

bhatti exec

Execute a command inside a sandbox. The exit code of the child process is forwarded to the CLI's exit code. Sleeping sandboxes wake automatically.

Synopsis

bhatti exec <sandbox> [--] <command...> [flags]

Description

The -- separator is optional — bhatti exec dev echo hello works just like bhatti exec dev -- echo hello. Use -- only when the command contains flags that cobra would otherwise try to parse (e.g. bhatti exec dev -- ls -la /tmp).

Commands run as the unprivileged user lohar (uid 1000), not root. Use sudo inside the sandbox for root operations. Stdout and stderr are kept on separate streams; when output is captured, the result distinguishes them.

Output mode auto-detects:

  • Stdout is a TTY → streaming NDJSON, line-by-line, flushed as the process emits it. You see npm install's progress bar in real time.
  • Stdout is a pipe or --json is set → buffered. The CLI prints a JSON object {exit_code, stdout, stderr} once the command finishes.
  • BHATTI_FORCE_STREAM=1 → forces streaming even when piping. Useful for CI logs that want progressive output.

Cold sandboxes wake transparently. If the sandbox is cold or warm, the server resumes it before executing — typically ~50ms for cold, sub-millisecond for warm. The wake is invisible to the caller; the command just takes a bit longer.

Failures get recovery hints. Common errors (sandbox not found, sandbox not running, name conflict, quota reached) are followed by a one-line suggestion in stderr. For example:

404 Not Found: sandbox not found

  Check sandbox name:
    bhatti ls

Examples

# Most basic
bhatti exec dev -- echo hello
# -- is optional
bhatti exec dev echo hello
# Pipe output to other tools — CLI switches to buffered mode automatically
bhatti exec dev -- cat /workspace/data.json | jq .name
# Shell expansion needs a shell — env vars in the *guest*, not in your terminal
bhatti exec dev -- bash -c 'echo $API_KEY'
# Cap a long-running command at 60s
bhatti exec dev --timeout 60 -- ./benchmark.sh
# Run in the background, return immediately with the guest PID
bhatti exec dev --detach -- ./worker.sh
pid: 4218
output: /var/log/lohar/sessions/sess-7b3c.log

Options

| Flag | Default | Description | | ---- | ------- | ----------- | | --timeout <int> | 300 | Exec timeout in seconds. The server kills the process group on timeout and returns exit code 137. Hard max: 86400 (24 hours). | | --detach | false | Run the command in the background and return immediately with the guest PID and the path to the captured output file. The session continues until it finishes or is killed. |

See Global flags for --url, --token, --json, --timing, --data-dir.

Exit codes

| Code | Meaning | | ---- | ------- | | <n> | The child process's exit code is forwarded verbatim. | | 137 | The child was killed (timeout exceeded, or session manually killed). | | 1 | CLI / API error before the command ran (sandbox not found, network, auth). |

See also