Skip to main content
Execute and manage processes in your sandboxes with Blaxel SDK. Run shell commands, retrieve process information, and control process execution.
Complete code examples demonstrating all operations are available on Blaxel’s GitHub: in TypeScript, in Python, and in Go.

Execute processes and commands

The Blaxel SDK requires two environment variables to authenticate:You can create an API key from the Blaxel console. Your workspace name is visible in the URL when you log in to the console (e.g. app.blaxel.ai/{workspace}).Set them as environment variables or add them to a .env file at the root of your project:
The Blaxel SDK does not accept credentials as constructor arguments. Credentials must come from environment variables, a .env file, or a local CLI login session (see below).When developing locally, you can also log in to your workspace with Blaxel CLI (as shown above). This allows you to run Blaxel SDK functions that will automatically connect to your workspace without additional setup. When you deploy on Blaxel, authentication is handled automatically — no environment variables needed.

Execute command

Execute shell commands:
By default, exec returns after starting the process without waiting for it to finish. Its output may not be available yet.

Get command output

Set waitForCompletion: true ("wait_for_completion": True in Python) to wait for the command to finish. The result then holds its stdout, stderr, and exitCode (exit_code in Python):
The logs field holds stdout and stderr together. A command that exits with a non-zero code does not raise an error: its status is failed, so check the exit code. Set timeout to bound how long the call waits. For longer commands, see Wait for process completion. Process execution logs are also visible in the Blaxel Console. Refer to the Logs section of the sandbox detail page, as shown below: process logs

Set the working directory

Set the working directory for subsequent commands:
workingDir is a JSON request-body field, not a URL path. Pass a normal absolute filesystem path such as "/workspace"; do not URL-encode it as "%2Fworkspace". In Python, the equivalent field is working_dir.

Use process names

When starting a process (running a command), you can specify a process name. This lets you interact with the process—such as retrieving logs or process information—without needing to store the process ID on your end.
You can use either the process name or the process ID to get information about the process:
The exit code of the process is available in the exitCode parameter (exit_code in Python) of the process execution object returned by the process.exec and process.get methods. You can also use the process ID or name to retrieve logs of your processes.

Kill process

Kill a process immediately by running:

Long-running processes

Blaxel Sandboxes are great for long-running processes. Processes you launch detach by design: their stdout and stderr are redirected to files and the process is monitored by background workers in the sandbox, so it survives independently of your client connection. By default, the general sandbox lifecycle rules still apply: the sandbox only stays awake while a connection is maintained and will suspend after a few seconds of inactivity. Use keepAlive to override this for the duration of a process. Two independent flags let you tune how the behavior works.
  • waitForCompletion (default: false) controls only whether the SDK call blocks until the process exits and returns its output. It has no effect on the process or sandbox lifetime.
  • keepAlive (default: none) controls only whether the sandbox stays awake (auto-standby/scale-to-zero disabled) while the process runs, even with no active client connection. A counter tracks running keepAlive processes and is decremented automatically when each one completes, letting the sandbox return to standby on its own. See Sandbox keep-alive for details.

Wait for process completion

You can wait for process completion when executing it:
When waiting for completion, the process execution object contains the command’s output: stdout, stderr, and both combined in logs. Also, notice the timeout parameter which allows you to set the process timeout duration in seconds.
When using waitForCompletion, Blaxel enforces a timeout limit of 60 seconds. Don’t set your timeout longer than this. For longer waiting periods, use the process-watching option described below.
For processes without keepAlive: true, the timeout parameter does not kill the process. It only bounds how long the API call waits when using waitForCompletion (or waitForPorts); once the timeout elapses, an error is returned but the process keeps running in the background. Non-keepAlive processes have no auto-kill timeout and run until they complete on their own. To auto-kill a process after a duration, use keepAlive: true together with a timeout (see Sandbox keep-alive).
You can also wait for a process after it has started:
Set a long completion duration if your process is expected to take longer.

Wait for ports

In some cases, you may want to wait for a port to be opened while running — for example if you are running npm run dev and want to wait for port 3000 to be open. exec returns as soon as the ports are open, and the process keeps running in the background.
A port counts as open once the server listens on the address in HOST (or on all interfaces). A server bound only to localhost isn’t reachable from outside the sandbox, so it doesn’t count. timeout bounds how long the call waits for the ports. Keep it under 120 seconds: a request that stays open that long is cut off by the gateway with a 504 error instead of the timeout error. If the process fails before its ports open (it exits with a non-zero code or is killed), the call fails right away instead of waiting out the timeout. The error includes the exit code and the last lines of the process’s output:
Don’t end the command with &. The shell exits straight away and the server it put in the background isn’t tracked as part of the process, so the call waits until timeout and a startup crash isn’t reported. Failing fast needs sandbox-api 0.2.62 or later; custom images pick it up when rebuilt.

Process stdin

By default, a process has no stdin: it reads end-of-file as soon as it starts. Start it with stdin: true to give it a writable pipe, then send input with writeStdin and close the pipe with closeStdin. Use this to drive programs that read from stdin, such as stdio MCP servers and other JSON-RPC programs. The pipe passes your bytes through unchanged. Unlike the interactive terminal, there is no TTY in between, so nothing is echoed back or rewritten.
Process stdin needs @blaxel/core 0.3.19 or later in TypeScript, blaxel 0.4.9 or later in Python, and sandbox-api 0.2.56 or later in the sandbox. Custom images pick it up when rebuilt.

Write to a process

Start the process with a name and stdin: true, write to it, then close stdin to send end-of-file:
writeStdin (write_stdin in Python) takes a string or bytes and writes them as is, so include the trailing newline your program expects. closeStdin (close_stdin in Python) can be called more than once.

Run a stdio MCP server

A stdio MCP server reads JSON-RPC messages from stdin and writes one reply per line to stdout. Send each message with writeStdin, and read the replies by streaming the process’s stdout:
The first npx run downloads the server package, so the first reply can take several seconds.

Stdin errors and restarts

Sequential writes keep their order, and two concurrent writes never mix inside a message. The SDK does not retry a failed write, since a duplicate would corrupt the stream. A write fails with:
  • 409 if the process was started without stdin: true, or its stdin is closed
  • 413 if the data is larger than 8 MiB
  • 503 if the process stopped reading and the pipe stayed full for 10 seconds
After a 503, part of the data may have gone through, so restart the process. The pipe survives sandbox standby and resume. With restartOnFailure, each restart gets a new pipe, and data written between the failure and the restart is lost. If the sandbox API itself restarts, the process reads end-of-file and writes fail with 409: restart the process and redo your protocol’s handshake. Over the Sandbox API, start the process with "stdin": true on POST /process, then write to its stdin with POST /process/{identifier}/stdin and the raw bytes as the request body, and close its stdin with DELETE /process/{identifier}/stdin.

Auto-restart

Restart process on failure

You can restart a process if it fails, up to a maximum number of restart attempts:

Sandbox keep-alive

By default, sandboxes automatically switch to standby when there is no active connection to save resources. However, it is possible to adjust this behavior and keep the sandbox running when you launch a process, even if there isn’t an active connection to it. This is typically used to keep a long-running task actively running within the sandbox environment even when it is not serving requests. You can include additional keep-alive metadata when launching a new process:
The auto-kill timeout and its 600-second default only apply to processes started with keepAlive: true. If a keepAlive process is started without a timeout, it defaults to 600 seconds (10 minutes) and is automatically terminated when the timeout elapses. To run a keepAlive process indefinitely with no auto-kill, set timeout: 0. The table below summarizes how keepAlive and timeout interact: You can run multiple processes, and the sandbox will stay active until all of them complete:

Disable process telemetry logging

By default, process stdout and stderr are exported as structured telemetry logs (visible in external observability systems). You can disable this telemetry export by setting the SANDBOX_DISABLE_PROCESS_LOGGING environment variable inside the sandbox. When set to true or 1, structured telemetry output is suppressed for all processes. File-based logging and real-time log streaming via the SDK remain fully functional and are not affected. Set this variable in your Dockerfile or at sandbox creation time:
Alternatively, you can disable process logging for sandboxes at workspace level using the Blaxel Console, in the Workspace settings section. Disable process logging
This only suppresses the structured telemetry export. You can still retrieve process logs via the SDK’s process.logs() method and stream them in real-time.

Process statuses

A process can have any of the following statuses:
  • running
  • completed
  • failed
  • killed
  • stopped
Last modified on October 5, 2026