CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-inquirer--prompts

Collection of common interactive command line user interface prompts for gathering input from users.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

@inquirer/prompts

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.

Package Information

  • Package Name: @inquirer/prompts
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @inquirer/prompts

Core Imports

import { 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 prompt

Basic Usage

import { 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?' });

Architecture

@inquirer/prompts is built around several key concepts:

  • Unified API: All prompts follow consistent patterns for configuration and usage
  • TypeScript-First: Full type safety with generic support for custom value types
  • Theming System: Comprehensive theme customization for visual styling
  • Context Options: Runtime configuration for input/output streams and behavior
  • Validation Framework: Built-in and custom validation with async support
  • Accessibility: Screen reader support and keyboard navigation

Context Options

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)
  }
);

Capabilities

Text Input

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>>;
}

Single Selection

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>>;
}

Multiple Selection

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>>;
}

Boolean Confirmation

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>;
}

Password Input

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>;
}

Number Input

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>;
}

External Editor

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>>;
}

Expandable List

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;
}

Raw List

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>;
}

Search

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>>;
}

Types

Common Choice Interface

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;
}

Separator

Visual separator for organizing choices:

class Separator {
  constructor(separator?: string);
  separator: string;
  
  static isSeparator(choice: unknown): choice is Separator;
}

Theme System

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];
};

Prompt-Specific Theme Extensions

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';
}

Advanced Usage Examples

Conditional Questions

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'
  });
}

Async Search

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
    }));
  }
});

Custom Theming

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}:`
    }
  }
});

Cancellation with AbortSignal

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 }
);

Node.js Requirements

  • Minimum Node Version: 18+
  • Peer Dependencies: @types/node (optional for TypeScript projects)
  • Core Dependencies: All prompts depend on @inquirer/core and @inquirer/type

Error Handling

Prompts may throw errors in various scenarios:

  • ExitPromptError: User pressed Ctrl+C to exit
  • AbortPromptError: Prompt was cancelled via AbortSignal
  • ValidationError: Configuration validation failed (e.g., no selectable choices)

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;
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@inquirer/prompts@7.8.x
Publish Source
CLI
Badge
tessl/npm-inquirer--prompts badge