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.ProcessOpen Axial.Process.DSL for command-line-shaped authoring:
Show page setup
// Setup for the checked examples on this page.
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
/// Fails the docs test when an example's result differs from the value shown.
let shouldEqual expected actual =
if actual <> expected then failwithf "Expected %A but got %A" expected actual// The examples on this page start real processes with the live service.
let host : ProcessHostEnvironment =
{ Process = Process.live Clock.live FileSystem.live Console.live
Console = Console.live }
let stdoutOf (workflow: Flow<ProcessHostEnvironment, ProcessError, ProcessResult>) : string =
match Flow.run host workflow with
| Exit.Success result -> result.StdOut
| Exit.Failure cause -> failwithf "%A" cause
host: ProcessHostEnvironmentAxial.Process.ProcessHostEnvironmentThe live environment used by <c>Process.run</c> at a command-line host boundary. Application workflows normally use their own environment record and <c>Process.runWith</c>.
Process: IProcessAxial.Process.ProcessModulelive: IClock -> IFileSystem -> IConsole -> IProcessCreates a live process service using an explicit clock for transcript timestamps and durations.
Axial.PlatformService.ClockHelpers for the clock service.
live: IClockCreates a live clock backed by and a monotonic timer.
Axial.FileSystem.FileSystemModulelive: IFileSystemCreates a live file-system service backed by , , and .
Axial.Console.ConsoleModulelive: IConsoleCreates a live console service backed by .
Console: IConsolestdoutOf: Flow<ProcessHostEnvironment,ProcessError,ProcessResult> -> stringworkflow: Flow<ProcessHostEnvironment,ProcessError,ProcessResult>Axial.Flow`3Represents a cold workflow that reads an environment, returns a typed result, and is executed explicitly through one of its execution members such as ToTask, ToAsync, or RunSynchronously. The type of the environment dependency. The type of the failure value. The type of the success value.
Axial.Process.ProcessErrorA recoverable process startup, timeout, stage, or I/O failure. Interrupting the workflow is not an error: it terminates the processes and surfaces as <c>Cause.Interrupt</c>.
Axial.Process.ProcessResultThe complete structured transcript returned by a process execution.
stringAn abbreviation for the CLI type . Basic Types
Axial.Flowrun: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
Axial.Exit`2Represents the final outcome of a workflow execution. The type of the success value. The type of the domain-specific failure value.
SuccessThe workflow completed successfully.
result: ProcessResultStdOut: stringFailureThe workflow failed due to a specific cause.
cause: Cause<ProcessError>failwithf: Printf.StringFormat<'T,'Result> -> 'TPrint to a string buffer and raise an exception with the given result. Helper printers must return strings. The formatter. The formatted result. See Printf.failwithf (link: ) for examples.
open Axial.Process.DSL
let connect (deviceId: string) (workspace: string) =
cmd $"printf %%s {deviceId}"
|> cwd workspace
|> env "DEVICE_MODE" "service"
|> timeout (TimeSpan.FromSeconds 30.0)
|> capture
AxialProcessAxial.Process.DSLconnect: string -> string -> Flow<'a,ProcessError,ProcessResult>deviceId: stringstringAn abbreviation for the CLI type . Basic Types
workspace: stringcmd: FormattableString -> ProcessSpecBuilds a command-line-shaped command while preserving every interpolation hole as one argument.
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
cwd: string -> ProcessSpec -> ProcessSpecenv: string -> string -> ProcessSpec -> ProcessSpectimeout: TimeSpan -> ProcessSpec -> ProcessSpecSets the maximum execution time for a command or specification. Example: cmd $"service-device" |> timeout (TimeSpan.FromSeconds 30.0) |> capture
System.TimeSpanRepresents a time interval.
FromSeconds: float -> TimeSpanReturns a that represents a specified number of seconds, where the specification is accurate to the nearest millisecond. A number of seconds, accurate to the nearest millisecond. An object that represents . is less than or greater than . -or- is . -or- is . is equal to .
capture: ProcessSpec -> Flow<'a,ProcessError,ProcessResult>Runs a command or specification and captures stdout and stderr.
stdoutOf (connect "sensor 7; rm -rf /" (IO.Path.GetTempPath())) |> shouldEqual "sensor 7; rm -rf /"
stdoutOf: Flow<ProcessHostEnvironment,ProcessError,ProcessResult> -> stringconnect: string -> string -> Flow<'a,ProcessError,ProcessResult>IOGetTempPath: unit -> stringReturns the path of the current user's temporary folder. The path to the temporary folder, ending with a backslash. The caller does not have the required permissions.
System.IO.PathPerforms operations on instances that contain file or directory path information. These operations are performed in a cross-platform manner.
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
shouldEqual: 'a -> 'a -> unitInterpolation holes remain individual native arguments. They are not concatenated into shell source. Mark sensitive values explicitly:
let authenticate (token: string) =
cmd $"printf %%s {secret token}"
authenticate: string -> ProcessSpectoken: stringstringAn abbreviation for the CLI type . Basic Types
cmd: FormattableString -> ProcessSpecBuilds a command-line-shaped command while preserving every interpolation hole as one argument.
authenticate "s3cret" |> Process.render |> shouldEqual "printf %s ***"
stdoutOf (authenticate "s3cret" |> capture) |> shouldEqual "s3cret"
authenticate: string -> ProcessSpec(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
Axial.Process.ProcessModulerender: ProcessSpec -> stringRenders a redacted shell-like description of the complete process specification.
shouldEqual: 'a -> 'a -> unitstdoutOf: Flow<ProcessHostEnvironment,ProcessError,ProcessResult> -> stringcapture: ProcessSpec -> Flow<'a,ProcessError,ProcessResult>Runs a command or specification and captures stdout and stderr.
The real value reaches the process; renders, plans, and errors show ***.
Use bash, sh, or pwsh when shell syntax is required. Interpolated values are passed out of band as positional arguments:
let shout (value: string) =
bash $"printf '%%s' {value} | tr '[:lower:]' '[:upper:]'"
|> capture
shout: string -> Flow<'a,ProcessError,ProcessResult>value: stringstringAn abbreviation for the CLI type . Basic Types
bash: FormattableString -> ProcessSpecBuilds a Bash program with interpolation values passed as positional arguments.
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
capture: ProcessSpec -> Flow<'a,ProcessError,ProcessResult>Runs a command or specification and captures stdout and stderr.
stdoutOf (shout "it's $HOME") |> shouldEqual "IT'S $HOME"
stdoutOf: Flow<ProcessHostEnvironment,ProcessError,ProcessResult> -> stringshout: string -> Flow<'a,ProcessError,ProcessResult>(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
shouldEqual: 'a -> 'a -> unitcapture, 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
|> shouldEqual 0
cmd: FormattableString -> ProcessSpecBuilds a command-line-shaped command while preserving every interpolation hole as one argument.
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
console: ProcessSpec -> Flow<'a,ProcessError,ProcessResult>Forwards stdout and stderr to the host console while retaining structured completion data.
run: Flow<ProcessHostEnvironment,ProcessError,'a> -> intStarts a process Flow with live services and returns a command-line exit code.
shouldEqual: 'a -> 'a -> unitUse 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.
type AppEnvironment =
{ Process: IProcess
Console: IConsole
Region: string }
interface IHasProcess with member this.Process = this.Process
interface IHasConsole with member this.Console = this.Console
let appEnvironment =
{ Process = Process.live Clock.live FileSystem.live Console.live
Console = Console.live
Region = "eu" }
FsLiveDocsGeneratedPage4_333522998462.AppEnvironmentProcess: IProcessAxial.Process.IProcessInterprets process specifications as lazy Axial workflows for a concrete host platform.
Console: IConsoleAxial.Console.IConsoleProvides explicit access to standard console and terminal I/O.
Region: stringstringAn abbreviation for the CLI type . Basic Types
Axial.Process.IHasProcessDeclares that an environment supplies the process service. Implement this on the environment record supplied at the host edge. A workflow that runs processes constrains its environment with 'env :> IHasProcess.
this: AppEnvironmentProcess: AppEnvironment -> unit -> IProcessAxial.Console.IHasConsoleDeclares that an environment supplies the console service. Implement this on the environment supplied at the host edge. A workflow that reads or writes the console constrains its environment with 'env :> IHasConsole.
Console: AppEnvironment -> unit -> IConsoleappEnvironment: AppEnvironmentAxial.Process.ProcessModulelive: IClock -> IFileSystem -> IConsole -> IProcessCreates a live process service using an explicit clock for transcript timestamps and durations.
Axial.PlatformService.ClockHelpers for the clock service.
live: IClockCreates a live clock backed by and a monotonic timer.
Axial.FileSystem.FileSystemModulelive: IFileSystemCreates a live file-system service backed by , , and .
Axial.Console.ConsoleModulelive: IConsoleCreates a live console service backed by .
let exit =
cmd $"dotnet --version"
|> console
|> runWith appEnvironment
exit |> shouldEqual 0
exit: intcmd: FormattableString -> ProcessSpecBuilds a command-line-shaped command while preserving every interpolation hole as one argument.
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
console: ProcessSpec -> Flow<'a,ProcessError,ProcessResult>Forwards stdout and stderr to the host console while retaining structured completion data.
runWith: 'a -> Flow<'a,ProcessError,'b> -> intStarts a process Flow with the supplied application environment and returns a command-line exit code.
appEnvironment: AppEnvironmentshouldEqual: 'a -> 'a -> unitFor application composition, use Process.toFlow (or the DSL's capture or console) and start the enclosing workflow with Flow.run.

