Skip to main content
Use sandbox.commands for foreground and background execution inside a running sandbox. Use shell=True for authored shell snippets. Use args=[...] for exact argv; shell=True cannot be combined with args.

Foreground commands

from nullspace import Sandbox

with Sandbox.create() as sandbox:
    result = sandbox.commands.run(
        "echo $GREETING",
        shell=True,
        envs={"GREETING": "hello"},
        cwd="/workspace",
        timeout=30,
    )
    print(result.stdout.strip(), result.exit_code)
CommandResult includes exit_code, stdout, stderr, and optional pid. Non-zero command exits are returned in exit_code; they are not raised as SDK exceptions.

Background processes

process = sandbox.commands.run("python3 -m http.server 8080", shell=True, background=True)
try:
    print(sandbox.commands.get_logs(process.pid).stdout)
finally:
    process.kill()
    result = process.wait()
    print(result.exit_code)
The returned BackgroundCommand exposes pid, wait(), kill(), get_logs(), disconnect(), and iteration over new stdout/stderr chunks. Pass callbacks with background=True when you want live output while the process keeps running:
process = sandbox.commands.run(
    "python3 -u worker.py",
    shell=True,
    background=True,
    on_stdout=lambda chunk: print(chunk, end=""),
)
process.disconnect()

Streaming

def on_stdout(chunk: str) -> None:
    print(chunk, end="")

result = sandbox.commands.run_streaming(
    "python3 -u script.py",
    shell=True,
    on_stdout=on_stdout,
)
You can also pass on_stdout or on_stderr directly to sandbox.commands.run(...) to use the streaming path. Reconnect to an existing running PID:
handle = sandbox.commands.connect(process.pid, on_stdout=on_stdout)
result = handle.wait()

Stdin and argv

proc = sandbox.commands.run("python3 -i", shell=True, background=True)
sandbox.commands.send_stdin(proc.pid, "print('hello')\n")
sandbox.commands.send_stdin(proc.pid, "exit()\n")

exact = sandbox.commands.run("python3", args=["-c", "print('argv')"])
print(exact.stdout.strip())
Command cwd values must be valid sandbox paths and cannot target runtime-managed paths under /workspace/.nullspace. Process APIs return ProcessInfo(pid, command, running) and CommandLogs(stdout, stderr, output, exit_code).

Async

AsyncSandbox exposes the same commands namespace with awaitable methods:
from nullspace import AsyncSandbox

async with await AsyncSandbox.create() as sandbox:
    result = await sandbox.commands.run("echo async", shell=True)
    print(result.stdout.strip())

    proc = await sandbox.commands.run("sleep 10", shell=True, background=True)
    await proc.kill()

Git helpers

sandbox.git includes first-class helpers for common repository workflows:
sandbox.git.configure_user(
    "Example User",
    "user@example.com",
    scope="local",
    path="/tmp/project",
)
sandbox.git.commit("Update docs", files=["README.md"], path="/tmp/project")
Helpers include clone(), pull(), checkout(), create_branch(), delete_branch(), branches(), add(), commit(), push(), status(), diff(), remote_add(), set_config(), get_config(), configure_user(), add_ssh_key(), and dangerously_authenticate(). commit() uses the repo’s configured Git identity unless you pass author_name and author_email for a one-off commit. Concept: Exec. API reference: execCommand, listProcesses, sendStdin, getProcessLogs, and killProcess.