Execute processes and commands
Learn more about authentication on Blaxel
Learn more about authentication on Blaxel
The Blaxel SDK requires two environment variables to authenticate:The Blaxel SDK does not accept credentials as constructor arguments. Credentials must come from environment variables, a
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:.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:exec returns after starting the process without waiting for it to finish. Its output may not be available yet.
Get command output
SetwaitForCompletion: 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):
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:

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.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: theirstdout 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 runningkeepAliveprocesses 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:stdout, stderr, and both combined in logs. Also, notice the timeout parameter which allows you to set the process timeout duration in seconds.
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).Wait for ports
In some cases, you may want to wait for a port to be opened while running — for example if you are runningnpm 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.
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 withstdin: 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 andstdin: 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 withwriteStdin, and read the replies by streaming the process’s stdout:
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:409if the process was started withoutstdin: true, or its stdin is closed413if the data is larger than 8 MiB503if the process stopped reading and the pipe stayed full for 10 seconds
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: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 theSANDBOX_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:

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:runningcompletedfailedkilledstopped