prompt

View script Copied!

Interactive prompt with default value and placeholder -- for shell scripts that need to ask the user a question and get back a clean answer in a variable.

Unlike plain read, this gives you a gray placeholder hint that disappears when the user starts typing, and backspace that works the way you'd expect. The result (or default, if they just press Enter) lands directly in a variable you specify.

Must be sourced, not executed. The whole point is to set a variable in your shell, which only works via sourcing (. prompt ...).

Quick start

. prompt USERNAME "What is your username? " "admin"
echo "Hello, $USERNAME"

If the user types alice and presses Enter, $USERNAME becomes alice. If they just press Enter without typing, $USERNAME becomes admin.

Common examples

Prompt with a default, no placeholder override:

. prompt HOST "Enter hostname: " "localhost"
curl "https://$HOST/api/status"

The default localhost appears as a gray placeholder. User can type to replace it, or press Enter to accept it.

Prompt with a custom placeholder that includes the default:

. prompt BRANCH "Branch name: " "main" "e.g. feature/foo (default: %DEFAULT%)"
git checkout "$BRANCH"

The placeholder text e.g. feature/foo (default: main) appears in gray. %DEFAULT% is replaced with the actual default value (main).

Prompt with no default (required input):

. prompt API_KEY "Paste your API key: "
if [ -z "$API_KEY" ]; then
    echo "API key is required" >&2
    exit 1
fi

If the user presses Enter without typing, $API_KEY becomes empty. Your script decides whether that's acceptable.

Yes/no confirmation with default:

. prompt CONFIRM "Continue with deployment? [Y/n] " "Y"
case "$CONFIRM" in
    [Yy]*) echo "Deploying..." ;;
    *) echo "Aborted." ; exit 0 ;;
esac

Reading in a non-interactive context (piped input or redirected stdin):

printf 'my-value\n' | . prompt RESULT "Enter result: " "fallback"
echo "Got: $RESULT"

When stdin isn't a terminal, prompt prints the prompt text (no placeholder) and reads a line. The default still applies if input is empty.

In a script that asks multiple questions:

#!/bin/bash
. prompt NAME "Your name: " "Anonymous"
. prompt EMAIL "Your email: " "user@example.com"
. prompt ROLE "Your role: " "developer" "e.g. developer, designer, manager"

echo "Profile created:"
echo "  Name:  $NAME"
echo "  Email: $EMAIL"
echo "  Role:  $ROLE"

Must be sourced

Executing prompt directly produces an error:

$ prompt VAR "Enter something: "
[ERR][prompt] Must be sourced, not executed. Run `prompt -h` for usage

This is by design. The script needs to set a variable in your shell, which is impossible from a subprocess. Always invoke it via sourcing:

. prompt VAR "Enter something: " "default"

or with the source keyword (equivalent):

source prompt VAR "Enter something: " "default"

Raw-mode editing

When stdin is a terminal (interactive use), prompt switches to raw mode for character-at-a-time input. This gives you:

The placeholder is purely cosmetic -- it's not part of the input buffer. When the user starts typing, it vanishes and is replaced by their actual input.

Ctrl-C is a no-op

During the prompt, prompt ignores SIGINT and SIGTERM entirely. Ctrl-C does nothing -- to dismiss the prompt, press Enter (which accepts the default, if one was provided). Once prompt finishes, normal signal handling resumes.

This is a deliberate trade-off, not a feature. If Ctrl-C reaches the outer shell, readline's signal-cleanup path can race with our terminal-state restore and leave the shell unable to echo typed characters. Ignoring the signal is the simplest reliable workaround.

Non-TTY fallback

When stdin is not a terminal (piped input, redirected from a file, or running in a CI environment), prompt skips raw mode entirely:

  1. Prints the prompt text to stdout (no placeholder)
  2. Does a plain read -r to grab a line
  3. Uses the default if input is empty

This means scripts using prompt stay usable in automated contexts:

printf 'automated-value\n' | ./my-script.sh

If your script redirects stdin from /dev/null and the prompt hits EOF, the default is used.


Reference

All options

Flag Description
variable Shell variable name to store the result (required)
prompt Text displayed before input (optional, e.g. "Name: ")
default Value used when user presses Enter without typing (optional)
placeholder Gray hint text shown in place of default; %DEFAULT% is replaced with the actual default value. If omitted, the default itself is used as the placeholder (optional)
-h, --help Show help message

Positional arguments

Arguments are positional, in this order:

. prompt <variable> [prompt] [default] [placeholder]

Exit codes

Code Meaning
0 Success (user provided input or default was used)
2 Usage error (script was executed rather than sourced)

Dependencies

Warnings