Reference · reference

shell module

3 min read · 2026-09-02 · config-weave 0.1.0

use shell runs external commands. It replaces the process module of wscript-std, which config-weave does not register. Every function takes a command or script string and an options Value, and returns Result[CmdOutput, string]. The options argument is required because wscript functions have a fixed arity: pass Value::Null for the defaults, or a Value::Map with any of the keys below. A timeout kills the child and returns Err.

OptionTypeMeaning
cwdstringworking directory for the child
envmap of stringenvironment variables added to the child
timeoutint or floatseconds before the child is killed
stdinstringtext written to the child's standard input

A non-zero exit is not an Err

Err means the command could not run: the program was not found, the spawn failed or the timeout fired. When the command ran and exited non-zero, the result is Ok and success is false. Inspect success or code.

CmdOutput

rust
struct CmdOutput {
    stdout: string,
    stderr: string,
    code: int,
    success: bool,
}

The result of every function in this module. success is true when code is zero. stdout and stderr are decoded as UTF-8 lossily: a byte that is not valid UTF-8, such as an OEM code-page character from Windows PowerShell 5.1, becomes U+FFFD and the rest of the stream survives.

run

rust
shell::run(cmd: string, opts: Value) -> Result[CmdOutput, string]

Splits cmd into words with shell-words rules and executes the program directly. There is no shell interpretation, so globs, pipes and $VAR references are passed to the program as literal text.

run_streaming

rust
shell::run_streaming(cmd: string, opts: Value) -> Result[CmdOutput, string]

Behaves like run, and also streams each output line through the log module as it arrives. Standard output lines are logged at info and standard error lines at warn. Use it for long installs so the reader sees progress.

bash

rust
shell::bash(script: string, opts: Value) -> Result[CmdOutput, string]

Runs script with bash -c, and falls back to sh when bash is absent. This is the way to use pipes, globs and variable expansion.

powershell

rust
shell::powershell(script: string, opts: Value) -> Result[CmdOutput, string]

Runs script with powershell, and falls back to pwsh, passing -NoProfile -NonInteractive. It works on Linux when PowerShell Core is installed. The script never appears on the command line, so the process list and command-line auditing do not see a secret interpolated into it: it is written to a private temp file, deleted after the run, which a short -Command bootstrap reads and runs. Exit codes, output and standard input ($input and [Console]::In) behave as they would with -Command, with the exception below, and execution policy does not apply.

Two exit-code cases to know, both measured on Windows PowerShell 5.1 and pwsh 7.4. A script-level return while $? is false exits 0, where -Command <script> exited 1: the script runs as a dot-sourced script block followed by if ($?) { exit 0 } else { exit 1 }, and return leaves the block before that line runs. So try { Get-Service nope -ErrorAction Stop } catch { return } exits 0. A script whose last statement is an empty catch {} after a caught error exits 1, as it does under -Command. End a script whose exit code matters, such as a guard, with an explicit exit 0 or exit 1, and never rely on return.

rust
use shell
use value

fn check(props: Value) -> Result[CheckResult, string] {
    let out = shell::run("systemctl is-active nginx", Value::Null)?
    if !out.success { return Ok(CheckResult::NotConfigured) }
    Ok(CheckResult::AlreadyConfigured)
}