# CLI apps

`args()` is the argument list. `std/args` reads flags and options from it, and `std/cli` builds the whole command from a record type.

## Reading arguments

[std/args](https://vyrn-lang.github.io/docs/std/args.html) takes a token list. `cli()` takes the real arguments; `cliOf(list)` takes a list you supply, which is how a test checks the parsing without a process.

`flag` asks whether a token is present. `opt` reads `--name=value` and `--name value`, and answers `Option<String>`. `positionals` returns what is left, and `rest` returns what follows `--`.

```vyrn
// `std/args` reads a token list. `cli()` takes the real arguments; `cliOf` takes
// a list you hand it, which is what a test does.
import { cliOf, flag, opt, positionals } from "std/args"
import { joinWith } from "std/strings"

export fn demo() -> String {
    let a = cliOf(["--verbose", "--port=8080", "site", "docs"])
    let port = match opt(a, "--port") {
        Some(v) => v,
        None => "none",
    }
    let short = flag(a, "-v")
    let long = flag(a, "--verbose")
    let rest = joinWith(positionals(a), ", ")

    return joinWith([
        "-v          \{short}",
        "--verbose   \{long}",
        "port        \{port}",
        "positionals \{rest}",
    ], "\n")
}

fn main() -> Int64 {
    print(demo())
    return 0
}
```

Built output:

```
-v          false
--verbose   true
port        8080
positionals site, docs
```

## std/cli

[std/cli](https://vyrn-lang.github.io/docs/std/cli.html) goes further. Declare a record whose fields are the options, and give each field a validated type with its own documentation line. `cli("./module")` reflects it into a parser and a help text, so no flag name is written twice.

A parse answers `Valid` or `Invalid` with the issues attached to their fields, so a program reports every problem at once instead of the first one.

---

From https://vyrn-lang.github.io/guide/cli.html — generated by `site/export.vyrn` from the Vyrn repository.
