Arguments & flags
Declare typed positional arguments and flags, give them defaults, make them optional or variadic, and validate their values. Read more
The effect/unstable/cli modules let you build command-line applications the
same way you build the rest of an Effect program: declaratively, with typed
inputs and effectful handlers. You describe a command’s positional arguments
and named flags as Param values, attach a handler written with
Effect.fn, and Effect takes care of parsing process.argv, validating inputs,
generating help text, and reporting friendly errors.
Because handlers are ordinary Effects, everything you already know carries over: you can access services, acquire scoped resources, fail with typed errors, and provide Layers — all from inside a command.
import { NodeRuntime, NodeServices } from "@effect/platform-node"import { Console, Effect } from "effect"import { Argument, Command, Flag } from "effect/unstable/cli"
// A command pairs a typed config (its arguments and flags) with a handler.const greet = Command.make( "greet", { // A required positional argument: `greet Alice` name: Argument.string("name").pipe( Argument.withDescription("Who to greet") ), // A flag with a default, so `--count` is optional: `greet Alice --count 3` count: Flag.integer("count").pipe( Flag.withAlias("c"), Flag.withDescription("How many times to greet"), Flag.withDefault(1) ) }, // The handler receives the parsed, fully-typed config. Writing it with // `Effect.fn` means it is a normal Effect — it can use services and fail. Effect.fn(function*({ name, count }) { for (let i = 0; i < count; i++) { yield* Console.log(`Hello, ${name}!`) } }))
// `Command.run` turns a command into an Effect that reads argv, parses it, and// dispatches to the handler. `--help` and `--version` are wired up for free.greet.pipe( Command.run({ version: "1.0.0" }), // Provide the services for your target platform (file system, stdin/stdout…). Effect.provide(NodeServices.layer), NodeRuntime.runMain)Run it with node app.ts Alice --count 2 and it prints Hello, Alice! twice.
Run node app.ts --help and Effect prints generated usage and option docs.
Flag — named options like --count 3 or -c 3. Flags are optional by
default once you give them a default; otherwise they are required (boolean
flags are an exception: a bare boolean flag defaults to false).Argument — positional operands like the Alice above. Order matters and
they are matched left to right.Command — bundles a config of flags and arguments with a handler, and
can compose child commands into a tree of subcommands.Both Flag and Argument are built on the shared Param type, so the same
combinators (withDefault, optional, map, withSchema, …) work on either.
Arguments & flags
Declare typed positional arguments and flags, give them defaults, make them optional or variadic, and validate their values. Read more
Subcommands
Compose child commands into a single executable, share parent flags, and read parent input from inside a subcommand. Read more
Command.run produces a plain Effect. To execute it you provide the platform
services it needs (Stdio, FileSystem, …) and hand it to a runtime. On
Node.js that is NodeServices.layer plus NodeRuntime.runMain, as shown above.
See Platform for other runtimes and what each layer provides.