Generate interactive command-line prompts using Inquirer.js with validation, conditional logic, and custom renderers. Creates user-friendly input collection flows for CLI applications.
Generates interactive CLI prompts with validation, conditional logic, and custom formatting using Inquirer.js.
npx claudepluginhub a5c-ai/babysitterThis skill is limited to using the following tools:
README.mdGenerate interactive CLI prompts using Inquirer.js with comprehensive validation, conditional flows, and custom formatting.
Invoke this skill when you need to:
| 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) |
{
"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
}
]
}
prompts/
├── <flowName>/
│ ├── index.ts # Main prompt flow
│ ├── types.ts # TypeScript interfaces
│ ├── validators.ts # Validation functions
│ ├── formatters.ts # Custom formatters
│ └── README.md # Usage documentation
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,
};
}
/**
* 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;
}
/**
* 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;
};
}
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')}
`;
}
| 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 |
validate: (value) => value.trim() ? true : 'This field is required'
validate: (value) => /^[a-z-]+$/.test(value) || 'Invalid format'
validate: async (value) => {
const exists = await checkExists(value);
return exists ? 'Already exists' : true;
}
validate: (value, answers) => {
if (answers.type === 'advanced' && !value) {
return 'Required for advanced mode';
}
return true;
}
{
type: 'input',
name: 'apiKey',
message: 'Enter API key:',
when: (answers) => answers.useExternalApi
}
const prompts = basePrompts.filter(p => {
if (p.name === 'advanced' && !options.showAdvanced) {
return false;
}
return true;
});
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.