Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

Flag unstable

Defines named options for command-line applications.

A Flag<A> describes how to read one named value from parsed command-line input, validate it, and produce an A. Flags are useful for inputs such as ports, verbosity switches, configuration files, output directories, choices, secrets, and repeated values. The helpers here build flags with aliases, defaults, optional values, prompts, configuration fallbacks, validation, and value transformations.

37 exports Since v4.0.0 Source

Aliasing

withAlias

unstable
Since v4.0.0

Adds an alias to a flag, allowing it to be referenced by multiple names.

Signature

declare const withAlias: {
<A>(alias: string): (self: Flag<A>) => Flag<A>;
<A>(self: Flag<A>, alias: string): Flag<A>;
}

Example Adding flag aliases

import { Flag } from "effect/cli"
// Flag can be used as both --verbose and -v
const verboseFlag = Flag.Boolean("verbose").pipe(
Flag.withAlias("v")
)
// Multiple aliases can be chained
const helpFlag = Flag.Boolean("help").pipe(
Flag.withAlias("h"),
Flag.withAlias("?")
)
const kinds = [verboseFlag.kind, helpFlag.kind] // => ["flag", "flag"]

Alternatives

orElse

unstable
Since v4.0.0

Provides an alternative flag if the first one fails to parse.

Signature

declare const orElse: {
<B>(that: LazyArg<Flag<B>>): <A>(self: Flag<A>) => Flag<B | A>;
<A, B>(self: Flag<A>, that: LazyArg<Flag<B>>): Flag<A | B>;
}

Example Falling back to another flag

import { Flag } from "effect/cli"
// Try parsing as integer, fallback to string
const valueFlag = Flag.orElse(
Flag.Int("value"),
() => Flag.String("value")
)
// Multiple input sources with fallback
const configFlag = Flag.orElse(
Flag.File("config"),
() => Flag.String("config-url")
)
const kinds = [valueFlag.kind, configFlag.kind] // => ["flag", "flag"]
Since v4.0.0

Tries to parse with the first flag, then the second, returning a Result that indicates which succeeded.

Signature

declare const orElseResult: {
<B>(that: LazyArg<Flag<B>>): <A>(self: Flag<A>) => Flag<Result<A, B>>;
<A, B>(self: Flag<A>, that: LazyArg<Flag<B>>): Flag<Result<A, B>>;
}

Example Returning fallback results

import { Effect, FileSystem, Layer, Path, Result, Stdio, Terminal } from "effect"
import { Flag } from "effect/cli"
import { ChildProcessSpawner } from "effect/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 sourceFlag = Flag.orElseResult(
Flag.String("source"),
() => Flag.String("source-url")
)
const program = Effect.gen(function*() {
const [, source] = yield* sourceFlag.parse({
arguments: [],
flags: { "source-url": ["https://example.com"] }
})
return source
})
await Effect.runPromise(program.pipe(Effect.provide(CliTestLayer))) // => Result.fail("https://example.com")

Combinators

Since v4.0.0

Adds a fallback config that is loaded when a required flag is missing.

Signature

declare const withFallbackConfig: {
<B>(config: Config<B>): <A>(self: Flag<A>) => Flag<B | A>;
<A, B>(self: Flag<A>, config: Config<B>): Flag<A | B>;
}

Example Falling back to config

import { Config } from "effect"
import { Flag } from "effect/cli"
const verbose = Flag.Boolean("verbose").pipe(
Flag.withFallbackConfig(Config.Boolean("VERBOSE"))
)
verbose.kind // => "flag"
Since v4.0.0

Adds a fallback prompt that is shown when a required flag is missing.

Signature

declare const withFallbackPrompt: {
<B>(prompt: FallbackPrompt<B>): <A>(self: Flag<A>) => Flag<B | A>;
<A, B>(self: Flag<A>, prompt: FallbackPrompt<B>): Flag<A | B>;
}

Example Falling back to prompts

import { Flag, Prompt } from "effect/cli"
const name = Flag.String("name").pipe(
Flag.withFallbackPrompt(Prompt.String({ message: "Name" }))
)
name.kind // => "flag"
Since v4.1.0

Lets a flag be given without a value, in which case value is used.

Details

Follows GNU-style optional values, like --color[=WHEN]. An explicit value must be attached with = (--watch=until-done or -w=until-done). A bare --watch is parsed as --watch=<value>, so value is validated like any other input. The flag never consumes the next token, so in --watch build, build stays a positional argument or subcommand. The flag is still required unless it is made optional or given a default.

Signature

declare const withOptionalValue: {
(value: string): <A>(self: Flag<A>) => Flag<A>;
<A>(self: Flag<A>, value: string): Flag<A>;
}

Example Flag with an optional value

import { Flag } from "effect/cli"
const watch = Flag.Literals("watch", ["first-failure", "until-done"]).pipe(
Flag.withOptionalValue("first-failure"),
Flag.optional
)
// --watch => Option.some("first-failure")
// --watch=until-done => Option.some("until-done")
// (absent) => Option.none()
// In help: --watch [=choice]
watch.kind // => "flag"

Constructors

Boolean

unstable
Since v4.0.0

Creates a boolean flag that can be enabled or disabled.

Signature

declare function Boolean(name: string): Flag<boolean>

Example Creating boolean flags

import { Flag } from "effect/cli"
const verboseFlag = Flag.Boolean("verbose")
// Usage: --verbose (true) or --no-verbose (false)
// Omission fails unless the flag is made optional or given a fallback.
verboseFlag.kind // => "flag"
Since v4.0.0

Constructs option parameters that represent a choice between several inputs. Each tuple maps a string flag value to an associated typed value.

Signature

declare function ChoiceWithValue<Choice extends readonly Array<readonly [string, any]>>(name: string, choices: Choice): Flag<Choice[number][1]>

Example Creating flag choices with values

import { Flag } from "effect/cli"
// simple enum like choice mapping directly to string union
const color = Flag.Literals("color", ["red", "green", "blue"])
// choice with custom value mapping
const logLevel = Flag.ChoiceWithValue("log-level", [
["debug", "Debug" as const],
["info", "Info" as const],
["error", "Error" as const]
])
const kinds = [color.kind, logLevel.kind] // => ["flag", "flag"]

Date

unstable
Since v4.0.0

Creates a date flag that accepts date input in ISO format.

Signature

declare function Date(name: string): Flag<Date>

Example Creating date flags

import { Flag } from "effect/cli"
const startDateFlag = Flag.Date("start-date")
// Usage: --start-date 2023-12-25
startDateFlag.kind // => "flag"

Directory

unstable
Since v4.0.0

Creates a directory path flag that accepts directory paths with optional existence validation.

Signature

declare function Directory(name: string, options?: {
readonly mustExist?: boolean;
}): Flag<string>

Example Creating directory flags

import { Flag } from "effect/cli"
// Basic directory flag
const outputFlag = Flag.Directory("output")
// Usage: --output ./build
// Directory that must exist
const sourceFlag = Flag.Directory("source", { mustExist: true })
// Usage: --source ./src (directory must exist)
const kinds = [outputFlag.kind, sourceFlag.kind] // => ["flag", "flag"]

File

unstable
Since v4.0.0

Creates a file path flag that accepts file paths with optional existence validation.

Signature

declare function File(name: string, options?: {
readonly mustExist?: boolean;
}): Flag<string>

Example Creating file flags

import { Flag } from "effect/cli"
// Basic file flag
const inputFlag = Flag.File("input")
// Usage: --input ./data.json
// File that must exist
const configFlag = Flag.File("config", { mustExist: true })
// Usage: --config ./config.yaml (file must exist)
const kinds = [inputFlag.kind, configFlag.kind] // => ["flag", "flag"]

FileParse

unstable
Since v4.0.0

Creates a flag that reads and parses the content of the specified file.

Details

The parser that is utilized will depend on the specified format, or the extension of the file passed on the command-line if no format is specified.

Signature

declare function FileParse(name: string, options?: FileParseOptions): Flag<unknown>

Example Parsing file contents

import { Flag } from "effect/cli"
// Will use the extension of the file passed on the command line to determine
// the parser to use
const config = Flag.FileParse("config")
// Will use the JSON parser
const jsonConfig = Flag.FileParse("json-config", { format: "json" })
const kinds = [config.kind, jsonConfig.kind] // => ["flag", "flag"]

FileSchema

unstable
Since v4.0.0

Creates a flag that reads and validates file content using the specified schema.

Signature

declare function FileSchema<A>(name: string, schema: ConstraintDecoder<A, Environment>, options?: {
readonly errorFormatter?: Formatter<string>;
readonly format?: "json" | "ini" | "toml" | "yaml";
}): Flag<A>

Example Validating file contents

import { Schema } from "effect"
import { Flag } from "effect/cli"
const ConfigSchema = Schema.Struct({
port: Schema.Number,
host: Schema.String
})
const config = Flag.FileSchema("config", ConfigSchema, { format: "json" })
config.kind // => "flag"

FileText

unstable
Since v4.0.0

Creates a flag that reads and returns file content as a string.

Signature

declare function FileText(name: string): Flag<string>

Example Reading file text

import { Flag } from "effect/cli"
const config = Flag.FileText("config-file")
// --config-file ./app.json will read the file content
config.kind // => "flag"

Finite

unstable
Since v4.0.0

Creates a float flag that accepts decimal number input.

Signature

declare function Finite(name: string): Flag<number>

Example Creating float flags

import { Flag } from "effect/cli"
const rateFlag = Flag.Finite("rate")
// Usage: --rate 3.14
rateFlag.kind // => "flag"

Int

unstable
Since v4.0.0

Creates an integer flag that accepts whole number input.

Signature

declare function Int(name: string): Flag<number>

Example Creating integer flags

import { Flag } from "effect/cli"
const portFlag = Flag.Int("port")
// Usage: --port 8080
portFlag.kind // => "flag"
Since v4.0.0

Creates a flag that parses key=value pairs.

When to use

Use when you need a CLI flag that accepts one or more key=value configuration entries.

Details

Requires at least one key=value pair. Multiple pairs are merged into a single record.

Signature

declare function KeyValuePair(name: string): Flag<Record<string, string>>

Example Parsing key-value pairs

import { Flag } from "effect/cli"
const env = Flag.KeyValuePair("env")
// --env FOO=bar --env BAZ=qux will parse to { FOO: "bar", BAZ: "qux" }
env.kind // => "flag"

Literals

unstable
Since v4.0.0

Accepts one of the provided strings. An empty array rejects all input.

See

Signature

declare function Literals<Literals extends readonly Array<string>>(name: string, literals: Literals): Flag<Literals[number]>

Never

unstable
Since v4.0.0

A flag that always fails to parse.

Signature

declare const Never: Flag<never>

Example Creating sentinel flags

import { Flag } from "effect/cli"
const makeValueFlag = (includeValue: boolean) =>
includeValue ? Flag.String("value") : Flag.Never
makeValueFlag(true) === Flag.Never // => false
makeValueFlag(false) === Flag.Never // => true

Path

unstable
Since v4.0.0

Creates a path flag that accepts file system path input with validation options.

Signature

declare function Path(name: string, options?: {
readonly mustExist?: boolean;
readonly pathType?: "either" | "file" | "directory";
readonly typeName?: string;
}): Flag<string>

Example Creating path flags

import { Flag } from "effect/cli"
// Basic path flag
const pathFlag = Flag.Path("config-path")
// File-only path that must exist
const fileFlag = Flag.Path("input-file", {
pathType: "file",
mustExist: true
})
// Directory path with custom type name
const dirFlag = Flag.Path("output-dir", {
pathType: "directory",
typeName: "OUTPUT_DIRECTORY"
})
const kinds = [pathFlag.kind, fileFlag.kind, dirFlag.kind] // => ["flag", "flag", "flag"]

Redacted

unstable
Since v4.0.0

Creates a string flag whose parsed value is wrapped in Redacted.Redacted so stringification and logging redact the value.

Gotchas

Values supplied on the command line may still be visible to the operating system or shell history.

Signature

declare function Redacted(name: string): Flag<Redacted<string>>

Example Creating redacted flags

import { Effect, FileSystem, Layer, Path, Redacted, Stdio, Terminal } from "effect"
import { Flag } from "effect/cli"
import { ChildProcessSpawner } from "effect/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 passwordFlag = Flag.Redacted("password")
const program = Effect.gen(function*() {
const [, password] = yield* passwordFlag.parse({
arguments: [],
flags: { "password": ["abc123"] }
})
return Redacted.value(password).length
})
await Effect.runPromise(program.pipe(Effect.provide(CliTestLayer))) // => 6

String

unstable
Since v4.0.0

Creates a string flag that accepts text input.

Signature

declare function String(name: string): Flag<string>

Example Creating string flags

import { Flag } from "effect/cli"
const nameFlag = Flag.String("name")
// Usage: --name "John Doe"
nameFlag.kind // => "flag"

Filtering

filter

unstable
Since v4.0.0

Filters a flag value based on a predicate, failing with a custom error if the predicate returns false.

Signature

declare const filter: {
<A>(predicate: (a: A) => boolean, onFalse: (a: A) => string): (self: Flag<A>) => Flag<A>;
<A>(self: Flag<A>, predicate: (a: A) => boolean, onFalse: (a: A) => string): Flag<A>;
}

Example Filtering parsed values

import { Flag } from "effect/cli"
// Ensure port is in valid range
const portFlag = Flag.Int("port").pipe(
Flag.filter(
(port) => port >= 1 && port <= 65535,
(port) => `Port ${port} is out of range (1-65535)`
)
)
// Ensure non-empty string
const nameFlag = Flag.String("name").pipe(
Flag.filter(
(name) => name.trim().length > 0,
() => "Name cannot be empty"
)
)
const kinds = [portFlag.kind, nameFlag.kind] // => ["flag", "flag"]

filterMap

unstable
Since v4.0.0

Transforms and filters a flag value, failing with a custom error if the transformation returns None.

Signature

declare const filterMap: {
<A, B>(f: (a: A) => Option<B>, onNone: (a: A) => string): (self: Flag<A>) => Flag<B>;
<A, B>(self: Flag<A>, f: (a: A) => Option<B>, onNone: (a: A) => string): Flag<B>;
}

Example Filtering and transforming values

import { Option } from "effect"
import { Flag } from "effect/cli"
// Parse positive integers only
const positiveInt = Flag.Int("count").pipe(
Flag.filterMap(
(n) => n > 0 ? Option.some(n) : Option.none(),
(n) => `Expected positive integer, got ${n}`
)
)
// Parse valid email addresses
const emailFlag = Flag.String("email").pipe(
Flag.filterMap(
(email) => email.includes("@") ? Option.some(email) : Option.none(),
(email) => `Invalid email address: ${email}`
)
)
const kinds = [positiveInt.kind, emailFlag.kind] // => ["flag", "flag"]

Mapping

map

unstable
Since v4.0.0

Transforms the parsed value of a flag using a mapping function.

Signature

declare const map: {
<A, B>(f: (a: A) => B): (self: Flag<A>) => Flag<B>;
<A, B>(self: Flag<A>, f: (a: A) => B): Flag<B>;
}

Example Mapping parsed values

import { Flag } from "effect/cli"
// Convert string to uppercase
const nameFlag = Flag.String("name").pipe(
Flag.map((name) => name.toUpperCase())
)
// Convert port to URL
const urlFlag = Flag.Int("port").pipe(
Flag.map((port) => `http://localhost:${port}`)
)
const kinds = [nameFlag.kind, urlFlag.kind] // => ["flag", "flag"]

mapEffect

unstable
Since v4.0.0

Transforms the parsed value using an Effect that can perform IO operations.

Signature

declare const mapEffect: {
<A, B>(f: (a: A) => Effect<B, CliError, Environment>): (self: Flag<A>) => Flag<B>;
<A, B>(self: Flag<A>, f: (a: A) => Effect<B, CliError, Environment>): Flag<B>;
}

Example Mapping parsed values effectfully

import { Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect"
import { Flag } from "effect/cli"
import { ChildProcessSpawner } from "effect/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 upperName = Flag.String("name").pipe(
Flag.mapEffect((name) => Effect.succeed(name.toUpperCase()))
)
const [, value] = await Effect.runPromise(
upperName.parse({
arguments: [],
flags: { name: ["alice"] }
}).pipe(Effect.provide(CliTestLayer))
)
value // => "ALICE"

mapTryCatch

unstable
Since v4.0.0

Transforms the parsed value using a function that might throw, with error handling.

Signature

declare const mapTryCatch: {
<A, B>(f: (a: A) => B, onError: (error: unknown) => string): (self: Flag<A>) => Flag<B>;
<A, B>(self: Flag<A>, f: (a: A) => B, onError: (error: unknown) => string): Flag<B>;
}

Example Mapping thrown errors

import { Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect"
import { Flag } from "effect/cli"
import { ChildProcessSpawner } from "effect/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"))
)
)
// Parse JSON string with error handling
const jsonFlag = Flag.String("config").pipe(
Flag.mapTryCatch(
(json) => JSON.parse(json),
(error) => `Invalid JSON: ${error}`
)
)
// Parse URL with error handling
const urlFlag = Flag.String("url").pipe(
Flag.mapTryCatch(
(url) => new URL(url),
(error) => `Invalid URL: ${error}`
)
)
const [, value] = await Effect.runPromise(
jsonFlag.parse({
arguments: [],
flags: { config: ['{"enabled":true}'] }
}).pipe(Effect.provide(CliTestLayer))
)
value // => { enabled: true }

Metadata

Since v4.0.0

Adds a description to a flag for help documentation.

Signature

declare const withDescription: {
<A>(description: string): (self: Flag<A>) => Flag<A>;
<A>(self: Flag<A>, description: string): Flag<A>;
}

Example Adding help descriptions

import { Flag } from "effect/cli"
const portFlag = Flag.Int("port").pipe(
Flag.withDescription("The port number to listen on")
)
const configFlag = Flag.File("config").pipe(
Flag.withDescription("Path to the configuration file")
)
const kinds = [portFlag.kind, configFlag.kind] // => ["flag", "flag"]

withHidden

unstable
Since v4.0.0

Hides a flag from generated help output and shell completions while keeping it fully parseable on the command line.

When to use

Use when experimental or internal flags should be accepted but not advertised, such as --experimental-foo, debug toggles, or escape hatches that are not yet committed to the public CLI surface.

Signature

declare function withHidden<A>(self: Flag<A>): Flag<A>

Example Hiding a flag from help

import { Flag } from "effect/cli"
// Flag still parses --experimental-foo, but it does not appear in --help.
const experimental = Flag.Boolean("experimental-foo").pipe(
Flag.withHidden
)
experimental.kind // => "flag"

withMetavar

unstable
Since v4.0.0

Sets a custom metavar (placeholder name) for the flag in help documentation.

Details

The metavar is displayed in usage text to indicate what value the user should provide. For example, --output FILE shows FILE as the metavar.

Signature

declare const withMetavar: {
<A>(metavar: string): (self: Flag<A>) => Flag<A>;
<A>(self: Flag<A>, metavar: string): Flag<A>;
}

Example Setting metavars

import { Flag } from "effect/cli"
const databaseFlag = Flag.String("database-url").pipe(
Flag.withMetavar("URL"),
Flag.withDescription("Database connection URL")
)
// In help: --database-url URL
const timeoutFlag = Flag.Int("timeout").pipe(
Flag.withMetavar("SECONDS")
)
// In help: --timeout SECONDS
const kinds = [databaseFlag.kind, timeoutFlag.kind] // => ["flag", "flag"]

Models

Flag

interface unstable
Since v4.0.0

Represents a command-line flag.

Signature

interface Flag<A> extends Param<typeof Param.flagKind, A> {}

Optionality

optional

unstable
Since v4.0.0

Makes a flag optional, returning an Option type that can be None if not provided.

Signature

declare function optional<A>(param: Flag<A>): Flag<Option<A>>

Example Making flags optional

import { Effect, FileSystem, Layer, Option, Path, Stdio, Terminal } from "effect"
import { Flag } from "effect/cli"
import { ChildProcessSpawner } from "effect/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 optionalPort = Flag.optional(Flag.Int("port"))
const program = Effect.gen(function*() {
const [, port] = yield* optionalPort.parse({
arguments: [],
flags: { "port": ["4000"] }
})
return port
})
await Effect.runPromise(program.pipe(Effect.provide(CliTestLayer))) // => Option.some(4000)

withDefault

unstable
Since v4.0.0

Provides a default value for a flag when it's not specified.

Signature

declare const withDefault: {
<B>(defaultValue: B | Effect<B, CliError, Environment>): <A>(self: Flag<A>) => Flag<B | A>;
<A, B>(self: Flag<A>, defaultValue: B | Effect<B, CliError, Environment>): Flag<A | B>;
}

Example Providing default values

import { Flag } from "effect/cli"
const portFlag = Flag.Int("port").pipe(
Flag.withDefault(8080)
)
// If --port is not provided, defaults to 8080
const hostFlag = Flag.String("host").pipe(
Flag.withDefault("localhost")
)
// If --host is not provided, defaults to "localhost"
const kinds = [portFlag.kind, hostFlag.kind] // => ["flag", "flag"]

Repetition

atLeast

unstable
Since v4.0.0

Ensures a flag is specified at least a minimum number of times.

Signature

declare const atLeast: {
<A>(min: number): (self: Flag<A>) => Flag<readonly Array<A>>;
<A>(self: Flag<A>, min: number): Flag<readonly Array<A>>;
}

Example Requiring repeated values

import { Flag } from "effect/cli"
const sourceFlag = Flag.atLeast(Flag.File("source"), 2)
// Requires at least 2 source files
// Usage: --source file1.ts --source file2.ts
const tagFlag = Flag.String("tag").pipe(
Flag.atLeast(1)
)
// Requires at least 1 tag
const kinds = [sourceFlag.kind, tagFlag.kind] // => ["flag", "flag"]

atMost

unstable
Since v4.0.0

Ensures a flag is specified at most a maximum number of times.

Signature

declare const atMost: {
<A>(max: number): (self: Flag<A>) => Flag<readonly Array<A>>;
<A>(self: Flag<A>, max: number): Flag<readonly Array<A>>;
}

Example Limiting repeated values

import { Flag } from "effect/cli"
const warningFlag = Flag.atMost(Flag.String("warning"), 3)
// Allows up to 3 warning flags
// Usage: --warning w1 --warning w2 --warning w3
const debugFlag = Flag.String("debug").pipe(
Flag.atMost(1)
)
// Allows at most 1 debug flag
const kinds = [warningFlag.kind, debugFlag.kind] // => ["flag", "flag"]

between

unstable
Since v4.0.0

Ensures a flag is specified between a minimum and maximum number of times.

Signature

declare const between: {
<A>(min: number, max: number): (self: Flag<A>) => Flag<readonly Array<A>>;
<A>(self: Flag<A>, min: number, max: number): Flag<readonly Array<A>>;
}

Example Bounding repeated values

import { Flag } from "effect/cli"
const hostFlag = Flag.between(Flag.String("host"), 1, 3)
// Requires 1-3 host flags
// Usage: --host host1 --host host2
const excludeFlag = Flag.String("exclude").pipe(
Flag.between(0, 5)
)
// Allows 0-5 exclude patterns
const kinds = [hostFlag.kind, excludeFlag.kind] // => ["flag", "flag"]

Schemas

withSchema

unstable
Since v4.0.0

Validates and transforms a flag value using a Schema codec.

Signature

declare const withSchema: {
<A, B>(schema: ConstraintCodec<B, A, Environment, unknown>): (self: Flag<A>) => Flag<B>;
<A, B>(self: Flag<A>, schema: ConstraintCodec<B, A, Environment, unknown>): Flag<B>;
}

Example Validating with schemas

import { Schema } from "effect"
import { Flag } from "effect/cli"
const isEmail = Schema.isPattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, {
message: "Must be a valid email address"
})
// Parse and validate email with custom schema
const EmailSchema = Schema.String.pipe(
Schema.check(isEmail)
)
const emailFlag = Flag.String("email").pipe(
Flag.withSchema(EmailSchema)
)
// Parse JSON configuration with schema validation
const ConfigSchema = Schema.Struct({
port: Schema.Number,
host: Schema.String,
ssl: Schema.optional(Schema.Boolean)
}).pipe(Schema.fromJsonString)
const configFlag = Flag.String("config").pipe(
Flag.withSchema(ConfigSchema)
)
const kinds = [emailFlag.kind, configFlag.kind] // => ["flag", "flag"]