| name | inquirer-patterns |
| description | Interactive prompt patterns for CLI tools with text, list, checkbox, password, autocomplete, and conditional questions. Use when building CLIs with user input, creating interactive prompts, implementing questionnaires, or when user mentions inquirer, prompts, interactive input, CLI questions, user prompts. |
| allowed-tools | Read, Write, Bash |
Inquirer Patterns
Comprehensive interactive prompt patterns for building CLI tools with rich user input capabilities. Provides templates for text, list, checkbox, password, autocomplete, and conditional questions in both Node.js and Python.
Instructions
When Building Interactive CLI Prompts
-
Identify prompt type needed:
- Text input: Simple string input
- List selection: Single choice from options
- Checkbox: Multiple selections
- Password: Secure input (hidden)
- Autocomplete: Type-ahead suggestions
- Conditional: Questions based on previous answers
-
Choose language:
- Node.js: Use templates in
templates/nodejs/
- Python: Use templates in
templates/python/
-
Select appropriate template:
text-prompt.js/py - Basic text input
list-prompt.js/py - Single selection list
checkbox-prompt.js/py - Multiple selections
password-prompt.js/py - Secure password input
autocomplete-prompt.js/py - Type-ahead suggestions
conditional-prompt.js/py - Dynamic questions based on answers
comprehensive-example.js/py - All patterns combined
-
Install required dependencies:
- Node.js: Run
scripts/install-nodejs-deps.sh
- Python: Run
scripts/install-python-deps.sh
-
Test prompts:
- Use examples in
examples/nodejs/ or examples/python/
- Run validation script:
scripts/validate-prompts.sh
-
Customize for your CLI:
- Copy relevant template sections
- Modify questions, choices, validation
- Add custom conditional logic
Node.js Implementation
Library: inquirer (v9.x)
Installation:
npm install inquirer
Basic Usage:
import inquirer from 'inquirer';
const answers = await inquirer.prompt([
{
type: 'input',
name: 'username',
message: 'Enter your username:',
validate: (input) => input.length > 0 || 'Username required'
}
]);
console.log(`Hello, ${answers.username}!`);
Python Implementation
Library: questionary (v2.x)
Installation:
pip install questionary
Basic Usage:
import questionary
username = questionary.text(
"Enter your username:",
validate=lambda text: len(text) > 0 or "Username required"
).ask()
print(f"Hello, {username}!")
Available Templates
Node.js Templates (templates/nodejs/)
- text-prompt.js - Text input with validation
- list-prompt.js - Single selection from list
- checkbox-prompt.js - Multiple selections
- password-prompt.js - Secure password input with confirmation
- autocomplete-prompt.js - Type-ahead with fuzzy search
- conditional-prompt.js - Dynamic questions based on answers
- comprehensive-example.js - Complete CLI questionnaire
Python Templates (templates/python/)
- text_prompt.py - Text input with validation
- list_prompt.py - Single selection from list
- checkbox_prompt.py - Multiple selections
- password_prompt.py - Secure password input with confirmation
- autocomplete_prompt.py - Type-ahead with fuzzy search
- conditional_prompt.py - Dynamic questions based on answers
- comprehensive_example.py - Complete CLI questionnaire
Prompt Types Reference
Text Input
- Use for: Names, emails, URLs, paths, free-form text
- Features: Validation, default values, transform
- Node.js:
{ type: 'input' }
- Python:
questionary.text()
List Selection
- Use for: Single choice from predefined options
- Features: Arrow key navigation, search filtering
- Node.js:
{ type: 'list' }
- Python:
questionary.select()
Checkbox
- Use for: Multiple selections from options
- Features: Space to toggle, Enter to confirm
- Node.js:
{ type: 'checkbox' }
- Python:
questionary.checkbox()
Password
- Use for: Sensitive input (credentials, tokens)
- Features: Hidden input, confirmation, validation
- Node.js:
{ type: 'password' }
- Python:
questionary.password()
Autocomplete
- Use for: Large option lists with search
- Features: Type-ahead, fuzzy matching, suggestions
- Node.js:
inquirer-autocomplete-prompt plugin
- Python:
questionary.autocomplete()
Conditional Questions
- Use for: Dynamic forms based on previous answers
- Features: Skip logic, dependent questions, branching
- Node.js:
when property in question config
- Python: Conditional logic with if statements
Validation Patterns
Email Validation
validate: (input) => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(input) || 'Invalid email address';
}
def validate_email(text):
import re
regex = r'^[^\s@]+@[^\s@]+\.[^\s@]+$'
return bool(re.match(regex, text)) or "Invalid email address"
questionary.text("Email:", validate=validate_email).ask()
Non-Empty Validation
validate: (input) => input.length > 0 || 'This field is required'
questionary.text("Name:", validate=lambda t: len(t) > 0 or "Required").ask()
Numeric Range Validation
validate: (input) => {
const num = parseInt(input);
return (num >= 1 && num <= 100) || 'Enter number between 1-100';
}
def validate_range(text):
try:
num = int(text)
return 1 <= num <= 100 or "Enter number between 1-100"
except ValueError:
return "Invalid number"
questionary.text("Number:", validate=validate_range).ask()
Examples
Example 1: Project Initialization Wizard
Use case: Interactive CLI for scaffolding new projects
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'Project name:',
validate: (input) => /^[a-z0-9-]+$/.test(input) || 'Invalid project name'
},
{
type: 'list',
name: 'framework',
message: 'Choose framework:',
choices: ['React', 'Vue', 'Angular', 'Svelte']
},
{
type: 'checkbox',
name: 'features',
message: 'Select features:',
choices: ['TypeScript', 'ESLint', 'Prettier', 'Testing']
}
]);
import questionary
project_name = questionary.text(
"Project name:",
validate=lambda t: bool(re.match(r'^[a-z0-9-]+$', t)) or "Invalid name"
).ask()
framework = questionary.select(
"Choose framework:",
choices=['React', 'Vue', 'Angular', 'Svelte']
).ask()
features = questionary.checkbox(
"Select features:",
choices=['TypeScript', 'ESLint', 'Prettier', 'Testing']
).ask()
Example 2: Conditional Question Flow
Use case: Dynamic questions based on previous answers
const questions = [
{
type: 'confirm',
name: 'useDatabase',
message: 'Use database?',
default: true
},
{
type: 'list',
name: 'dbType',
message: 'Database type:',
choices: ['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite'],
when: (answers) => answers.useDatabase
},
{
type: 'input',
name: 'dbHost',
message: 'Database host:',
default: 'localhost',
when: (answers) => answers.useDatabase && answers.dbType !== 'SQLite'
}
];
use_database = questionary.confirm("Use database?", default=True).ask()
if use_database:
db_type = questionary.select(
"Database type:",
choices=['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite']
).ask()
if db_type != 'SQLite':
db_host = questionary.text(
"Database host:",
default="localhost"
).ask()
Example 3: Password with Confirmation
Use case: Secure password input with validation and confirmation
const answers = await inquirer.prompt([
{
type: 'password',
name: 'password',
message: 'Enter password:',
validate: (input) => input.length >= 8 || 'Password must be 8+ characters'
},
{
type: 'password',
name: 'confirmPassword',
message: 'Confirm password:',
validate: (input, answers) => {
return input === answers.password || 'Passwords do not match';
}
}
]);
password = questionary.password(
"Enter password:",
validate=lambda t: len(t) >= 8 or "Password must be 8+ characters"
).ask()
confirm = questionary.password(
"Confirm password:",
validate=lambda t: t == password or "Passwords do not match"
).ask()
Scripts
Install Dependencies
Node.js:
./scripts/install-nodejs-deps.sh
Python:
./scripts/install-python-deps.sh
Validate Prompts
./scripts/validate-prompts.sh [nodejs|python]
Generate Prompt Code
./scripts/generate-prompt.sh --type [text|list|checkbox|password] --lang [js|py]
Best Practices
- Always validate user input - Prevent invalid data early
- Provide clear messages - Use descriptive prompt text
- Set sensible defaults - Reduce friction for common cases
- Use conditional logic - Skip irrelevant questions
- Group related questions - Keep context together
- Handle Ctrl+C gracefully - Catch interrupts and exit cleanly
- Test interactively - Run examples to verify UX
- Provide help text - Add descriptions for complex prompts
Common Patterns
CLI Configuration Generator
const config = await inquirer.prompt([
{ type: 'input', name: 'appName', message: 'App name:' },
{ type: 'input', name: 'version', message: 'Version:', default: '1.0.0' },
{ type: 'list', name: 'env', message: 'Environment:', choices: ['dev', 'prod'] },
{ type: 'confirm', name: 'debug', message: 'Enable debug?', default: false }
]);
Multi-Step Installation Wizard
components = questionary.checkbox(
"Select components:",
choices=['Core', 'CLI', 'Web UI', 'API']
).ask()
for component in components:
print(f"\nConfiguring {component}...")
Error Recovery
try {
const answers = await inquirer.prompt(questions);
} catch (error) {
if (error.isTtyError) {
console.error('Prompt could not be rendered in this environment');
} else {
console.error('User interrupted prompt');
}
process.exit(1);
}
Requirements
- Node.js: v14+ with ESM support
- Python: 3.7+ with pip
- Dependencies:
- Node.js:
inquirer@^9.0.0, inquirer-autocomplete-prompt@^3.0.0
- Python:
questionary@^2.0.0, prompt_toolkit@^3.0.0
Troubleshooting
Node.js Issues
Problem: Error [ERR_REQUIRE_ESM]
Solution: Use import instead of require, or add "type": "module" to package.json
Problem: Autocomplete not working
Solution: Install inquirer-autocomplete-prompt plugin
Python Issues
Problem: No module named 'questionary'
Solution: Run pip install questionary
Problem: Prompt rendering issues
Solution: Ensure terminal supports ANSI escape codes
Purpose: Provide reusable interactive prompt patterns for CLI development
Load when: Building CLIs with user input, creating interactive questionnaires, implementing wizards