A prompt is an input, and painted's CLI grammar already has an input channel: declared flags. --force and 'Are you sure? [y/N]' are the same declaration at different fidelities — one resolves from argv, one resolves interactively at a TTY. A declared prompt is the parser's fourth reflection, after parse, help, and completion: one declaration generates a flag, a rendered question, an honest refusal, and completion of its answer values.
Declare a prompt beside your tags and it generates its own flag, its own -h entry, and completion of its answer values — with zero prompt-specific code in any of the three. At a TTY, the same declaration renders and reads an answer; everywhere else, it resolves from the flag or the declared default and leaves one line of proof.
✓ force: no (default) ✓ scope: local (default)
Every prompt resolves the same four-step ladder, declared or asked at runtime: the argv flag first (it's already visible in the invocation), then an interactive prompt at a TTY, then the declared default, then an honest refusal. A script without a flag or a default never hangs and never invents an answer — it gets a ContractError naming the exact flag that would resolve it.
stdin is not a terminal and no answer was provided for 'overwrite' — pass `--overwrite` / `--no-overwrite`
The prompt UI draws on stderr, never stdout, so `tool --json | jq` stays parseable even when the tool asked a question mid-run. And a prompt never forces an environment rewrite: it renders at whatever rung the terminal supports — a raw-mode cursor at a real TTY, a cooked-mode y/n on a dumb terminal or screen reader, or no interaction at all in a script — and every rung answers the same question the same way.
clig.dev names 'conversation as the norm' as a tenet no standalone prompt library can fully honor, because an honest refusal must name the flag that answers the question — and the flag lives in the application's parser. painted is a prompt library and a CLI framework in one package, so it holds both ends.
default= fires on absence of a terminal, not on EOF — a deliberate break from the ecosystem, where 'the value on bare Enter' and 'the value when nobody answers' are conflated. EOF (Ctrl-D) and Ctrl-C take the identical abort path at every rung: never an answer, never a silent fall-through to the default.
Full design: docs/PROMPTS_DESIGN.md.