Назад към всички

inquirer-prompt-generator

// Generate interactive command-line prompts using Inquirer.js with validation, conditional logic, and custom renderers. Creates user-friendly input collection flows for CLI applications.

$ git log --oneline --stat
stars:384
forks:73
updated:March 4, 2026
SKILL.mdreadonly
SKILL.md Frontmatter
nameinquirer-prompt-generator
descriptionGenerate interactive command-line prompts using Inquirer.js with validation, conditional logic, and custom renderers. Creates user-friendly input collection flows for CLI applications.
allowed-toolsRead, Write, Edit, Bash, Glob, Grep

Inquirer Prompt Generator

Generate interactive CLI prompts using Inquirer.js with comprehensive validation, conditional flows, and custom formatting.

Capabilities

  • Generate Inquirer.js prompt definitions
  • Create multi-step wizard flows
  • Implement input validation
  • Support conditional prompts
  • Generate TypeScript interfaces for answers
  • Create custom prompt formatters

Usage

Invoke this skill when you need to:

  • Create interactive CLI input collection
  • Build configuration wizards
  • Implement user confirmation flows
  • Generate form-like CLI interfaces

Inputs

ParameterTypeRequiredDescription
flowNamestringYesName of the prompt flow
promptsarrayYesList of prompt definitions
typescriptbooleanNoGenerate TypeScript types (default: true)
validationbooleanNoInclude validation helpers (default: true)

Prompt Definition Structure

{
  "prompts": [
    {
      "type": "input",
      "name": "projectName",
      "message": "What is your project name?",
      "default": "my-project",
      "validate": {
        "required": true,
        "pattern": "^[a-z][a-z0-9-]*$",
        "message": "Project name must be lowercase with hyphens"
      }
    },
    {
      "type": "list",
      "name": "template",
      "message": "Select a template:",
      "choices": [
        { "name": "React + TypeScript", "value": "react-ts" },
        { "name": "Vue + TypeScript", "value": "vue-ts" },
        { "name": "Node.js + Express", "value": "node-express" }
      ]
    },
    {
      "type": "checkbox",
      "name": "features",
      "message": "Select features to include:",
      "choices": ["ESLint", "Prettier", "Husky", "Jest", "Docker"],
      "when": "answers.template !== 'node-express'"
    },
    {
      "type": "confirm",
      "name": "installDeps",
      "message": "Install dependencies now?",
      "default": true
    }
  ]
}

Output Structure

prompts/
├── <flowName>/
│   ├── index.ts              # Main prompt flow
│   ├── types.ts              # TypeScript interfaces
│   ├── validators.ts         # Validation functions
│   ├── formatters.ts         # Custom formatters
│   └── README.md             # Usage documentation

Generated Code Patterns

Prompt Flow (index.ts)

import { input, select, checkbox, confirm } from '@inquirer/prompts';
import { validateProjectName, validatePort } from './validators';
import type { ProjectConfig } from './types';

export async function createProjectPrompt(): Promise<ProjectConfig> {
  // Project name
  const projectName = await input({
    message: 'What is your project name?',
    default: 'my-project',
    validate: validateProjectName,
  });

  // Template selection
  const template = await select({
    message: 'Select a template:',
    choices: [
      { name: 'React + TypeScript', value: 'react-ts' },
      { name: 'Vue + TypeScript', value: 'vue-ts' },
      { name: 'Node.js + Express', value: 'node-express' },
    ],
  });

  // Conditional features (not shown for node-express)
  let features: string[] = [];
  if (template !== 'node-express') {
    features = await checkbox({
      message: 'Select features to include:',
      choices: [
        { name: 'ESLint', value: 'eslint', checked: true },
        { name: 'Prettier', value: 'prettier', checked: true },
        { name: 'Husky', value: 'husky' },
        { name: 'Jest', value: 'jest' },
        { name: 'Docker', value: 'docker' },
      ],
    });
  }

  // Confirmation
  const installDeps = await confirm({
    message: 'Install dependencies now?',
    default: true,
  });

  return {
    projectName,
    template,
    features,
    installDeps,
  };
}

TypeScript Types (types.ts)

/**
 * Configuration collected from create-project prompts
 */
export interface ProjectConfig {
  /** Project name (lowercase, hyphens allowed) */
  projectName: string;

  /** Selected project template */
  template: 'react-ts' | 'vue-ts' | 'node-express';

  /** Selected optional features */
  features: Array<'eslint' | 'prettier' | 'husky' | 'jest' | 'docker'>;

  /** Whether to install dependencies */
  installDeps: boolean;
}

/**
 * Template metadata for display
 */
export interface TemplateChoice {
  name: string;
  value: ProjectConfig['template'];
  description?: string;
}

Validators (validators.ts)

/**
 * Validate project name format
 * - Must start with lowercase letter
 * - Only lowercase letters, numbers, and hyphens
 * - Max 50 characters
 */
export function validateProjectName(value: string): string | true {
  if (!value.trim()) {
    return 'Project name is required';
  }

  if (!/^[a-z][a-z0-9-]*$/.test(value)) {
    return 'Project name must start with a letter and contain only lowercase letters, numbers, and hyphens';
  }

  if (value.length > 50) {
    return 'Project name must be 50 characters or less';
  }

  return true;
}

/**
 * Validate port number
 */
export function validatePort(value: string): string | true {
  const port = parseInt(value, 10);

  if (isNaN(port)) {
    return 'Port must be a number';
  }

  if (port < 1024 || port > 65535) {
    return 'Port must be between 1024 and 65535';
  }

  return true;
}

/**
 * Validate URL format
 */
export function validateUrl(value: string): string | true {
  try {
    new URL(value);
    return true;
  } catch {
    return 'Please enter a valid URL';
  }
}

/**
 * Create async validator that checks for conflicts
 */
export function createConflictValidator(
  checkFn: (value: string) => Promise<boolean>
): (value: string) => Promise<string | true> {
  return async (value: string) => {
    const exists = await checkFn(value);
    if (exists) {
      return `"${value}" already exists`;
    }
    return true;
  };
}

Custom Formatters (formatters.ts)

import chalk from 'chalk';

/**
 * Format project name for display
 */
export function formatProjectName(value: string): string {
  return chalk.cyan(value);
}

/**
 * Format feature list for summary
 */
export function formatFeatures(features: string[]): string {
  if (features.length === 0) {
    return chalk.dim('None selected');
  }
  return features.map(f => chalk.green(`+ ${f}`)).join('\n');
}

/**
 * Format configuration summary
 */
export function formatSummary(config: ProjectConfig): string {
  return `
${chalk.bold('Project Configuration:')}

  ${chalk.dim('Name:')}     ${formatProjectName(config.projectName)}
  ${chalk.dim('Template:')} ${config.template}
  ${chalk.dim('Features:')}
${formatFeatures(config.features).split('\n').map(l => '    ' + l).join('\n')}
  ${chalk.dim('Install:')}  ${config.installDeps ? chalk.green('Yes') : chalk.yellow('No')}
`;
}

Prompt Types

TypeDescriptionUse Case
inputSingle-line textNames, values
passwordHidden inputSecrets, tokens
numberNumeric inputPorts, counts
confirmYes/NoConfirmations
selectSingle choice listOptions
checkboxMultiple choiceFeatures
expandAbbreviated choicesQuick actions
editorMulti-line editorLong text
searchSearchable listLarge lists
rawlistNumbered listIndexed options

Validation Patterns

Required Field

validate: (value) => value.trim() ? true : 'This field is required'

Pattern Matching

validate: (value) => /^[a-z-]+$/.test(value) || 'Invalid format'

Async Validation

validate: async (value) => {
  const exists = await checkExists(value);
  return exists ? 'Already exists' : true;
}

Dependent Validation

validate: (value, answers) => {
  if (answers.type === 'advanced' && !value) {
    return 'Required for advanced mode';
  }
  return true;
}

Conditional Prompts

When Function

{
  type: 'input',
  name: 'apiKey',
  message: 'Enter API key:',
  when: (answers) => answers.useExternalApi
}

Skip Logic

const prompts = basePrompts.filter(p => {
  if (p.name === 'advanced' && !options.showAdvanced) {
    return false;
  }
  return true;
});

Workflow

  1. Parse prompt definitions - Validate structure
  2. Generate prompt flow - Create main prompt file
  3. Generate types - TypeScript interfaces
  4. Generate validators - Validation functions
  5. Generate formatters - Display helpers
  6. Create documentation - Usage guide

Best Practices Applied

  • Modern @inquirer/prompts API
  • Reusable validation functions
  • Type-safe answer interfaces
  • Conditional flow support
  • Custom formatters for output
  • Clear error messages

References

Target Processes

  • interactive-prompt-system
  • interactive-form-implementation
  • cli-application-bootstrap