Exec Module
Top-level conveniences: run a program by name (without first building a `Command`), and run a whole batch of commands with bounded concurrency. The single-command verbs are zero-config one-liners (for cancellation, build a `Command` and use its verbs, or go through `Runner`); the batch verbs take an explicit `CancellationToken` so a long fan-out can be cancelled.
Functions and values
| Function or value |
Description
|
Full Usage:
Exec.detach program args
Parameters:
string
args : string seq
Returns: Result<DetachedProcess, ProcessError>
|
Launch `program` with `args` **outside all containment** and let it go — the one-liner form of `Command.LaunchDetached`, which documents the full contract. Unlike every other verb here the child runs in no kill-on-dispose group (Windows: no Job Object; POSIX: its own `setsid` session), is never waited on, and outlives this process; all you get back is its pid + start-time identity. Reach for it only for genuine spawn-and-forget work (a self-updater, a restart-myself relaunch, a daemon handed off to the OS) — for anything you want to observe, use `run`/`outputString` instead. Synchronous, like `which`: there is no run to await.
|
Full Usage:
Exec.outputAll concurrency runner commands cancellationToken
Parameters:
int
runner : IProcessRunner
commands : Command seq
cancellationToken : CancellationToken
Returns: Task<Result<ProcessResult<string>, ProcessError>[]>
|
Run every command in `commands` through `runner`, keeping at most `concurrency` live at once, and collect all results (decoded text) in input order. Each element is one command's independent `Result`; the batch never short-circuits on a failure — `BatchPolicy.CollectAll`. For an explicit fail-fast policy, use `outputAllWithPolicy`.
|
Full Usage:
Exec.outputAllBytes concurrency runner commands cancellationToken
Parameters:
int
runner : IProcessRunner
commands : Command seq
cancellationToken : CancellationToken
Returns: Task<Result<ProcessResult<byte[]>, ProcessError>[]>
|
The raw-bytes companion to `outputAll` — captures each command's stdout as bytes.
|
Full Usage:
Exec.outputAllBytesWithPolicy concurrency runner commands policy cancellationToken
Parameters:
int
runner : IProcessRunner
commands : Command seq
policy : BatchPolicy
cancellationToken : CancellationToken
Returns: Task<Result<ProcessResult<byte[]>, ProcessError>[]>
|
The raw-bytes companion to `outputAllWithPolicy` — captures each command's stdout as bytes.
|
Full Usage:
Exec.outputAllWithPolicy concurrency runner commands policy cancellationToken
Parameters:
int
runner : IProcessRunner
commands : Command seq
policy : BatchPolicy
cancellationToken : CancellationToken
Returns: Task<Result<ProcessResult<string>, ProcessError>[]>
|
Like `outputAll`, but with an explicit `BatchPolicy`: `BatchPolicy.CollectAll` behaves exactly like `outputAll` itself; `BatchPolicy.FailFast` stops the batch on its first `Error` (see `BatchPolicy` for the full contract — already-started/not-yet-started commands, cancellation precedence, input order). Route through the verb layer (not the raw seam) so each command's own `Retry` policy applies, matching `cmd.OutputStringAsync()` / `CliClient.OutputStringAsync` — retry still fires only on a genuine error, never on a non-zero exit (which stays data), and a `FailFast`-triggered cancellation reaches an in-flight retry loop exactly like the caller's own `cancellationToken` would.
|
Full Usage:
Exec.outputBytes program args
Parameters:
string
args : string seq
Returns: Task<Result<ProcessResult<byte[]>, ProcessError>>
|
The raw-bytes companion to `outputString` — captures `program`'s stdout as bytes.
|
Full Usage:
Exec.outputStream concurrency runner commands cancellationToken
Parameters:
int
runner : IProcessRunner
commands : Command seq
cancellationToken : CancellationToken
Returns: IAsyncEnumerable<BatchItem<string>>
|
Run every command in `commands` through `runner`, keeping at most `concurrency` live at once, and yield each result **the moment that command finishes** — the streaming sibling of `outputAll`. Same bounded fan-out, same per-command error semantics (an `Error` is a genuine run failure; a non-zero exit stays `Ok` data), same eager argument validation (a null runner / commands / command element, or `concurrency < 1`, throws right here, before anything runs) — presented as an `IAsyncEnumerable` over completions instead of one array at the end. Key differences from `outputAll`: - **Completion order, not input order.** A fast command never waits behind a slow one. Each `BatchItem` carries its command's `Index` — its position in `commands` — so a result stays traceable to its source; for the input-ordered array, use `outputAll`. - **Results survive a mid-fan-out cancellation.** Every item already handed to the consumer is the consumer's, unlike `outputAll`'s array, which materializes only when the whole batch is done. - **Nothing runs until you enumerate.** The fan-out starts on the first `MoveNextAsync`, and every enumeration starts its own: this is an `IAsyncEnumerable` factory, not a single-shot stream, so enumerating twice runs the batch twice. - **Backpressure.** A finished command hands its item over before releasing its concurrency slot, and the hand-off buffer is bounded at `concurrency`, so a consumer that stops reading stops the fan-out — once the buffer and the live commands are full, nothing further starts — instead of letting it run the whole batch ahead into memory. **Cancellation.** `cancellationToken` — and the token a consumer passes to `GetAsyncEnumerator` / `WithCancellation`, which is honoured identically — cancels every in-flight capture and stops any command still waiting for a slot from ever starting. It does **not** truncate the stream and never surfaces as an `OperationCanceledException`: a cancelled run is data here, exactly as in `outputAll`, so every command still yields exactly one item and a command that never started yields `ProcessError.Cancelled`. Enumerate to the end to see them. **Abandoning the stream** (breaking out of the loop, which disposes the enumerator) cancels the in-flight captures — with an own-group runner (`JobRunner`) that kills each live tree; with a shared-group runner (`ProcessGroup`) they live until you tear the group down — and leaves every still-queued command unstarted. Disposal awaits the fan-out's teardown, so nothing outlives it. **No `BatchPolicy` here, by design.** This first iteration is `BatchPolicy.CollectAll`-only: the stream never short-circuits on a command's `Error`, and there is no `policy` parameter to pass (rather than one that is quietly ignored). A consumer that wants to stop on the first failure already can, and more directly than a policy would: stop enumerating, and abandonment does the rest. If you want the fail-fast contract *with* an input-ordered array, use `outputAllWithPolicy` / `outputAllBytesWithPolicy`. Each command runs through the verb layer (`Runner.outputString`), not the raw capture seam, so its own `Retry` policy applies exactly as it does in `outputAll`.
|
Full Usage:
Exec.outputStreamBytes concurrency runner commands cancellationToken
Parameters:
int
runner : IProcessRunner
commands : Command seq
cancellationToken : CancellationToken
Returns: IAsyncEnumerable<BatchItem<byte[]>>
|
The raw-bytes companion to `outputStream` — captures each command's stdout as bytes (for binary artifacts: `git cat-file`, `tar -c`, an image transcoder). Scheduling, completion ordering, per-item indexing, validation, backpressure, and the cancellation/abandonment contract are identical to `outputStream`; the buffering counterpart is `outputAllBytes`.
|
Full Usage:
Exec.outputString program args
Parameters:
string
args : string seq
Returns: Task<Result<ProcessResult<string>, ProcessError>>
|
Run `program` with `args` to completion and return the full `ProcessResult` (a non-zero exit is data, not an error).
|
Full Usage:
Exec.run program args
Parameters:
string
args : string seq
Returns: Task<Result<string, ProcessError>>
|
Run `program` with `args` in a private kill-on-dispose group, require a zero/accepted exit, and return stdout with trailing whitespace trimmed.
|
|
Resolve `program` to a full path without spawning it — a preflight/`doctor`-style check ("is this tool installed?") with no side effects, unlike probing availability by actually running the program (`ProbeAsync`). Reuses the exact PATH/PATHEXT-aware logic the spawn path itself falls back on to name the directories it searched (`Native.Common.resolveProgram`), so `which` and an actual spawn of the same `program` never disagree on found-vs-not-found. Returns the resolved full path on success, or a typed `ProcessError.NotFound` — `Searched` names the `PATH` value that was probed when `program` is a bare name (e.g. `"git"`), and is `None` when `program` already names a path (e.g. `"./tool"`, `"/usr/bin/tool"`), since a path-form program is checked directly and never searched. **Resolves against the CURRENT PROCESS's `PATH`** (and no prefer-local) — the host-wide "is this tool installed" question. For "will THIS command find its program", against a command's effective child `PATH` (its `Env` override) and `PreferLocal`, use `Command.ResolveProgram` / `CliClient.ResolveProgram` instead; both share this same resolver, differing only in whose `PATH` is searched.
|
ProcessKit API Reference