inquirer-prompt-generator — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited inquirer-prompt-generator (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Generate 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 documentationimport { 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;
});~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.