Module process/index

process/index
Stability: unstable — may still change; see below.

Process information: platform/arch detection, child-process spawning, and exit.

Environment variables, command-line arguments, and current working directory live in std/env.

Stability

unstable, and not because of anything defined here. The last line of this file re-exports ALL of std/process/command — Command, Child, Stdio, ExitStatus and the child pipe handles — so importing std/process imports that surface, and it changed on 2026-09-10 when Child gained take_stdin/take_stdout/take_stderr beside the three bespoke *_stdin/read_*_to_end methods it already had. Two ways into a child's streams is one too many, and which pair survives is not settled. Freezing this module follows command.yo, not its own six members.

Those six are as settled as anything in std: platform/arch and the Platform/Arch constant sets have not changed since the bootstrap and are what every platform cond in std/ and src/ is written against. They report the CFG spellings (macos, x86), deliberately not the target-triple words (apple-darwin, i686) — the split is made explicitly in src/target.yo, see plans/reference/TARGET_TRIPLES.md. New targets add strings additively, but note that Platform/Arch are comptime STRINGS in a struct rather than enum variants, so a cond over them gets no exhaustiveness check and a newly added platform silently takes whatever true => arm is there.

Types

Stdio enum
Stdio

What to do with one of the child's standard streams (plans/archive/STD_API_AUDIT.md §7 P0 item 5).

Variants

VariantFieldsDescription
Inherit

Share the parent's stream (the default).

Piped

Connect a pipe; the parent end is on the returned Child.

Null

Redirect to /dev/null.

Methods
clone : (Stdio) fn(self : &Stdio) -> Stdio

Parameters

NameTypeNotes
selfStdio

Returns: Stdio

Command object
Command

Builder for a child-process invocation.

Construct with Command.new(program), then chain builder methods (arg, args, env, env_clear, stdin, stdout, stderr — each returns Self, and Command is a ref type, so chaining and statement-style calls both work) before status() / output() / spawn().

Fields

NameTypeDescription
_programString
_argsArrayList(String)
_env_overridesArrayList(String)
_env_clearbool
_stdinStdio
_stdoutStdio
_stderrStdio
_cwdOption(String)
Methods
new : (Command) fn(program : &String) -> Command

Create a new Command invoking program. The program name is also used as argv[0] unless a different first arg is pushed manually before invocation.

Parameters

NameTypeNotes
programString

Returns: Command

arg : (Command) fn(self : &Command, a : &String) -> Command

Append a single argument to the argv list.

Parameters

NameTypeNotes
selfCommand
aString

Returns: Command

args : (Command) fn(self : &Command, more : &ArrayList(String)) -> Command

Append multiple arguments to the argv list.

Parameters

NameTypeNotes
selfCommand
moreArrayList(String)

Returns: Command

get_program : (Command) fn(self : &Command) -> String

The program this command will run — Rust's Command::get_program.

Parameters

NameTypeNotes
selfCommand

Returns: String

get_args : (Command) fn(self : &Command) -> ArrayList(String)

The argv list built so far (a copy) — Rust's Command::get_args. The builder's fields are private to std/process/ (member visibility), so this is how a caller reads back what it assembled.

Parameters

NameTypeNotes
selfCommand

Returns: ArrayList(String)

env : (Command) fn(self : &Command, key : &String, value : &String) -> Command

Set an environment variable for the child (overrides an inherited one).

Parameters

NameTypeNotes
selfCommand
keyString
valueString

Returns: Command

current_dir : (Command) fn(self : &Command, dir : &String) -> Command

Run the child with dir as its working directory. POSIX uses posix_spawn_file_actions_addchdir_np (spawn reports ENOSYS on a libc without it — macOS 10.15+/glibc 2.29+/musl 1.2.5+ all have it); Windows passes lpCurrentDirectory.

Parameters

NameTypeNotes
selfCommand
dirString

Returns: Command

env_clear : (Command) fn(self : &Command) -> Command

Stop the child inheriting this process's environment, so it starts from an EMPTY one plus whatever env() supplied — Rust's Command::env_clear.

It does not clear the env() entries already recorded, and Rust's does. This sets a flag that is consulted at spawn time and only suppresses the walk over environ; the overrides are collected separately and always survive. So cmd.env(A, 1).env_clear() runs the child with A=1 here, and with nothing at all in Rust — call order makes no difference in either direction.

With neither this nor any env() call, no envp is constructed at all and the child inherits by the platform's own mechanism.

Parameters

NameTypeNotes
selfCommand

Returns: Command

stdin : (Command) fn(self : &Command, mode : Stdio) -> Command

Configure the child's stdin.

Parameters

NameTypeNotes
selfCommand
modeStdio

Returns: Command

stdout : (Command) fn(self : &Command, mode : Stdio) -> Command

Configure the child's stdout.

Parameters

NameTypeNotes
selfCommand
modeStdio

Returns: Command

stderr : (Command) fn(self : &Command, mode : Stdio) -> Command

Configure the child's stderr.

Parameters

NameTypeNotes
selfCommand
modeStdio

Returns: Command

status : (Command) fn(self : &Command, io : Io) -> Impl(Future(ExitStatus, IoExn))

Spawn the child with stdio inherited from the parent, wait for it to exit, and return its ExitStatus.

Parameters

NameTypeNotes
selfCommand
ioIo

Returns: Impl(Future(ExitStatus, IoExn))

output : (Command) fn(self : &Command, io : Io) -> Impl(Future(Output, IoExn))

Spawn the child with stdout and stderr captured through pipes. Waits for the child to exit and returns the exit status plus the captured bytes.

Parameters

NameTypeNotes
selfCommand
ioIo

Returns: Impl(Future(Output, IoExn))

spawn : (Command) fn(self : &Command, io : Io) -> Impl(Future(Child, IoExn))

Spawn the child WITHOUT waiting. Streams configured Stdio.Piped get pipes whose parent ends live on the returned Child; Inherit shares the parent's stream; Null redirects to /dev/null. Call wait() to reap.

Parameters

NameTypeNotes
selfCommand
ioIo

Returns: Impl(Future(Child, IoExn))

ExitStatus struct
ExitStatus

The result of a finished child process.

Holds the raw waitpid status code along with helpers to extract the exit code and termination signal.

Fields

NameTypeDescription
rawi32

Encoded waitpid status. Use code() / signal() helpers instead of reading this directly when possible.

Methods
clone : (ExitStatus) fn(self : &ExitStatus) -> ExitStatus

Parameters

NameTypeNotes
selfExitStatus

Returns: ExitStatus

code : (ExitStatus) fn(self : ExitStatus) -> Option(i32)

The process exit code (0..255 on Unix), or .None when the process was TERMINATED BY A SIGNAL — a signal death is not an exit code of 0 (plans/archive/STD_API_AUDIT.md §4 process row).

Parameters

NameTypeNotes
selfExitStatus

Returns: Option(i32)

signal : (ExitStatus) fn(self : ExitStatus) -> i32

Returns the signal number that terminated the process, or 0 if the process exited normally.

Parameters

NameTypeNotes
selfExitStatus

Returns: i32

success : (ExitStatus) fn(self : ExitStatus) -> bool

Returns true if the child exited with status code 0.

Parameters

NameTypeNotes
selfExitStatus

Returns: bool

Output object
Output

Captured output of a child process.

Returned by Command.output. Holds the exit status plus the bytes captured from the child's stdout and stderr.

Fields

NameTypeDescription
statusExitStatus

Spawn the child with stdio inherited from the parent, wait for it to exit, and return its ExitStatus.

stdoutArrayList(u8)

Configure the child's stdout.

stderrArrayList(u8)

Configure the child's stderr.

Child struct
Child

A running child process, returned by Command.spawn. Pipe fds exist for the streams configured Stdio.Piped; wait() reaps the child. Dropping a Child closes the pipe ends it still holds but does not wait for it.

A move-only value (its state is a Box): one owner reaps the child, and a copy is E0901. Lend it with &child; its methods take self : &Self and update the pipe ends inside the box, so a Child is never Sync.

Fields

NameTypeDescription
_cellBox(_ChildState)
Methods
_st : (Child) fn(self : &Child) -> *(_ChildState)

The state cell: written through &Child (see the type's doc).

Parameters

NameTypeNotes
selfChild

Returns: *(_ChildState)

pid : (Child) fn(self : &Child) -> i32

The calling process's id (getpid(2); GetCurrentProcessId on Windows). Unique among LIVE processes, so it is the per-process component the test runner puts in its batch artifact names — two concurrent yo test runs over one directory must not overwrite each other's batches (issues/fixed/concurrent-yo-test-runs-in-one-directory-overwrite-each-others-batches.md). The raw C bindings are platform-only (unistd.h has no pid_t under the Windows UCRT), which is why pid lives here rather than at the libc layer.

Parameters

NameTypeNotes
selfChild

Returns: i32

take_stdin : (Child) fn(self : &Child) -> Option(ChildStdin)

Take the parent's write end of the child's stdin pipe as a Writer. .None if stdin was not Stdio.Piped, or if it has already been taken or closed.

Taking MOVES the fd out of the Child: wait() no longer closes it, the returned handle owns it, and write_stdin/close_stdin on this Child throw BadFileDescriptor from then on. Dropping the handle closes the pipe, which is the EOF the child is usually waiting for.

Parameters

NameTypeNotes
selfChild

Returns: Option(ChildStdin)

take_stdout : (Child) fn(self : &Child) -> Option(ChildStdout)

Take the parent's read end of the child's stdout pipe as a Reader, so read_to_string, read_exact and BufReader apply. .None if stdout was not Stdio.Piped, or if it has already been taken.

Taking MOVES the fd out of the Child, exactly as take_stdin does.

Parameters

NameTypeNotes
selfChild

Returns: Option(ChildStdout)

take_stderr : (Child) fn(self : &Child) -> Option(ChildStderr)

Take the parent's read end of the child's stderr pipe as a Reader. .None if stderr was not Stdio.Piped, or if it has already been taken.

Parameters

NameTypeNotes
selfChild

Returns: Option(ChildStderr)

write_stdin : (Child) fn(self : &Child, data : &ArrayList(u8), io : Io) -> Impl(Future(usize, IoExn))

Write bytes into the child's piped stdin. Requires stdin(Stdio.Piped). Throws BadFileDescriptor once take_stdin() has moved the fd out.

Parameters

NameTypeNotes
selfChild
dataArrayList(u8)
ioIo

Returns: Impl(Future(usize, IoExn))

close_stdin : (Child) fn(self : &Child, io : Io) -> Impl(Future(unit, IoExn))

Close the child's stdin pipe — the EOF the child is usually waiting for.

Parameters

NameTypeNotes
selfChild
ioIo

Returns: Impl(Future(unit, IoExn))

read_stdout_to_end : (Child) fn(self : &Child, io : Io) -> Impl(Future(ArrayList(u8), IoExn))

Read the child's piped stdout to EOF. Requires stdout(Stdio.Piped).

Parameters

NameTypeNotes
selfChild
ioIo

Returns: Impl(Future(ArrayList(u8), IoExn))

read_stderr_to_end : (Child) fn(self : &Child, io : Io) -> Impl(Future(ArrayList(u8), IoExn))

Read the child's piped stderr to EOF. Requires stderr(Stdio.Piped).

Parameters

NameTypeNotes
selfChild
ioIo

Returns: Impl(Future(ArrayList(u8), IoExn))

kill : (Child) fn(self : &Child, signum : i32, exn : Exception) -> unit

Send a signal to the child (e.g. 15 = SIGTERM, 9 = SIGKILL). A failure — ESRCH once the child has been reaped, EPERM — is thrown as an IoError through exn, Rust's Child::kill -> io::Result<()>. Until 2026-09-06 this handed back the raw -errno as an i32 (issues/fixed/child-kill-returned-a-raw-errno.md).

Parameters

NameTypeNotes
selfChild
signumi32
exnException

Returns: unit

wait : (Child) fn(self : &Child, io : Io) -> Impl(Future(ExitStatus, IoExn))

Wait for the child to exit and return its status. Closes any pipe fds still open on this handle.

Parameters

NameTypeNotes
selfChild
ioIo

Returns: Impl(Future(ExitStatus, IoExn))

ChildStdin struct
ChildStdin

The parent's write end of a child's stdin pipe — a Writer, so write_all, write_string and the rest of std/io's writer surface work on it. Take it off a Child with take_stdin(); closing it (explicitly, or by dropping it) is the EOF the child is usually waiting for. A move-only value: the handle owns the fd.

Fields

NameTypeDescription
_cellBox(_PipeEnd)
Methods
fd : (ChildStdin) fn(self : &ChildStdin) -> i32

The underlying file descriptor.

Parameters

NameTypeNotes
selfChildStdin

Returns: i32

is_closed : (ChildStdin) fn(self : &ChildStdin) -> bool

Whether the handle has been closed.

Parameters

NameTypeNotes
selfChildStdin

Returns: bool

close : (ChildStdin) fn(self : &ChildStdin, io : Io) -> Impl(Future(unit, IoExn))

Close the write end — the child sees EOF. Safe to call multiple times.

Parameters

NameTypeNotes
selfChildStdin
ioIo

Returns: Impl(Future(unit, IoExn))

write : (ChildStdin) fn(self : &ChildStdin, buf : *(u8), size : usize, io : Io) -> Impl(Future(usize, IoExn))

Write up to size bytes. Returns the number written. The future borrows the handle, so the fd cannot be closed under it.

Parameters

NameTypeNotes
selfChildStdin
buf*(u8)
sizeusize
ioIo

Returns: Impl(Future(usize, IoExn))

flush : (ChildStdin) fn(self : &ChildStdin, io : Io) -> Impl(Future(unit, IoExn))

A no-op that always succeeds: a pipe write goes straight to the kernel, so there is nothing held here to push. Everything write reported as written is already visible to the child, and flushing is NOT what delivers EOF — close (or dropping the handle) is.

Parameters

NameTypeNotes
selfChildStdin
ioIo

Returns: Impl(Future(unit, IoExn))

write_all : (ChildStdin) fn(self : &ChildStdin, buf : *(u8), size : usize, io : Io) -> Impl(Future(unit, IoExn))

Parameters

NameTypeNotes
selfChildStdin
buf*(u8)
sizeusize
ioIo

Returns: Impl(Future(unit, IoExn))

write_string : (ChildStdin) fn(self : &ChildStdin, data : &String, io : Io) -> Impl(Future(usize, IoExn))

Write a String, in full. File.write_string spells the same convenience.

Parameters

NameTypeNotes
selfChildStdin
dataString
ioIo

Returns: Impl(Future(usize, IoExn))

ChildStdout struct
ChildStdout

The parent's read end of a child's stdout pipe — a Reader, so read_to_end, read_to_string, read_exact and BufReader work on it. Take it off a Child with take_stdout(). A move-only value, as ChildStdin is.

Fields

NameTypeDescription
_cellBox(_PipeEnd)
Methods
fd : (ChildStdout) fn(self : &ChildStdout) -> i32

The underlying file descriptor.

Parameters

NameTypeNotes
selfChildStdout

Returns: i32

is_closed : (ChildStdout) fn(self : &ChildStdout) -> bool

Whether the handle has been closed.

Parameters

NameTypeNotes
selfChildStdout

Returns: bool

close : (ChildStdout) fn(self : &ChildStdout, io : Io) -> Impl(Future(unit, IoExn))

Close the read end. Safe to call multiple times.

Parameters

NameTypeNotes
selfChildStdout
ioIo

Returns: Impl(Future(unit, IoExn))

read : (ChildStdout) fn(self : &ChildStdout, buf : *(u8), size : usize, io : Io) -> Impl(Future(usize, IoExn))

Read up to size bytes. Returns the number read; 0 means EOF. The future borrows the handle, so the fd cannot be closed under it.

Parameters

NameTypeNotes
selfChildStdout
buf*(u8)
sizeusize
ioIo

Returns: Impl(Future(usize, IoExn))

read_to_end : (ChildStdout) fn(self : &ChildStdout, io : Io) -> Impl(Future(ArrayList(u8), IoExn))

Parameters

NameTypeNotes
selfChildStdout
ioIo

Returns: Impl(Future(ArrayList(u8), IoExn))

read_to_string : (ChildStdout) fn(self : &ChildStdout, io : Io) -> Impl(Future(String, IoExn))

Parameters

NameTypeNotes
selfChildStdout
ioIo

Returns: Impl(Future(String, IoExn))

ChildStderr struct
ChildStderr

The parent's read end of a child's stderr pipe. Structurally identical to ChildStdout and distinct for the same reason Rust keeps them apart: the type says which stream you are holding.

Fields

NameTypeDescription
_cellBox(_PipeEnd)
Methods
fd : (ChildStderr) fn(self : &ChildStderr) -> i32

The underlying file descriptor.

Parameters

NameTypeNotes
selfChildStderr

Returns: i32

is_closed : (ChildStderr) fn(self : &ChildStderr) -> bool

Whether the handle has been closed.

Parameters

NameTypeNotes
selfChildStderr

Returns: bool

close : (ChildStderr) fn(self : &ChildStderr, io : Io) -> Impl(Future(unit, IoExn))

Close the read end. Safe to call multiple times.

Parameters

NameTypeNotes
selfChildStderr
ioIo

Returns: Impl(Future(unit, IoExn))

read : (ChildStderr) fn(self : &ChildStderr, buf : *(u8), size : usize, io : Io) -> Impl(Future(usize, IoExn))

Read up to size bytes. Returns the number read; 0 means EOF. The future borrows the handle, so the fd cannot be closed under it.

Parameters

NameTypeNotes
selfChildStderr
buf*(u8)
sizeusize
ioIo

Returns: Impl(Future(usize, IoExn))

read_to_end : (ChildStderr) fn(self : &ChildStderr, io : Io) -> Impl(Future(ArrayList(u8), IoExn))

Parameters

NameTypeNotes
selfChildStderr
ioIo

Returns: Impl(Future(ArrayList(u8), IoExn))

read_to_string : (ChildStderr) fn(self : &ChildStderr, io : Io) -> Impl(Future(String, IoExn))

Parameters

NameTypeNotes
selfChildStderr
ioIo

Returns: Impl(Future(String, IoExn))

Functions

exit function
fn(code : usize) -> never

Exit the process with the given status code.

Parameters

NameTypeNotes
codeusize

Returns: never

pid function
fn() -> u32

The calling process's id (getpid(2); GetCurrentProcessId on Windows). Unique among LIVE processes, so it is the per-process component the test runner puts in its batch artifact names — two concurrent yo test runs over one directory must not overwrite each other's batches (issues/fixed/concurrent-yo-test-runs-in-one-directory-overwrite-each-others-batches.md). The raw C bindings are platform-only (unistd.h has no pid_t under the Windows UCRT), which is why pid lives here rather than at the libc layer.

Returns: u32

Constants

platform constant comptime_str

Current target platform as a compile-time string. One of: "linux", "macos", "windows", "freebsd", "emscripten", "wasi".

Value: "linux"

Platform constant <struct:struct_process__index_Platform_r0c12_n0>

Platform constants for compile-time platform comparisons.

Value: struct_process__index_Platform_r0c12_n0(Linux: "linux", Macos: "macos", Windows: "windows", FreeBSD: "freebsd", Emscripten: "emscripten", Wasi: "wasi")

arch constant comptime_str

Current target architecture as a compile-time string. One of: "x86_64", "aarch64", "x86", "arm", "wasm32".

Value: "x86_64"

Arch constant <struct:struct_process__index_Arch_r0c8_n0>

Architecture constants for compile-time architecture comparisons.

Value: struct_process__index_Arch_r0c8_n0(X86_64: "x86_64", Aarch64: "aarch64", X86: "x86", Arm: "arm", Wasm32: "wasm32")