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 ...).
. 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.
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"
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"
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.
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.
When stdin is not a terminal (piped input, redirected from a file, or running in a CI environment), prompt skips raw mode entirely:
read -r to grab a lineThis 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.
| 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 |
Arguments are positional, in this order:
. prompt <variable> [prompt] [default] [placeholder]
variable is given, you get a silent prompt with no text and no default.prompt is given but default is omitted, user must provide input (pressing Enter yields an empty string).placeholder is omitted, the default value is shown as the placeholder.placeholder is given, any %DEFAULT% inside it is replaced with the default value.| Code | Meaning |
|---|---|
| 0 | Success (user provided input or default was used) |
| 2 | Usage error (script was executed rather than sourced) |
stty – used to put the terminal in raw mode for the inline placeholder and backspace handling. When stdin is not a terminal (piped or redirected input), raw mode is skipped and a plain read is used instead, so stty is not required in that path.my-var), the eval will fail with a syntax error.$MYVAR already exists, sourcing prompt MYVAR ... replaces its value.read -n and ${var:?} syntax.