Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Console
open Axial.FileSystem
open Axial.PlatformService
open Axial.Process

Open Axial.Process.DSL for command-line-shaped authoring:

open Axial.Process.DSL

let workflow =
    cmd $"device-tool connect {deviceId}"
    |> cwd workspace
    |> env "DEVICE_MODE" "service"
    |> timeout (TimeSpan.FromSeconds 30)
    |> capture

Interpolation holes remain individual native arguments. They are not concatenated into shell source. Mark sensitive values explicitly:

let workflow =
    cmd $"device-tool authenticate {secret token}"
    |> capture

Use bash, sh, or pwsh when shell syntax is required. Interpolated values are passed out of band as positional arguments:

let workflow =
    bash $"printf '%s' {value} | tr '[:lower:]' '[:upper:]'"
    |> capture

capture, console, and stream are lazy: they turn the specification into a Flow or FlowStream. Capture selects complete stdout and stderr capture. Console forwards both channels while retaining structured completion data. Stream yields ProcessEvent values and must be consumed by a Flow before a host can run it.

run is the host execution verb: it starts a process Flow with live services and returns a command-line exit code. This keeps it distinct from Flow.run, which runs an application Flow with its explicit environment.

cmd $"dotnet --version"
|> console
|> run

Use runWith when an application already owns its environment. The environment must provide IConsole for reporting a typed process failure; it can carry any additional application services. The Flow's own type states whether it also needs IProcess.

let exit =
    cmd $"dotnet --version"
    |> console
    |> runWith appEnvironment

For application composition, use Process.toFlow (or the DSL's capture or console) and start the enclosing workflow with Flow.run.