Argument
Defines typed positional arguments for Effect CLI applications.
Arguments consume ordered values after a command name and its flags, then parse them into the types a command handler expects. This module includes constructors for common argument shapes, plus helpers for optional or variadic arguments, schema validation, transformations, defaults, config fallbacks, and prompts for missing values.
Combinators
Creates a variadic argument that requires at least n values.
Signature
declare const atLeast: { <A>(min: number): (self: Argument<A>) => Argument<readonly Array<A>>; <A>(self: Argument<A>, min: number): Argument<readonly Array<A>>;}Example
(Requiring a minimum number of values)
import { Argument } from "effect/unstable/cli"
const files = Argument.string("files").pipe(Argument.atLeast(1))files.kind // => "argument"Creates a variadic argument that accepts at most n values.
Signature
declare const atMost: { <A>(max: number): (self: Argument<A>) => Argument<readonly Array<A>>; <A>(self: Argument<A>, max: number): Argument<readonly Array<A>>;}Example
(Limiting the maximum number of values)
import { Argument } from "effect/unstable/cli"
const files = Argument.string("files").pipe(Argument.atMost(5))files.kind // => "argument"Creates a variadic argument that accepts between min and max values.
Signature
declare const between: { <A>(min: number, max: number): (self: Argument<A>) => Argument<readonly Array<A>>; <A>(self: Argument<A>, min: number, max: number): Argument<readonly Array<A>>;}Example
(Requiring a range of values)
import { Argument } from "effect/unstable/cli"
const files = Argument.string("files").pipe(Argument.between(1, 5))files.kind // => "argument"Filters parsed values, failing with a custom error message if the predicate returns false.
Signature
declare const filter: { <A>(predicate: (a: A) => boolean, onFalse: (a: A) => string): (self: Argument<A>) => Argument<A>; <A>(self: Argument<A>, predicate: (a: A) => boolean, onFalse: (a: A) => string): Argument<A>;}Example
(Filtering parsed values)
import { Argument } from "effect/unstable/cli"
const positiveInt = Argument.integer("count").pipe( Argument.filter( (n) => n > 0, (n) => `Expected positive integer, got ${n}` ))positiveInt.kind // => "argument"Filters and transforms parsed values, failing with a custom error message if the filter function returns None.
Signature
declare const filterMap: { <A, B>(f: (a: A) => Option<B>, onNone: (a: A) => string): (self: Argument<A>) => Argument<B>; <A, B>(self: Argument<A>, f: (a: A) => Option<B>, onNone: (a: A) => string): Argument<B>;}Example
(Filtering and mapping parsed values)
import { Option } from "effect"import { Argument } from "effect/unstable/cli"
const positiveInt = Argument.integer("count").pipe( Argument.filterMap( (n) => n > 0 ? Option.some(n) : Option.none(), (n) => `Expected positive integer, got ${n}` ))positiveInt.kind // => "argument"Transforms the parsed value of a positional argument.
Signature
declare const map: { <A, B>(f: (a: A) => B): (self: Argument<A>) => Argument<B>; <A, B>(self: Argument<A>, f: (a: A) => B): Argument<B>;}Example
(Mapping parsed values)
import { Argument } from "effect/unstable/cli"
const port = Argument.integer("port").pipe( Argument.map((p) => ({ port: p, url: `http://localhost:${p}` })))port.kind // => "argument"Transforms the parsed value of a positional argument using an effectful function.
Signature
declare const mapEffect: { <A, B>(f: (a: A) => Effect<B, CliError, Environment>): (self: Argument<A>) => Argument<B>; <A, B>(self: Argument<A>, f: (a: A) => Effect<B, CliError, Environment>): Argument<B>;}Example
(Validating values effectfully)
import { Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect"import { Argument, CliError } from "effect/unstable/cli"import { ChildProcessSpawner } from "effect/unstable/process"
const CliTestLayer = Layer.mergeAll( FileSystem.layerNoop({}), Path.layer, Stdio.layerTest({}), Layer.succeed(Terminal.Terminal, Terminal.make({ columns: Effect.succeed(80), rows: Effect.succeed(24), readInput: Effect.die("unused"), readLine: Effect.die("unused"), display: () => Effect.void })), Layer.succeed( ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make(() => Effect.die("unused")) ))
const files = Argument.string("files").pipe( Argument.mapEffect((file) => file.endsWith(".txt") ? Effect.succeed(file) : Effect.fail( new CliError.UserError({ cause: new Error(`Unsupported file extension: ${file}`), userMessage: "Only .txt files allowed" }) ) ))
const [, value] = await Effect.runPromise( files.parse({ arguments: ["notes.txt"], flags: {} }).pipe(Effect.provide(CliTestLayer)))value // => "notes.txt"mapTryCatch
Transforms the parsed value of a positional argument using a function that may throw.
Signature
declare const mapTryCatch: { <A, B>(f: (a: A) => B, onError: (error: unknown) => string): (self: Argument<A>) => Argument<B>; <A, B>(self: Argument<A>, f: (a: A) => B, onError: (error: unknown) => string): Argument<B>;}Example
(Mapping values that may throw)
import { Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect"import { Argument } from "effect/unstable/cli"import { ChildProcessSpawner } from "effect/unstable/process"
const CliTestLayer = Layer.mergeAll( FileSystem.layerNoop({}), Path.layer, Stdio.layerTest({}), Layer.succeed(Terminal.Terminal, Terminal.make({ columns: Effect.succeed(80), rows: Effect.succeed(24), readInput: Effect.die("unused"), readLine: Effect.die("unused"), display: () => Effect.void })), Layer.succeed( ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make(() => Effect.die("unused")) ))
const json = Argument.string("data").pipe( Argument.mapTryCatch( (str) => JSON.parse(str), (error) => `Invalid JSON: ${error instanceof Error ? error.message : String(error)}` ))
const [, value] = await Effect.runPromise( json.parse({ arguments: ['{"enabled":true}'], flags: {} }).pipe(Effect.provide(CliTestLayer)))value // => { enabled: true }Makes a positional argument optional.
Signature
declare function optional<A>(arg: Argument<A>): Argument<Option<A>>Example
(Making an argument optional)
import { Argument } from "effect/unstable/cli"
const optionalVersion = Argument.string("version").pipe(Argument.optional)optionalVersion.kind // => "argument"Provides a fallback argument to use if this argument fails to parse.
Signature
declare const orElse: { <B>(that: LazyArg<Argument<B>>): <A>(self: Argument<A>) => Argument<B | A>; <A, B>(self: Argument<A>, that: LazyArg<Argument<B>>): Argument<A | B>;}Example
(Providing a fallback argument)
import { Argument } from "effect/unstable/cli"
const value = Argument.integer("value").pipe( Argument.orElse(() => Argument.string("value")))value.kind // => "argument"orElseResult
Provides a fallback argument, wrapping results in Result to distinguish which succeeded.
Signature
declare const orElseResult: { <B>(that: LazyArg<Argument<B>>): <A>(self: Argument<A>) => Argument<Result<A, B>>; <A, B>(self: Argument<A>, that: LazyArg<Argument<B>>): Argument<Result<A, B>>;}Example
(Returning which fallback succeeded)
import { Argument } from "effect/unstable/cli"
const source = Argument.file("source").pipe( Argument.orElseResult(() => Argument.string("url")))// Returns Result<string, string>source.kind // => "argument"Creates a variadic positional argument that accepts multiple values.
Signature
declare const variadic: { (options?: VariadicParamOptions): <A>(self: Argument<A>) => Argument<readonly Array<A>>; <A>(self: Argument<A>, options?: VariadicParamOptions): Argument<readonly Array<A>>;}Example
(Accepting multiple values)
import { Argument } from "effect/unstable/cli"
// Accept any number of filesconst anyFiles = Argument.string("files").pipe(Argument.variadic)
// Accept at least 1 fileconst atLeastOneFile = Argument.string("files").pipe( Argument.variadic({ min: 1 }))
// Accept between 1 and 5 filesconst limitedFiles = Argument.string("files").pipe( Argument.variadic({ min: 1, max: 5 }))
const kinds = [anyFiles.kind, atLeastOneFile.kind, limitedFiles.kind] // => ["argument", "argument", "argument"]withDefault
Provides a default value for a positional argument.
Signature
declare const withDefault: { <B>(defaultValue: B | Effect<B, CliError, Environment>): <A>(self: Argument<A>) => Argument<B | A>; <A, B>(self: Argument<A>, defaultValue: B | Effect<B, CliError, Environment>): Argument<A | B>;}Example
(Providing a default value)
import { Argument } from "effect/unstable/cli"
const port = Argument.integer("port").pipe(Argument.withDefault(8080))port.kind // => "argument"withDescription
Adds a description to a positional argument.
Signature
declare const withDescription: { <A>(description: string): (self: Argument<A>) => Argument<A>; <A>(self: Argument<A>, description: string): Argument<A>;}Example
(Adding an argument description)
import { Argument } from "effect/unstable/cli"
const filename = Argument.string("filename").pipe( Argument.withDescription("The input file to process"))filename.kind // => "argument"withFallbackConfig
Adds a fallback config that is loaded when a required argument is missing.
Signature
declare const withFallbackConfig: { <B>(config: Config<B>): <A>(self: Argument<A>) => Argument<B | A>; <A, B>(self: Argument<A>, config: Config<B>): Argument<A | B>;}Example
(Loading a fallback config)
import { Config } from "effect"import { Argument } from "effect/unstable/cli"
const repository = Argument.string("repository").pipe( Argument.withFallbackConfig(Config.string("REPOSITORY")))repository.kind // => "argument"withFallbackPrompt
Adds a fallback prompt that is shown when a required argument is missing.
Signature
declare const withFallbackPrompt: { <B>(prompt: FallbackPrompt<B>): <A>(self: Argument<A>) => Argument<B | A>; <A, B>(self: Argument<A>, prompt: FallbackPrompt<B>): Argument<A | B>;}Example
(Showing a fallback prompt)
import { Argument, Prompt } from "effect/unstable/cli"
const filename = Argument.string("filename").pipe( Argument.withFallbackPrompt(Prompt.text({ message: "Filename" })))filename.kind // => "argument"withSchema
Validates parsed values against a Schema.
Signature
declare const withSchema: { <A, B>(schema: ConstraintCodec<B, A, Environment, unknown>): (self: Argument<A>) => Argument<B>; <A, B>(self: Argument<A>, schema: ConstraintCodec<B, A, Environment, unknown>): Argument<B>;}Example
(Validating parsed values with a schema)
import { Schema } from "effect"import { Argument } from "effect/unstable/cli"
const input = Argument.string("input").pipe( Argument.withSchema(Schema.NonEmptyString))input.kind // => "argument"Constructors
Creates a positional choice argument.
Signature
declare function choice<Choices extends readonly Array<string>>(name: string, choices: Choices): Argument<Choices[number]>Example
(Creating a choice argument)
import { Argument } from "effect/unstable/cli"
const environment = Argument.choice("environment", ["dev", "staging", "prod"])environment.kind // => "argument"choiceWithValue
Creates a positional choice argument with custom value mapping.
Signature
declare function choiceWithValue<Choices extends readonly Array<readonly [string, any]>>(name: string, choices: Choices): Argument<Choices[number][1]>Example
(Mapping choices to values)
import { Argument } from "effect/unstable/cli"
const logLevel = Argument.choiceWithValue("level", [ ["debug", 0], ["info", 1], ["warn", 2], ["error", 3]])logLevel.kind // => "argument"Creates a positional date argument.
Signature
declare function date(name: string): Argument<Date>Example
(Creating a date argument)
import { Argument } from "effect/unstable/cli"
const startDate = Argument.date("start-date")startDate.kind // => "argument"Creates a positional directory path argument.
Signature
declare function directory(name: string, options?: { readonly mustExist?: boolean;}): Argument<string>Example
(Creating a directory path argument)
import { Argument } from "effect/unstable/cli"
const workspace = Argument.directory("workspace", { mustExist: true }) // Must existworkspace.kind // => "argument"Creates a positional file path argument.
Signature
declare function file(name: string, options?: { readonly mustExist?: boolean;}): Argument<string>Example
(Creating file path arguments)
import { Argument } from "effect/unstable/cli"
const inputFile = Argument.file("input", { mustExist: true }) // Must existconst outputFile = Argument.file("output", { mustExist: false }) // Must not existconst kinds = [inputFile.kind, outputFile.kind] // => ["argument", "argument"]Creates a positional argument that reads a file and parses its content.
Details
The parser is chosen from the explicit format option or, when omitted, the
file extension. The parsed value is unknown; use fileSchema when the
parsed content should also be decoded with a Schema.
Signature
declare function fileParse(name: string, options?: FileParseOptions): Argument<unknown>Example
(Parsing file content)
import { Argument } from "effect/unstable/cli"
const config = Argument.fileParse("config", { format: "json" })config.kind // => "argument"fileSchema
Creates a positional argument that reads and validates file content using a schema.
Signature
declare function fileSchema<A>(name: string, schema: ConstraintDecoder<A, Environment>, options?: { readonly errorFormatter?: Formatter<string>; readonly format?: "json" | "ini" | "toml" | "yaml";}): Argument<A>Example
(Validating file content with a schema)
import { Schema } from "effect"import { Argument } from "effect/unstable/cli"
const ConfigSchema = Schema.Struct({ port: Schema.Number, host: Schema.String})
const config = Argument.fileSchema("config", ConfigSchema)config.kind // => "argument"Creates a positional argument that reads file content as a string.
Signature
declare function fileText(name: string): Argument<string>Example
(Reading file text)
import { Argument } from "effect/unstable/cli"
const config = Argument.fileText("config-file")config.kind // => "argument"Creates a positional float argument.
Signature
declare function float(name: string): Argument<number>Example
(Creating a float argument)
import { Argument } from "effect/unstable/cli"
const ratio = Argument.float("ratio")ratio.kind // => "argument"Creates a positional integer argument.
Signature
declare function integer(name: string): Argument<number>Example
(Creating an integer argument)
import { Argument } from "effect/unstable/cli"
const count = Argument.integer("count")count.kind // => "argument"Creates an empty sentinel argument that always fails to parse.
Signature
declare const none: Argument<never>Example
(Creating a sentinel argument)
import { Argument } from "effect/unstable/cli"
// Used as a placeholder or default in combinatorsconst noArg = Argument.nonenoArg.kind // => "argument"Creates a positional path argument.
Signature
declare function path(name: string, options?: { mustExist?: boolean; pathType?: "either" | "file" | "directory";}): Argument<string>Example
(Creating a path argument)
import { Argument } from "effect/unstable/cli"
const configPath = Argument.path("config")configPath.kind // => "argument"Creates a positional redacted argument that obscures its value.
Signature
declare function redacted(name: string): Argument<Redacted<string>>Example
(Creating a redacted argument)
import { Argument } from "effect/unstable/cli"
const secret = Argument.redacted("secret")secret.kind // => "argument"Creates a positional string argument.
Signature
declare function string(name: string): Argument<string>Example
(Creating a string argument)
import { Argument } from "effect/unstable/cli"
const filename = Argument.string("filename")filename.kind // => "argument"Metadata
withMetavar
Sets a custom metavar (placeholder name) for the argument in help documentation.
Details
The metavar is displayed in usage text to indicate what value the user should provide.
For example, <FILE> shows FILE as the metavar.
Signature
declare const withMetavar: { <A>(metavar: string): (self: Argument<A>) => Argument<A>; <A>(self: Argument<A>, metavar: string): Argument<A>;}Example
(Setting a metavar)
import { Argument } from "effect/unstable/cli"
const port = Argument.integer("port").pipe( Argument.withMetavar("PORT"))port.kind // => "argument"Models
Represents a positional command-line argument.
Gotchas
boolean is intentionally omitted from Argument constructors. Positional
boolean arguments are ambiguous in CLI design since there is no flag name to
negate (for example, --no-verbose). Use Flag.boolean instead, or use
Argument.choice with explicit "true" / "false" strings if needed.
Signature
interface Argument<A> extends Param<typeof Param.argumentKind, A> {}