# CLI

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](https://effect.plants.sh/services-and-layers/) — all from inside a command.

```ts
// app.ts
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.
**Note:** The CLI modules live under `effect/unstable/cli`. Unstable modules are usable
today but their API may still change between minor versions before they
stabilize.

## How the pieces fit together

- **`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.
- **`Prompt`** — interactive input read from the terminal (text, password,
  confirm, select, multi-select, and more) for when a value was not supplied on
  the command line.
- **`GlobalFlag`** — the built-in `--help`, `--version`, and `--completions`
  flags, plus a way to define your own global flags and settings (like
  `--log-level`) that apply across the whole command tree.
- **`Completions`** — generates shell completion scripts (bash, zsh, fish) from
  your command tree, surfaced through the `--completions` global flag.
- **`CliOutput`** — the formatter that renders help text and error messages; swap
  it out to customize coloring and layout.

Both `Flag` and `Argument` are built on the shared `Param` type, so the same
combinators (`withDefault`, `optional`, `map`, `withSchema`, …) work on either.

## Command lifecycle

A command moves through three steps, each backed by a `Command` API:

- **`Command.make`** pairs a config (its flags and arguments) with a handler.
  Write the handler with `Effect.fn` so it stays a normal Effect — it can use
  services, acquire resources, and fail with typed errors. You can also attach
  the handler later with `Command.withHandler`.
- **`Command.run`** turns the command into an `Effect`. It reads the process
  argument vector from the `Stdio` service, lexes and parses it, applies global
  flags like `--help`/`--version`, and dispatches to the matching handler.
- **`Command.runWith`** does the same but takes an explicit `ReadonlyArray<string>`
  of arguments instead of reading `Stdio`. This is what you use in tests to
  exercise a command with specific argv without a real terminal.

```ts
import { Effect } from "effect"
import { Command, Flag } from "effect/unstable/cli"

const greet = Command.make("greet", {
  name: Flag.string("name")
}, ({ name }) => Effect.log(`Hello, ${name}!`))

// In a test: feed argv directly, no Stdio needed.
const run = Command.runWith(greet, { version: "1.0.0" })
// `program` is an Effect; running it logs "Hello, Alice!"
const program = run(["--name", "Alice"])
```

## In this section
**Arguments & flags**
Declare typed positional arguments and flags, give them defaults, make them
    optional or variadic, and validate their values.
    [Read more](https://effect.plants.sh/cli/arguments-and-flags/)

**Subcommands**
Compose child commands into a single executable, share parent flags, and
    read parent input from inside a subcommand.
    [Read more](https://effect.plants.sh/cli/subcommands/)

**Prompts**
Ask for input interactively — text, password, confirm, select,
    multi-select, and more — when a value was not passed on the command line.
    [Read more](https://effect.plants.sh/cli/prompts/)

**Global flags & completions**
The built-in `--help`, `--version`, and `--completions` flags, custom global
    flags and settings, and generating shell completion scripts.
    [Read more](https://effect.plants.sh/cli/global-flags-and-completions/)

**Output & errors**
How help text and parse errors are formatted, and how to customize the
    output formatter.
    [Read more](https://effect.plants.sh/cli/output-and-errors/)

## Running on a platform

`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](https://effect.plants.sh/platform/) for other runtimes and what each layer provides.