Collection of common interactive command line user interface prompts for gathering input from users.
npx @tessl/cli install tessl/npm-inquirer--prompts@7.8.0Collection of common interactive command line user interface prompts for gathering input from users. Inquirer.js provides a powerful, modern toolkit for building CLI applications with rich user interactions, featuring 10 specialized prompt types with full TypeScript support and extensive customization options.
npm install @inquirer/promptsimport { input, select, checkbox, confirm, password, editor, expand, rawlist, search, number, Separator } from '@inquirer/prompts';For CommonJS:
const { input, select, checkbox, confirm, password, editor, expand, rawlist, search, number, Separator } = require('@inquirer/prompts');Individual prompt imports are also supported:
import input from '@inquirer/input';
import select from '@inquirer/select';
import checkbox, { Separator } from '@inquirer/checkbox';
// ... etc for each promptimport { input, select, checkbox, confirm } from '@inquirer/prompts';
// Text input
const name = await input({ message: 'Enter your name:' });
// Single selection
const framework = await select({
message: 'Choose a framework:',
choices: ['React', 'Vue', 'Angular', 'Svelte']
});
// Multiple selection
const features = await checkbox({
message: 'Select features:',
choices: [
{ name: 'TypeScript', value: 'typescript' },
{ name: 'ESLint', value: 'eslint' },
{ name: 'Testing', value: 'testing' }
]
});
// Boolean confirmation
const proceed = await confirm({ message: 'Continue with installation?' });@inquirer/prompts is built around several key concepts:
All prompts accept an optional second parameter for runtime configuration:
interface PromptContext {
/** The stdin stream (defaults to process.stdin) */
input?: NodeJS.ReadableStream;
/** The stdout stream (defaults to process.stdout) */
output?: NodeJS.WritableStream;
/** Clear the screen after the prompt is answered */
clearPromptOnDone?: boolean;
/** AbortSignal to cancel prompts asynchronously */
signal?: AbortSignal;
}Usage Example:
import { confirm } from '@inquirer/prompts';
const answer = await confirm(
{ message: 'Continue?' },
{
clearPromptOnDone: true,
signal: AbortSignal.timeout(5000)
}
);Collects single-line text input with validation and transformation support.
function input(config: InputConfig, context?: PromptContext): Promise<string>;
interface InputConfig {
/** The question message to display */
message: string;
/** Default value */
default?: string;
/** How to handle default value ('tab' to fill on tab, 'editable' to prefill) */
prefill?: 'tab' | 'editable';
/** Require non-empty input */
required?: boolean;
/** Transform display value during input and final answer */
transformer?: (value: string, { isFinal }: { isFinal: boolean }) => string;
/** Validation function */
validate?: (value: string) => boolean | string | Promise<string | boolean>;
/** Theme customization */
theme?: PartialDeep<Theme<InputTheme>>;
}Choose one item from a list with arrow key navigation and search.
function select<Value>(config: SelectConfig<Value>, context?: PromptContext): Promise<Value>;
interface SelectConfig<Value> {
/** The question message to display */
message: string;
/** Array of choices */
choices: ReadonlyArray<Choice<Value> | Separator>;
/** Number of choices to display per page */
pageSize?: number;
/** Enable/disable looping through choices with arrow keys */
loop?: boolean;
/** Default selected value */
default?: unknown;
/** Custom instruction messages */
instructions?: { navigation: string; pager: string };
/** Theme customization */
theme?: PartialDeep<Theme<SelectTheme>>;
}Choose multiple items from a list with checkbox-style selection.
function checkbox<Value>(config: CheckboxConfig<Value>, context?: PromptContext): Promise<Array<Value>>;
interface CheckboxConfig<Value> {
/** The question message to display */
message: string;
/** Array of choices */
choices: ReadonlyArray<Choice<Value> | Separator>;
/** Custom prefix for the prompt */
prefix?: string;
/** Number of choices to display per page */
pageSize?: number;
/** Custom instructions or boolean to show/hide default instructions */
instructions?: string | boolean;
/** Enable/disable looping through choices */
loop?: boolean;
/** Require at least one selection */
required?: boolean;
/** Validation function for selected choices */
validate?: (choices: ReadonlyArray<Choice<Value>>) => boolean | string | Promise<string | boolean>;
/** Keyboard shortcuts configuration */
shortcuts?: { all?: string | null; invert?: string | null };
/** Theme customization */
theme?: PartialDeep<Theme<CheckboxTheme>>;
}Ask yes/no questions with customizable display.
function confirm(config: ConfirmConfig, context?: PromptContext): Promise<boolean>;
interface ConfirmConfig {
/** The question message to display */
message: string;
/** Default answer (true for Y/n, false for y/N) */
default?: boolean;
/** Transform the boolean result for display */
transformer?: (value: boolean) => string;
/** Theme customization */
theme?: PartialDeep<Theme>;
}Secure password entry with optional masking.
function password(config: PasswordConfig, context?: PromptContext): Promise<string>;
interface PasswordConfig {
/** The question message to display */
message: string;
/** Show mask characters (true='*', string=custom char, false=hidden) */
mask?: boolean | string;
/** Validation function */
validate?: (value: string) => boolean | string | Promise<string | boolean>;
/** Theme customization */
theme?: PartialDeep<Theme>;
}Numeric input with built-in validation for ranges and constraints.
function number<Required extends boolean = true>(config: NumberConfig<Required>, context?: PromptContext): Promise<Required extends true ? number : number | undefined>;
interface NumberConfig<Required extends boolean = true> {
/** The question message to display */
message: string;
/** Default numeric value */
default?: number;
/** Minimum allowed value */
min?: number;
/** Maximum allowed value */
max?: number;
/** Step increment for validation */
step?: number | 'any';
/** Require a numeric value */
required?: Required;
/** Custom validation function */
validate?: (value: number | undefined) => boolean | string | Promise<string | boolean>;
/** Theme customization */
theme?: PartialDeep<Theme>;
}Launch external editor for multi-line text input.
function editor(config: EditorConfig, context?: PromptContext): Promise<string>;
interface EditorConfig {
/** The question message to display */
message: string;
/** Default text content for the editor */
default?: string;
/** File extension for temporary file */
postfix?: string;
/** Wait for user to press Enter before launching editor */
waitForUseInput?: boolean;
/** Validation function for editor content */
validate?: (value: string) => boolean | string | Promise<string | boolean>;
/** Theme customization */
theme?: PartialDeep<Theme<EditorTheme>>;
}Compact single-key selection that expands to show full choices.
function expand<Value>(config: ExpandConfig<Value>, context?: PromptContext): Promise<Value>;
interface ExpandConfig<Value> {
/** The question message to display */
message: string;
/** Array of choices with key mappings */
choices: ReadonlyArray<ExpandChoice<Value> | Separator>;
/** Default key selection */
default?: Key | 'h';
/** Start in expanded mode */
expanded?: boolean;
/** Theme customization */
theme?: PartialDeep<Theme>;
}
interface ExpandChoice<Value> {
/** Single character key (a-z, 0-9, excluding 'h') */
key: Key;
/** Choice value */
value: Value;
/** Display name (optional, defaults to string version of value) */
name?: string;
}Number-indexed list selection with key input support.
function rawlist<Value>(config: RawlistConfig<Value>, context?: PromptContext): Promise<Value>;
interface RawlistConfig<Value> {
/** The question message to display */
message: string;
/** Array of choices */
choices: ReadonlyArray<Choice<Value> | Separator>;
/** Enable/disable looping through choices with arrow keys */
loop?: boolean;
/** Theme customization */
theme?: PartialDeep<Theme>;
}Live search with asynchronous source function and filtering.
function search<Value>(config: SearchConfig<Value>, context?: PromptContext): Promise<Value>;
interface SearchConfig<Value> {
/** The question message to display */
message: string;
/** Async function that returns filtered choices based on search term */
source: (term: string | undefined, opt: { signal: AbortSignal }) => Promise<ReadonlyArray<Choice<Value> | Separator>>;
/** Validation function for selected value */
validate?: (value: Value) => boolean | string | Promise<string | boolean>;
/** Number of choices to display per page */
pageSize?: number;
/** Custom instruction messages */
instructions?: { navigation: string; pager: string };
/** Theme customization */
theme?: PartialDeep<Theme<SearchTheme>>;
}Used by multi-choice prompts (select, checkbox, rawlist, search):
interface Choice<Value> {
/** Choice value (required) */
value: Value;
/** Display name (optional, defaults to string version of value) */
name?: string;
/** Additional description text */
description?: string;
/** Short display text for final answer */
short?: string;
/** Disable choice selection */
disabled?: boolean | string;
/** Pre-checked state for checkbox */
checked?: boolean;
}Visual separator for organizing choices:
class Separator {
constructor(separator?: string);
separator: string;
static isSeparator(choice: unknown): choice is Separator;
}All prompts support comprehensive theme customization:
interface Theme<T = {}> {
/** Prefix displayed before the prompt */
prefix: string | { idle: string; done: string };
/** Spinner configuration for loading states */
spinner: { interval: number; frames: string[] };
/** Style functions for different prompt elements */
style: {
/** Style the final answer display */
answer: (text: string) => string;
/** Style the prompt message based on current status */
message: (text: string, status: Status) => string;
/** Style error messages */
error: (text: string) => string;
/** Style help text */
help: (text: string) => string;
/** Style highlighted/active items */
highlight: (text: string) => string;
/** Style keyboard shortcut keys */
key: (text: string) => string;
/** Style the default value indicator */
defaultAnswer: (text: string) => string;
} & T;
}
type Status = 'idle' | 'done' | 'loading';
type PartialDeep<T> = {
[P in keyof T]?: T[P] extends object ? PartialDeep<T[P]> : T[P];
};interface CheckboxTheme {
icon: { checked: string; unchecked: string; cursor: string };
style: {
disabledChoice: (text: string) => string;
renderSelectedChoices: <T>(selectedChoices: ReadonlyArray<Choice<T>>, allChoices: ReadonlyArray<Choice<T> | Separator>) => string;
description: (text: string) => string;
};
helpMode: 'always' | 'never' | 'auto';
}
interface SelectTheme {
icon: { cursor: string };
style: {
disabled: (text: string) => string;
description: (text: string) => string;
};
helpMode: 'always' | 'never' | 'auto';
indexMode: 'hidden' | 'number';
}
interface InputTheme {
validationFailureMode: 'keep' | 'clear';
}
interface EditorTheme {
validationFailureMode: 'keep' | 'clear';
}
interface SearchTheme {
icon: { cursor: string };
style: {
disabled: (text: string) => string;
searchTerm: (text: string) => string;
description: (text: string) => string;
};
helpMode: 'always' | 'never' | 'auto';
}import { confirm, input } from '@inquirer/prompts';
const needsEmail = await confirm({ message: 'Do you want email notifications?' });
let email;
if (needsEmail) {
email = await input({
message: 'Enter your email:',
validate: (input) => input.includes('@') || 'Please enter a valid email'
});
}import { search } from '@inquirer/prompts';
const user = await search({
message: 'Select a user:',
source: async (term) => {
const users = await fetchUsers(term); // Your API call
return users.map(user => ({
name: `${user.name} (${user.email})`,
value: user.id,
description: user.role
}));
}
});import { select } from '@inquirer/prompts';
const choice = await select({
message: 'Choose an option:',
choices: ['Option 1', 'Option 2', 'Option 3'],
theme: {
prefix: '🎯',
style: {
answer: (text) => `✅ ${text}`,
highlight: (text) => `🔸 ${text}`,
message: (text) => `${text}:`
}
}
});import { input } from '@inquirer/prompts';
// Timeout after 10 seconds
const name = await input(
{ message: 'Enter your name:' },
{ signal: AbortSignal.timeout(10000) }
).catch((error) => {
if (error.name === 'AbortPromptError') {
return 'Default Name';
}
throw error;
});
// Manual cancellation
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
const answer = await input(
{ message: 'Quick question:' },
{ signal: controller.signal }
);Prompts may throw errors in various scenarios:
Handle these gracefully in your applications:
try {
const answer = await input({ message: 'Enter something:' });
} catch (error) {
if (error.name === 'ExitPromptError') {
console.log('User cancelled');
process.exit(0);
}
throw error;
}