Agent Skills: 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.

UncategorizedID: a5c-ai/babysitter/inquirer-prompt-generator

Install this agent skill to your local

pnpm dlx add-skill https://github.com/a5c-ai/babysitter/tree/HEAD/plugins/babysitter/skills/babysit/process/specializations/cli-mcp-development/skills/inquirer-prompt-generator

Skill Files

Browse the full folder contents for inquirer-prompt-generator.

Download Skill

Loading file tree…

plugins/babysitter/skills/babysit/process/specializations/cli-mcp-development/skills/inquirer-prompt-generator/SKILL.md

Skill Metadata

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

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

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | flowName | string | Yes | Name of the prompt flow | | prompts | array | Yes | List of prompt definitions | | typescript | boolean | No | Generate TypeScript types (default: true) | | validation | boolean | No | Include 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

| Type | Description | Use Case | |------|-------------|----------| | input | Single-line text | Names, values | | password | Hidden input | Secrets, tokens | | number | Numeric input | Ports, counts | | confirm | Yes/No | Confirmations | | select | Single choice list | Options | | checkbox | Multiple choice | Features | | expand | Abbreviated choices | Quick actions | | editor | Multi-line editor | Long text | | search | Searchable list | Large lists | | rawlist | Numbered list | Indexed 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

  • Inquirer.js: https://github.com/SBoudrias/Inquirer.js
  • @inquirer/prompts: https://www.npmjs.com/package/@inquirer/prompts
  • Chalk: https://github.com/chalk/chalk

Target Processes

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