0
# @inquirer/prompts
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: @inquirer/prompts
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @inquirer/prompts`
10
11
## Core Imports
12
13
```typescript
14
import { input, select, checkbox, confirm, password, editor, expand, rawlist, search, number, Separator } from '@inquirer/prompts';
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { input, select, checkbox, confirm, password, editor, expand, rawlist, search, number, Separator } = require('@inquirer/prompts');
21
```
22
23
Individual prompt imports are also supported:
24
25
```typescript
26
import input from '@inquirer/input';
27
import select from '@inquirer/select';
28
import checkbox, { Separator } from '@inquirer/checkbox';
29
// ... etc for each prompt
30
```
31
32
## Basic Usage
33
34
```typescript
35
import { input, select, checkbox, confirm } from '@inquirer/prompts';
36
37
// Text input
38
const name = await input({ message: 'Enter your name:' });
39
40
// Single selection
41
const framework = await select({
42
message: 'Choose a framework:',
43
choices: ['React', 'Vue', 'Angular', 'Svelte']
44
});
45
46
// Multiple selection
47
const features = await checkbox({
48
message: 'Select features:',
49
choices: [
50
{ name: 'TypeScript', value: 'typescript' },
51
{ name: 'ESLint', value: 'eslint' },
52
{ name: 'Testing', value: 'testing' }
53
]
54
});
55
56
// Boolean confirmation
57
const proceed = await confirm({ message: 'Continue with installation?' });
58
```
59
60
## Architecture
61
62
@inquirer/prompts is built around several key concepts:
63
64
- **Unified API**: All prompts follow consistent patterns for configuration and usage
65
- **TypeScript-First**: Full type safety with generic support for custom value types
66
- **Theming System**: Comprehensive theme customization for visual styling
67
- **Context Options**: Runtime configuration for input/output streams and behavior
68
- **Validation Framework**: Built-in and custom validation with async support
69
- **Accessibility**: Screen reader support and keyboard navigation
70
71
## Context Options
72
73
All prompts accept an optional second parameter for runtime configuration:
74
75
```typescript { .api }
76
interface PromptContext {
77
/** The stdin stream (defaults to process.stdin) */
78
input?: NodeJS.ReadableStream;
79
/** The stdout stream (defaults to process.stdout) */
80
output?: NodeJS.WritableStream;
81
/** Clear the screen after the prompt is answered */
82
clearPromptOnDone?: boolean;
83
/** AbortSignal to cancel prompts asynchronously */
84
signal?: AbortSignal;
85
}
86
```
87
88
**Usage Example:**
89
90
```typescript
91
import { confirm } from '@inquirer/prompts';
92
93
const answer = await confirm(
94
{ message: 'Continue?' },
95
{
96
clearPromptOnDone: true,
97
signal: AbortSignal.timeout(5000)
98
}
99
);
100
```
101
102
## Capabilities
103
104
### Text Input
105
106
Collects single-line text input with validation and transformation support.
107
108
```typescript { .api }
109
function input(config: InputConfig, context?: PromptContext): Promise<string>;
110
111
interface InputConfig {
112
/** The question message to display */
113
message: string;
114
/** Default value */
115
default?: string;
116
/** How to handle default value ('tab' to fill on tab, 'editable' to prefill) */
117
prefill?: 'tab' | 'editable';
118
/** Require non-empty input */
119
required?: boolean;
120
/** Transform display value during input and final answer */
121
transformer?: (value: string, { isFinal }: { isFinal: boolean }) => string;
122
/** Validation function */
123
validate?: (value: string) => boolean | string | Promise<string | boolean>;
124
/** Theme customization */
125
theme?: PartialDeep<Theme<InputTheme>>;
126
}
127
```
128
129
### Single Selection
130
131
Choose one item from a list with arrow key navigation and search.
132
133
```typescript { .api }
134
function select<Value>(config: SelectConfig<Value>, context?: PromptContext): Promise<Value>;
135
136
interface SelectConfig<Value> {
137
/** The question message to display */
138
message: string;
139
/** Array of choices */
140
choices: ReadonlyArray<Choice<Value> | Separator>;
141
/** Number of choices to display per page */
142
pageSize?: number;
143
/** Enable/disable looping through choices with arrow keys */
144
loop?: boolean;
145
/** Default selected value */
146
default?: unknown;
147
/** Custom instruction messages */
148
instructions?: { navigation: string; pager: string };
149
/** Theme customization */
150
theme?: PartialDeep<Theme<SelectTheme>>;
151
}
152
```
153
154
### Multiple Selection
155
156
Choose multiple items from a list with checkbox-style selection.
157
158
```typescript { .api }
159
function checkbox<Value>(config: CheckboxConfig<Value>, context?: PromptContext): Promise<Array<Value>>;
160
161
interface CheckboxConfig<Value> {
162
/** The question message to display */
163
message: string;
164
/** Array of choices */
165
choices: ReadonlyArray<Choice<Value> | Separator>;
166
/** Custom prefix for the prompt */
167
prefix?: string;
168
/** Number of choices to display per page */
169
pageSize?: number;
170
/** Custom instructions or boolean to show/hide default instructions */
171
instructions?: string | boolean;
172
/** Enable/disable looping through choices */
173
loop?: boolean;
174
/** Require at least one selection */
175
required?: boolean;
176
/** Validation function for selected choices */
177
validate?: (choices: ReadonlyArray<Choice<Value>>) => boolean | string | Promise<string | boolean>;
178
/** Keyboard shortcuts configuration */
179
shortcuts?: { all?: string | null; invert?: string | null };
180
/** Theme customization */
181
theme?: PartialDeep<Theme<CheckboxTheme>>;
182
}
183
```
184
185
### Boolean Confirmation
186
187
Ask yes/no questions with customizable display.
188
189
```typescript { .api }
190
function confirm(config: ConfirmConfig, context?: PromptContext): Promise<boolean>;
191
192
interface ConfirmConfig {
193
/** The question message to display */
194
message: string;
195
/** Default answer (true for Y/n, false for y/N) */
196
default?: boolean;
197
/** Transform the boolean result for display */
198
transformer?: (value: boolean) => string;
199
/** Theme customization */
200
theme?: PartialDeep<Theme>;
201
}
202
```
203
204
### Password Input
205
206
Secure password entry with optional masking.
207
208
```typescript { .api }
209
function password(config: PasswordConfig, context?: PromptContext): Promise<string>;
210
211
interface PasswordConfig {
212
/** The question message to display */
213
message: string;
214
/** Show mask characters (true='*', string=custom char, false=hidden) */
215
mask?: boolean | string;
216
/** Validation function */
217
validate?: (value: string) => boolean | string | Promise<string | boolean>;
218
/** Theme customization */
219
theme?: PartialDeep<Theme>;
220
}
221
```
222
223
### Number Input
224
225
Numeric input with built-in validation for ranges and constraints.
226
227
```typescript { .api }
228
function number<Required extends boolean = true>(config: NumberConfig<Required>, context?: PromptContext): Promise<Required extends true ? number : number | undefined>;
229
230
interface NumberConfig<Required extends boolean = true> {
231
/** The question message to display */
232
message: string;
233
/** Default numeric value */
234
default?: number;
235
/** Minimum allowed value */
236
min?: number;
237
/** Maximum allowed value */
238
max?: number;
239
/** Step increment for validation */
240
step?: number | 'any';
241
/** Require a numeric value */
242
required?: Required;
243
/** Custom validation function */
244
validate?: (value: number | undefined) => boolean | string | Promise<string | boolean>;
245
/** Theme customization */
246
theme?: PartialDeep<Theme>;
247
}
248
```
249
250
### External Editor
251
252
Launch external editor for multi-line text input.
253
254
```typescript { .api }
255
function editor(config: EditorConfig, context?: PromptContext): Promise<string>;
256
257
interface EditorConfig {
258
/** The question message to display */
259
message: string;
260
/** Default text content for the editor */
261
default?: string;
262
/** File extension for temporary file */
263
postfix?: string;
264
/** Wait for user to press Enter before launching editor */
265
waitForUseInput?: boolean;
266
/** Validation function for editor content */
267
validate?: (value: string) => boolean | string | Promise<string | boolean>;
268
/** Theme customization */
269
theme?: PartialDeep<Theme<EditorTheme>>;
270
}
271
```
272
273
### Expandable List
274
275
Compact single-key selection that expands to show full choices.
276
277
```typescript { .api }
278
function expand<Value>(config: ExpandConfig<Value>, context?: PromptContext): Promise<Value>;
279
280
interface ExpandConfig<Value> {
281
/** The question message to display */
282
message: string;
283
/** Array of choices with key mappings */
284
choices: ReadonlyArray<ExpandChoice<Value> | Separator>;
285
/** Default key selection */
286
default?: Key | 'h';
287
/** Start in expanded mode */
288
expanded?: boolean;
289
/** Theme customization */
290
theme?: PartialDeep<Theme>;
291
}
292
293
interface ExpandChoice<Value> {
294
/** Single character key (a-z, 0-9, excluding 'h') */
295
key: Key;
296
/** Choice value */
297
value: Value;
298
/** Display name (optional, defaults to string version of value) */
299
name?: string;
300
}
301
```
302
303
### Raw List
304
305
Number-indexed list selection with key input support.
306
307
```typescript { .api }
308
function rawlist<Value>(config: RawlistConfig<Value>, context?: PromptContext): Promise<Value>;
309
310
interface RawlistConfig<Value> {
311
/** The question message to display */
312
message: string;
313
/** Array of choices */
314
choices: ReadonlyArray<Choice<Value> | Separator>;
315
/** Enable/disable looping through choices with arrow keys */
316
loop?: boolean;
317
/** Theme customization */
318
theme?: PartialDeep<Theme>;
319
}
320
```
321
322
### Search
323
324
Live search with asynchronous source function and filtering.
325
326
```typescript { .api }
327
function search<Value>(config: SearchConfig<Value>, context?: PromptContext): Promise<Value>;
328
329
interface SearchConfig<Value> {
330
/** The question message to display */
331
message: string;
332
/** Async function that returns filtered choices based on search term */
333
source: (term: string | undefined, opt: { signal: AbortSignal }) => Promise<ReadonlyArray<Choice<Value> | Separator>>;
334
/** Validation function for selected value */
335
validate?: (value: Value) => boolean | string | Promise<string | boolean>;
336
/** Number of choices to display per page */
337
pageSize?: number;
338
/** Custom instruction messages */
339
instructions?: { navigation: string; pager: string };
340
/** Theme customization */
341
theme?: PartialDeep<Theme<SearchTheme>>;
342
}
343
```
344
345
## Types
346
347
### Common Choice Interface
348
349
Used by multi-choice prompts (select, checkbox, rawlist, search):
350
351
```typescript { .api }
352
interface Choice<Value> {
353
/** Choice value (required) */
354
value: Value;
355
/** Display name (optional, defaults to string version of value) */
356
name?: string;
357
/** Additional description text */
358
description?: string;
359
/** Short display text for final answer */
360
short?: string;
361
/** Disable choice selection */
362
disabled?: boolean | string;
363
/** Pre-checked state for checkbox */
364
checked?: boolean;
365
}
366
```
367
368
### Separator
369
370
Visual separator for organizing choices:
371
372
```typescript { .api }
373
class Separator {
374
constructor(separator?: string);
375
separator: string;
376
377
static isSeparator(choice: unknown): choice is Separator;
378
}
379
```
380
381
### Theme System
382
383
All prompts support comprehensive theme customization:
384
385
```typescript { .api }
386
interface Theme<T = {}> {
387
/** Prefix displayed before the prompt */
388
prefix: string | { idle: string; done: string };
389
/** Spinner configuration for loading states */
390
spinner: { interval: number; frames: string[] };
391
/** Style functions for different prompt elements */
392
style: {
393
/** Style the final answer display */
394
answer: (text: string) => string;
395
/** Style the prompt message based on current status */
396
message: (text: string, status: Status) => string;
397
/** Style error messages */
398
error: (text: string) => string;
399
/** Style help text */
400
help: (text: string) => string;
401
/** Style highlighted/active items */
402
highlight: (text: string) => string;
403
/** Style keyboard shortcut keys */
404
key: (text: string) => string;
405
/** Style the default value indicator */
406
defaultAnswer: (text: string) => string;
407
} & T;
408
}
409
410
type Status = 'idle' | 'done' | 'loading';
411
412
type PartialDeep<T> = {
413
[P in keyof T]?: T[P] extends object ? PartialDeep<T[P]> : T[P];
414
};
415
```
416
417
### Prompt-Specific Theme Extensions
418
419
```typescript { .api }
420
interface CheckboxTheme {
421
icon: { checked: string; unchecked: string; cursor: string };
422
style: {
423
disabledChoice: (text: string) => string;
424
renderSelectedChoices: <T>(selectedChoices: ReadonlyArray<Choice<T>>, allChoices: ReadonlyArray<Choice<T> | Separator>) => string;
425
description: (text: string) => string;
426
};
427
helpMode: 'always' | 'never' | 'auto';
428
}
429
430
interface SelectTheme {
431
icon: { cursor: string };
432
style: {
433
disabled: (text: string) => string;
434
description: (text: string) => string;
435
};
436
helpMode: 'always' | 'never' | 'auto';
437
indexMode: 'hidden' | 'number';
438
}
439
440
interface InputTheme {
441
validationFailureMode: 'keep' | 'clear';
442
}
443
444
interface EditorTheme {
445
validationFailureMode: 'keep' | 'clear';
446
}
447
448
interface SearchTheme {
449
icon: { cursor: string };
450
style: {
451
disabled: (text: string) => string;
452
searchTerm: (text: string) => string;
453
description: (text: string) => string;
454
};
455
helpMode: 'always' | 'never' | 'auto';
456
}
457
```
458
459
## Advanced Usage Examples
460
461
### Conditional Questions
462
463
```typescript
464
import { confirm, input } from '@inquirer/prompts';
465
466
const needsEmail = await confirm({ message: 'Do you want email notifications?' });
467
468
let email;
469
if (needsEmail) {
470
email = await input({
471
message: 'Enter your email:',
472
validate: (input) => input.includes('@') || 'Please enter a valid email'
473
});
474
}
475
```
476
477
### Async Search
478
479
```typescript
480
import { search } from '@inquirer/prompts';
481
482
const user = await search({
483
message: 'Select a user:',
484
source: async (term) => {
485
const users = await fetchUsers(term); // Your API call
486
return users.map(user => ({
487
name: `${user.name} (${user.email})`,
488
value: user.id,
489
description: user.role
490
}));
491
}
492
});
493
```
494
495
### Custom Theming
496
497
```typescript
498
import { select } from '@inquirer/prompts';
499
500
const choice = await select({
501
message: 'Choose an option:',
502
choices: ['Option 1', 'Option 2', 'Option 3'],
503
theme: {
504
prefix: '๐ฏ',
505
style: {
506
answer: (text) => `โ ${text}`,
507
highlight: (text) => `๐ธ ${text}`,
508
message: (text) => `${text}:`
509
}
510
}
511
});
512
```
513
514
### Cancellation with AbortSignal
515
516
```typescript
517
import { input } from '@inquirer/prompts';
518
519
// Timeout after 10 seconds
520
const name = await input(
521
{ message: 'Enter your name:' },
522
{ signal: AbortSignal.timeout(10000) }
523
).catch((error) => {
524
if (error.name === 'AbortPromptError') {
525
return 'Default Name';
526
}
527
throw error;
528
});
529
530
// Manual cancellation
531
const controller = new AbortController();
532
setTimeout(() => controller.abort(), 5000);
533
534
const answer = await input(
535
{ message: 'Quick question:' },
536
{ signal: controller.signal }
537
);
538
```
539
540
## Node.js Requirements
541
542
- **Minimum Node Version**: 18+
543
- **Peer Dependencies**: @types/node (optional for TypeScript projects)
544
- **Core Dependencies**: All prompts depend on @inquirer/core and @inquirer/type
545
546
## Error Handling
547
548
Prompts may throw errors in various scenarios:
549
550
- **ExitPromptError**: User pressed Ctrl+C to exit
551
- **AbortPromptError**: Prompt was cancelled via AbortSignal
552
- **ValidationError**: Configuration validation failed (e.g., no selectable choices)
553
554
Handle these gracefully in your applications:
555
556
```typescript
557
try {
558
const answer = await input({ message: 'Enter something:' });
559
} catch (error) {
560
if (error.name === 'ExitPromptError') {
561
console.log('User cancelled');
562
process.exit(0);
563
}
564
throw error;
565
}
566
```