Collection of common interactive command line user interface prompts for gathering input from users.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Collection 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;
}