Skip to main content
exec runs one shell command in a sandbox and returns its stdout, stderr, and exit code in a single response. Use it for commands that finish within the 60-second default timeout_seconds and print under 512 KiB per stream. Before You Begin: BOXROUTER_API_KEY set and a client installed, as in the quickstart.

Choose How to Run It

Run It and Read the Result

exec returns stdout, stderr, and exit_code. This example runs echo hello and prints the output and the exit code. The command runs once, as Bash source, in a login shell.
The HTTP example needs curl 7.76 or later and jq. Leaving the Python with block, the TypeScript finally, or the HTTP trap requests deletion; it does not confirm it. Recover from Errors covers a deletion that stays pending.

A Nonzero Exit Is a Result

A command that exits nonzero is a completed result, not an error. The call succeeds and exit_code carries the status. This command writes to stderr and exits with 3.
A nonzero CLI status can also mean a client or API error, so read stderr before you treat it as the command’s exit status. A failed request raises APIError in the SDKs. To decide whether a failed call ran, read the error’s outcome (Recover from Errors). To raise on a nonzero exit instead, see Stop on Failure.

Options

This example sets cwd and env for one command.
Every result carries stdout_truncated and stderr_truncated. Output over the limit is not an error: the result holds the first output_limit_bytes of that stream, and the matching flag is true. To get all of the output, run the command as a process. A request that sets output_limit_bytes above 524288 is rejected with outcome: not_started, so the command did not run. A 413 output_limit error with outcome: unknown means the output was too large to deliver. The command may have run, so check its effects before you retry.

Stop on Failure

Pass check=True ({ check: true } in TypeScript) to raise CommandFailed when the command exits nonzero or times out. The error carries exit_code, stdout, stderr, and timed_out.
Without check, the same call returns the result and raises nothing.

When a Command Runs Too Long

When timeout_seconds runs out, BoxRouter sends TERM to the command’s process group, then KILL 5 seconds later. The call still succeeds: the result has timed_out set to true, exit_code set to null, and the output the command wrote before it was ended. This command prints one line, then sleeps past its 3-second deadline.
The CLI exits with status 124 and prints Command timed out; the output it wrote is above. on stderr. The sandbox keeps running. A child that left the group, such as a daemon started with setsid, is not ended. A 504 timeout with outcome: unknown is rare. It means BoxRouter lost track of the command and cannot say whether it ran, so check its effects before you resend it. Lifecycle compares the timeout with the other clocks. A command’s stdin is empty. Run a command lists every field and the guarantees on each route.

Custom Image Requirements

To enforce the deadline and capture the streams, BoxRouter wraps each command using shell tools. A custom image must contain them. What the image must contain lists them. Image preparation does not check for these tools, so the failure appears when you run a command: 422 unsupported_feature, with details.prerequisite naming the missing tool when known. outcome is always not_started: the command never began. Rebuild the image, then run the command again.

Next Steps

Run a Background Process

Run long jobs and servers, and read output as it grows.

Work with Files

Move files in and out of a sandbox.

Recover from Errors

Tell whether a failed call ran before you resend it.