# Prompts

> Ask people for text, passwords, choices and confirmations, with each answer also taken from a flag, so scripts and agents never wait for input.

This guide covers prompts. You will learn how to:

- Ask for text, with a default and validation
- Ask for a password
- Offer a list of choices
- Ask for confirmation
- Run Commands with nobody to answer
- Ask follow-up questions only when they help

## Overview

A prompt asks a person for something the command line didn't give, such as a title or which database to use. Every prompt is answered by a flag the Command declares, which makes the same answer something you can always pass instead:

- When the command line, or the flag's environment variable, gives the flag, the prompt returns its value without asking.
- When nobody can answer, the prompt returns the flag's default. A required prompt without one fails with an error naming the flag to pass. Nobody can answer in [Agent mode](../../reference/agent-mode.md), with `--no-interaction`, or when stdin or stderr isn't a terminal, as in CI.
- Otherwise it asks, and sets the flag to the answer, so the variable bound to the flag holds it.

Prompts take the context `Run` received, so Ctrl+C ends a prompt and the Command exits with status `130`.

## Ask for text

`c.Input` asks for a line of text, answered by the flag you name. The flag's default is the default answer, which the person accepts by pressing Enter:

```go
		Flags: func(f *cli.FlagSet) {
			f.StringVar(&title, "title", "", "The post's title")
		},
		Run: func(ctx context.Context, c *cli.Call) (cli.Result, error) {
			title, err := c.Input(ctx, "title", "What is the post's title?", cli.Required())
			if err != nil {
				return nil, err
			}
			…
		},
```

```text title="Output"
? What is the post's title? Hello, world
```

### Validate answers

`cli.Required()` refuses an empty answer, and `cli.Validate` checks each answer with your function. A person sees the error and is asked again; a flag that fails the check is a usage error:

```go
			title, err := c.Input(ctx, "title", "What is the post's title?", cli.Required(), cli.Validate(func(s string) error {
				if len(s) > 80 {
					return errors.New("keep it under 80 characters")
				}
				return nil
			}))
```

The answer is parsed as the flag's type, so a prompt for an `int` flag refuses an answer that isn't a number, and the variable bound to the flag holds the number.

## Ask for a password

`c.Password` asks for a secret without showing what the person types. Give its flag an environment variable with `Env`, so scripts pass the secret without putting it on the command line, where other users of the machine can see it:

```go
			f.StringVar(&token, "token", "", "The API token")
			f.Env("token", "API_TOKEN")
```

```go
			token, err := c.Password(ctx, "token", "Your API token?", cli.Required())
```

Errors never include the secret.

## Offer choices

`c.Select` asks the person to choose one of a list, with the arrow keys and Enter. The flag's default is selected first, and a value passed on the command line must be one of the choices:

```go
			f.StringVar(&db, "db", "sqlite", "The database")
```

```go
			db, err := c.Select(ctx, "db", "Which database?", []string{"sqlite", "postgres", "mysql"})
```

```text title="Output"
? Which database? (↑/↓ and Enter)
❯ sqlite
  postgres
  mysql
```

In a terminal that can't move the cursor (`TERM=dumb`), the choices are numbered and the person types a number.

## Ask for confirmation

`c.Confirm` asks a yes or no question, answered by a bool flag. When nobody can answer, it returns the flag's default, which is false unless you declare otherwise, so nothing is confirmed without a person or the flag:

```go
			f.BoolVar(&force, "force", false, "Overwrite an existing file")
```

```go
			if _, err := os.Stat(path); err == nil {
				ok, err := c.Confirm(ctx, "force", "Overwrite "+path+"?")
				if err != nil {
					return nil, err
				}
				if !ok {
					return nil, &cli.Error{Code: "exists", Message: path + " already exists", Fix: "Pass --force to overwrite it"}
				}
			}
```

```text title="Output"
? Overwrite app/controllers/posts.go? (y/N)
```

## Run with nobody to answer

In Agent mode, with `--no-interaction`, or without a terminal, a prompt answers itself from its flag, and a required prompt with no value fails with exit status `2` and the flag to pass:

```text title="Output"
$ act make:controller posts --no-interaction
Error: --title is required.
  No one can answer the prompt "What is the post's title?" here
  Fix: Pass --title=<value>
```

Agents get the same error as JSON, with the code `missing_flag`, and retry with the flag.

## Ask follow-up questions only when they help

`c.Given()` reports whether the person passed any flag, and `c.Interactive()` whether a person can answer at all. Ask optional follow-up questions only when both say so: someone who passed flags has shown what they want, and a script has nobody to ask:

```go
			if !c.Given() && c.Interactive() {
				if _, err := c.Confirm(ctx, "resource", "Add the resource actions?"); err != nil {
					return nil, err
				}
			}
```

See also: [Flags](flags.md), [Testing Commands](testing.md), [Agent mode](../../reference/agent-mode.md)
