Runtime And Web

std.proc

Host process status helpers behind explicit process capability boundaries.

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:

APIReturnNotes
std.proc.spawn(command)ProcStatusRuns an argv-style command with inherited stdio through the explicit proc capability surface and returns its status.
std.proc.spawnInherit(command)ProcStatusRuns an argv-style command while inheriting stdin, stdout, and stderr from the parent process.
std.proc.spawnInheritArgs(program, args, cwd, env)ProcStatusRuns 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)i32Reads the process status code.
std.proc.succeeded(status)BoolReports whether the status exit code is 0.
std.proc.failed(status)BoolReports whether the status exit code is nonzero.
std.proc.runOk(command)BoolSpawns a hosted command and reports whether the resulting status succeeded.
std.proc.runCode(command)i32Spawns 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)ProcStatusRuns 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)ProcStatusRuns a program path plus newline-separated argv entries and redirects stdout and stderr to hosted paths.
std.proc.spawnChild(command)ProcChildStarts 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)ProcChildStarts 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)ProcChildStarts 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)ProcChildStarts 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)BoolReports whether the handle currently names an open child slot.
std.proc.running(child)BoolPolls the child process without blocking.
std.proc.wait(child)ProcStatusWaits for process exit and returns its status.
std.proc.kill(child)BoolSends the child a termination signal on supported hosts.
std.proc.interrupt(child)BoolSends the child an interrupt signal on supported hosts.
std.proc.close(child)BoolCloses the handle and any remaining pipes.
std.proc.closeStdin(child)BoolCloses the child stdin pipe while keeping stdout, stderr, and status available.
std.proc.pid(child)i32Returns the hosted process id for a child handle, or 0 when unavailable.
std.proc.pidRunning(pid)BoolReports whether a hosted process id appears to be running.
std.proc.killPid(pid)BoolSends a termination signal to a hosted process id on supported hosts.
std.proc.interruptPid(pid)BoolSends an interrupt signal to a hosted process id on supported hosts.
std.proc.killGroupPid(pid)BoolSends a termination signal to the hosted process group whose id is pid on supported hosts.
std.proc.interruptGroupPid(pid)BoolSends 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 wait drains stdout, stderr, or PTY output
  • target support: hosted targets with the proc capability
  • error behavior: spawn, spawnInherit, captureFiles, and wait return ProcStatus; exitCode is infallible; capture and child I/O helpers return null when they cannot produce a complete result
  • ownership notes: ProcChild values name runtime-owned process slots; call wait when process status matters and close when 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.