When To Use std.proc
In Zerolang, use std.proc for hosted process helpers behind explicit process
capability boundaries. The surface is host-only and supports both status-style
helpers and owned child handles for incremental I/O.
Runnable today:
| API | Return | Notes |
|---|---|---|
std.proc.spawn(command) | ProcStatus | Runs an argv-style command with inherited stdio through the explicit proc capability surface and returns its status. |
std.proc.spawnInherit(command) | ProcStatus | Runs an argv-style command while inheriting stdin, stdout, and stderr from the parent process. |
std.proc.spawnInheritArgs(program, args, cwd, env) | ProcStatus | Runs a program path plus newline-separated argv entries while inheriting stdio, using a working directory and newline-separated KEY=value environment bindings. |
std.proc.exitCode(status) | i32 | Reads the process status code. |
std.proc.succeeded(status) | Bool | Reports whether the status exit code is 0. |
std.proc.failed(status) | Bool | Reports whether the status exit code is nonzero. |
std.proc.runOk(command) | Bool | Spawns a hosted command and reports whether the resulting status succeeded. |
std.proc.runCode(command) | i32 | Spawns a hosted command and returns its exit code. |
std.proc.capture(command, buffer) | Maybe<usize> | Runs an argv-style command and captures stdout into caller storage. Returns null on parse failure, spawn failure, nonzero exit, unsupported target, or output truncation. |
std.proc.captureArgs(program, args, buffer) | Maybe<usize> | Runs a program path plus newline-separated argv entries and captures stdout into caller storage. |
std.proc.captureFiles(command, stdoutPath, stderrPath) | ProcStatus | Runs an argv-style command and writes stdout and stderr to hosted paths. Returns 127 when the command cannot be parsed, spawned, waited on, or the output files cannot be opened. |
std.proc.captureFilesArgs(program, args, stdoutPath, stderrPath) | ProcStatus | Runs a program path plus newline-separated argv entries and redirects stdout and stderr to hosted paths. |
std.proc.spawnChild(command) | ProcChild | Starts a hosted child process with piped stdin, stdout, and stderr. Returns an invalid handle when the process cannot be created. |
std.proc.spawnChildIn(command, cwd) | ProcChild | Starts a hosted child process in a working directory with piped stdin, stdout, and stderr. Returns an invalid handle when the cwd is invalid or the process cannot be created. |
std.proc.spawnChildInEnv(command, cwd, env) | ProcChild | Starts a hosted child process in a working directory with piped stdin/stdout/stderr and explicit newline-separated KEY=value environment bindings. |
std.proc.spawnChildArgs(program, args, cwd, env) | ProcChild | Starts a hosted child process from a program path plus newline-separated argv entries, working directory, and newline-separated KEY=value environment bindings. |
std.proc.childValid(child) | Bool | Reports whether the handle currently names an open child slot. |
std.proc.running(child) | Bool | Polls the child process without blocking. |
std.proc.wait(child) | ProcStatus | Waits for process exit and returns its status. |
std.proc.kill(child) | Bool | Sends the child a termination signal on supported hosts. |
std.proc.interrupt(child) | Bool | Sends the child an interrupt signal on supported hosts. |
std.proc.close(child) | Bool | Closes the handle and any remaining pipes. |
std.proc.closeStdin(child) | Bool | Closes the child stdin pipe while keeping stdout, stderr, and status available. |
std.proc.pid(child) | i32 | Returns the hosted process id for a child handle, or 0 when unavailable. |
std.proc.pidRunning(pid) | Bool | Reports whether a hosted process id appears to be running. |
std.proc.killPid(pid) | Bool | Sends a termination signal to a hosted process id on supported hosts. |
std.proc.interruptPid(pid) | Bool | Sends an interrupt signal to a hosted process id on supported hosts. |
std.proc.killGroupPid(pid) | Bool | Sends a termination signal to the hosted process group whose id is pid on supported hosts. |
std.proc.interruptGroupPid(pid) | Bool | Sends an interrupt signal to the hosted process group whose id is pid on supported hosts. |
std.proc.readStdout(child, buffer) | Maybe<usize> | Nonblocking read from the child's stdout pipe into caller storage. Returns null when no bytes are currently available or the stream is closed. |
std.proc.readStderr(child, buffer) | Maybe<usize> | Nonblocking read from the child's stderr pipe into caller storage. Returns null when no bytes are currently available or the stream is closed. |
std.proc.writeStdin(child, bytes) | Maybe<usize> | Nonblocking write to the child's stdin pipe. Returns null when the stream is not writable. |
Metadata labels:
- effects: proc
- allocation behavior: child handles may keep runtime-owned pipe buffers while
waitdrains stdout, stderr, or PTY output - target support: hosted targets with the
proccapability - error behavior:
spawn,spawnInherit,captureFiles, andwaitreturnProcStatus;exitCodeis infallible;captureand child I/O helpers returnnullwhen they cannot produce a complete result - ownership notes:
ProcChildvalues name runtime-owned process slots; callwaitwhen process status matters andclosewhen the handle is no longer needed - example:
examples/std-platform.graph
Example
pub fn main(world: World) -> Void raises { let status: ProcStatus = std.proc.spawn("zero-noop") var storage: [64]u8 = [0_u8; 64] let captured: Maybe<usize> = std.proc.capture("printf proc-capture", storage) let files: ProcStatus = std.proc.captureFiles("sh -c 'printf proc-out; printf proc-err >&2'", ".zero/proc.out", ".zero/proc.err") if std.proc.succeeded(status) && std.proc.succeeded(files) && std.proc.runOk("sh -c true") && std.proc.runCode("sh -c true") == 0 && captured.has { check world.out.write("proc ok\n") }}Incremental child I/O uses caller-owned buffers:
pub fn main(world: World) -> Void raises { let child: ProcChild = std.proc.spawnChild("zero-noop") var stdoutStorage: [64]u8 = [0_u8; 64] let out: Maybe<usize> = std.proc.readStdout(child, stdoutStorage) if out.has { check world.out.write("child stdout available\n") } let pid: i32 = std.proc.pid(child) let status: ProcStatus = std.proc.wait(child) let closed: Bool = std.proc.close(child) if pid > 0 && std.proc.succeeded(status) && closed { check world.out.write("child ok\n") }}Design Notes
std.proc requires a hosted target that advertises the proc capability.
Targets without process support, including Windows hosts until their process
runtime is implemented, must reject process helpers before code generation.
They should not compile a placeholder process implementation.
capture and captureFiles do not invoke a shell. They split simple
argv-style command text and support quoted arguments. capture captures stdout
only into caller storage. captureFiles redirects stdout and stderr to
separate hosted paths.
spawnInherit uses the same argv-style parser and leaves stdin, stdout, and
stderr connected to the parent process. spawnInheritArgs uses an explicit
program plus newline-separated argv entries, working directory, and environment
block. Use inherited stdio for editor, pager, and terminal program launches
where captured pipes would be the wrong interface.
Child handles use the same command parser when created from command text. The
*Args helpers avoid command-text parsing: program is argv[0], and each
non-empty line in args becomes one following argv entry with spaces preserved.
captureArgs captures stdout into caller storage, captureFilesArgs redirects
stdout and stderr to hosted paths, and spawnChildArgs returns nonblocking
pipes so event loops can poll process state and terminal input without owning
threads. wait drains child output into the handle before reaping so post-wait
readStdout and readStderr calls can still consume buffered data.
Hosted child helpers start children in their own process group where the target
platform supports it. Use killGroupPid or interruptGroupPid when a stored
pid should stop a command tree instead of only the direct parent process.
spawnChildInEnv, spawnInheritArgs, and spawnChildArgs accept a
newline-separated env block such as "TOKEN=...\nMODE=batch". Empty lines are
ignored. Invalid entries or oversized env blocks make the helper fail: status
helpers return an error status and child helpers return an invalid handle.