Node's first framework for building immersive CLI apps.
—
Terminal UI management including show/hide prompt, logging, user interaction through prompts, and advanced UI redraw functionality.
Shows the Vorpal prompt in the terminal.
/**
* Shows the vorpal prompt in the terminal
* @returns Vorpal instance for chaining
*/
function show(): Vorpal;Usage Example:
const vorpal = require('vorpal')();
// Setup commands first
vorpal
.command('hello', 'Says hello')
.action(function(args, callback) {
this.log('Hello World!');
callback();
});
// Show the interactive prompt
vorpal
.delimiter('myapp$')
.show();Hides the Vorpal prompt from the terminal.
/**
* Hides the vorpal prompt from the terminal
* @returns Vorpal instance for chaining
*/
function hide(): Vorpal;Usage Example:
const vorpal = require('vorpal')();
// Show the prompt initially
vorpal.show();
// Later, hide it during some operation
vorpal.hide();
// Processing something in background...
setTimeout(() => {
console.log('Background task completed');
// Show the prompt again
vorpal.show();
}, 2000);Logs output to the console through Vorpal's logging system.
/**
* Logs output to console through Vorpal's logging system
* @param args - Arguments to log (same as console.log)
* @returns Vorpal instance for chaining
*/
function log(...args: any[]): Vorpal;Usage Examples:
const vorpal = require('vorpal')();
// Basic logging
vorpal.log('Hello, world!');
// Multiple arguments
vorpal.log('User:', 'john', 'Age:', 25);
// Logging objects
vorpal.log('Config:', { port: 3000, env: 'development' });
// In command actions
vorpal
.command('status', 'Shows application status')
.action(function(args, callback) {
// Use this.log within command context
this.log('Application is running');
this.log('Status: OK');
// Or use vorpal.log from outside
callback();
});Prompts the user for input with configurable options.
/**
* Prompts user for input
* @param options - Prompt configuration object or array of prompts
* @param userCallback - Optional callback function (if omitted, returns Promise)
* @returns Promise when no callback provided
*/
function prompt(options?: PromptOptions | PromptOptions[], userCallback?: (result: any) => void): Promise<any>;
interface PromptOptions {
type?: 'input' | 'password' | 'confirm' | 'list' | 'rawlist' | 'expand' | 'checkbox' | 'editor';
name?: string;
message?: string;
default?: any;
choices?: string[] | ChoiceOption[];
validate?: (input: any) => boolean | string;
filter?: (input: any) => any;
when?: boolean | ((answers: any) => boolean);
}
interface ChoiceOption {
name: string;
value?: any;
short?: string;
}Usage Examples:
const vorpal = require('vorpal')();
// Single input prompt with callback
vorpal.prompt({
type: 'input',
name: 'username',
message: 'Enter your username:',
default: 'guest'
}, function(result) {
console.log('Username:', result.username);
});
// Promise-based prompting
vorpal.prompt({
type: 'password',
name: 'password',
message: 'Enter your password:'
})
.then(function(result) {
console.log('Password length:', result.password.length);
});
// Multiple prompts
vorpal.prompt([
{
type: 'input',
name: 'name',
message: 'What is your name?'
},
{
type: 'list',
name: 'color',
message: 'What is your favorite color?',
choices: ['Red', 'Blue', 'Green', 'Yellow']
},
{
type: 'confirm',
name: 'confirmed',
message: 'Are you sure?',
default: true
}
])
.then(function(answers) {
console.log('Name:', answers.name);
console.log('Color:', answers.color);
console.log('Confirmed:', answers.confirmed);
});
// Validation example
vorpal.prompt({
type: 'input',
name: 'email',
message: 'Enter your email:',
validate: function(input) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(input)) {
return 'Please enter a valid email address';
}
return true;
}
})
.then(function(result) {
console.log('Valid email:', result.email);
});
// Using within command actions
vorpal
.command('setup', 'Interactive setup')
.action(function(args, callback) {
const self = this;
self.prompt([
{
type: 'input',
name: 'appName',
message: 'Application name:'
},
{
type: 'list',
name: 'environment',
message: 'Select environment:',
choices: ['development', 'staging', 'production']
}
], function(result) {
self.log(`Setting up ${result.appName} for ${result.environment}`);
callback();
});
});Advanced prompting with conditional logic:
vorpal.prompt([
{
type: 'confirm',
name: 'needsDatabase',
message: 'Do you need a database?'
},
{
type: 'list',
name: 'databaseType',
message: 'Select database type:',
choices: ['MySQL', 'PostgreSQL', 'MongoDB', 'SQLite'],
when: function(answers) {
return answers.needsDatabase;
}
},
{
type: 'input',
name: 'databaseUrl',
message: 'Database connection URL:',
when: function(answers) {
return answers.needsDatabase;
},
validate: function(input) {
if (!input.trim()) {
return 'Database URL is required';
}
return true;
}
}
])
.then(function(answers) {
if (answers.needsDatabase) {
console.log(`Using ${answers.databaseType} at ${answers.databaseUrl}`);
} else {
console.log('No database configured');
}
});const vorpal = require('vorpal')();
// Setup interactive CLI with rich UI
vorpal
.delimiter('myapp$')
.banner('Welcome to My Application v1.0.0')
.command('configure', 'Interactive configuration')
.action(function(args, callback) {
const self = this;
self.log('Starting configuration wizard...');
self.prompt([
{
type: 'input',
name: 'name',
message: 'Project name:',
default: 'my-project'
},
{
type: 'list',
name: 'framework',
message: 'Select framework:',
choices: [
{ name: 'Express.js', value: 'express' },
{ name: 'Koa.js', value: 'koa' },
{ name: 'Fastify', value: 'fastify' }
]
},
{
type: 'checkbox',
name: 'features',
message: 'Select features:',
choices: [
'Authentication',
'Database',
'Caching',
'Logging',
'Testing'
]
},
{
type: 'confirm',
name: 'proceed',
message: 'Proceed with configuration?',
default: true
}
], function(result) {
if (result.proceed) {
self.log('Configuration saved:');
self.log('- Name:', result.name);
self.log('- Framework:', result.framework);
self.log('- Features:', result.features.join(', '));
} else {
self.log('Configuration cancelled');
}
callback();
});
});
// Show the interface
vorpal.show();Controls prompt state for complex user interactions.
/**
* Pauses active prompt, returning the value of what had been typed so far
* @returns Current prompt input string or false if no active prompt
*/
function pause(): string | false;
/**
* Resumes active prompt with optional text to fill prompt with
* @param val - Optional text to fill prompt with on resume
* @returns UI instance for chaining
*/
function resume(val?: string): UI;Usage Example:
const vorpal = require('vorpal')();
vorpal
.command('interactive', 'Interactive command with pause/resume')
.action(function(args, callback) {
const self = this;
// Start a prompt
self.prompt({
type: 'input',
name: 'data',
message: 'Enter some data (will be paused):'
}, function(result) {
self.log('Final result:', result.data);
callback();
});
// Pause the prompt after 2 seconds
setTimeout(() => {
const currentInput = vorpal.ui.pause();
self.log('Prompt paused. Current input:', currentInput);
// Do some processing...
setTimeout(() => {
self.log('Resuming prompt...');
vorpal.ui.resume(currentInput + ' [processed]');
}, 1000);
}, 2000);
});Cancels the currently active prompt.
/**
* Cancels the active prompt
* @returns UI instance for chaining
*/
function cancel(): UI;Usage Example:
const vorpal = require('vorpal')();
vorpal
.command('cancelable', 'A command with cancelable prompt')
.action(function(args, callback) {
const self = this;
// Start a prompt
self.prompt({
type: 'input',
name: 'data',
message: 'Enter data (will auto-cancel in 5s):'
})
.then(result => {
self.log('Data entered:', result.data);
})
.catch(err => {
self.log('Prompt was cancelled');
})
.finally(() => {
callback();
});
// Auto-cancel after 5 seconds
setTimeout(() => {
self.log('Auto-cancelling prompt...');
vorpal.ui.cancel();
}, 5000);
});Advanced terminal output control for dynamic content updates.
/**
* Writes over existing logging, useful for progress indicators
* @param str - Content to write over existing output
* @returns UI instance for chaining
*/
function redraw(str: string): UI;
/**
* Clears all redraw content permanently
* @returns UI instance for chaining
*/
function redraw.clear(): UI;
/**
* Makes current redraw content permanent
* @returns UI instance for chaining
*/
function redraw.done(): UI;Usage Examples:
const vorpal = require('vorpal')();
vorpal
.command('progress', 'Shows a progress indicator')
.action(function(args, callback) {
const self = this;
let progress = 0;
const total = 100;
const interval = setInterval(() => {
progress += 10;
const percentage = Math.round((progress / total) * 100);
const bar = '█'.repeat(Math.floor(percentage / 5)) +
'░'.repeat(20 - Math.floor(percentage / 5));
// Update the same line with progress
vorpal.ui.redraw(`Progress: [${bar}] ${percentage}%`);
if (progress >= total) {
clearInterval(interval);
// Make the final progress permanent
vorpal.ui.redraw.done();
self.log('Process completed!');
callback();
}
}, 200);
});
vorpal
.command('loading', 'Shows a loading spinner')
.action(function(args, callback) {
const self = this;
const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
let i = 0;
const interval = setInterval(() => {
vorpal.ui.redraw(`Loading ${spinner[i % spinner.length]} Please wait...`);
i++;
}, 100);
// Simulate work
setTimeout(() => {
clearInterval(interval);
// Clear the loading message
vorpal.ui.redraw.clear();
self.log('Loading completed!');
callback();
}, 3000);
});
vorpal
.command('live-data', 'Shows live updating data')
.action(function(args, callback) {
const self = this;
let counter = 0;
self.log('Starting live data feed (Ctrl+C to stop):');
const interval = setInterval(() => {
const timestamp = new Date().toLocaleTimeString();
const data = {
counter: ++counter,
timestamp: timestamp,
random: Math.floor(Math.random() * 1000)
};
// Update the display with current data
vorpal.ui.redraw(JSON.stringify(data, null, 2));
}, 1000);
// Handle cancellation
const originalCancel = self.cancel;
self.cancel = function() {
clearInterval(interval);
vorpal.ui.redraw.clear();
self.log('Live data feed stopped');
if (originalCancel) originalCancel.call(self);
callback();
};
// Auto-stop after 10 seconds for demo
setTimeout(() => {
clearInterval(interval);
vorpal.ui.redraw.done(); // Keep the last data visible
self.log('Live data feed ended');
callback();
}, 10000);
});Advanced example combining multiple UI methods:
const vorpal = require('vorpal')();
vorpal
.command('system-monitor', 'Shows real-time system information')
.action(function(args, callback) {
const self = this;
const os = require('os');
self.log('System Monitor Started (press any key to stop)');
let monitoring = true;
const interval = setInterval(() => {
if (!monitoring) return;
const cpuUsage = process.cpuUsage();
const memUsage = process.memoryUsage();
const uptime = process.uptime();
const display = [
'=== System Monitor ===',
`Uptime: ${Math.floor(uptime)}s`,
`CPU User: ${(cpuUsage.user / 1000000).toFixed(2)}ms`,
`CPU System: ${(cpuUsage.system / 1000000).toFixed(2)}ms`,
`Memory RSS: ${(memUsage.rss / 1024 / 1024).toFixed(2)}MB`,
`Memory Heap: ${(memUsage.heapUsed / 1024 / 1024).toFixed(2)}MB`,
`Memory External: ${(memUsage.external / 1024 / 1024).toFixed(2)}MB`,
'=====================',
'Press any key to stop monitoring...'
].join('\n');
vorpal.ui.redraw(display);
}, 1000);
// Wait for any key press
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.once('data', () => {
monitoring = false;
clearInterval(interval);
process.stdin.setRawMode(false);
process.stdin.pause();
vorpal.ui.redraw.clear();
self.log('System monitoring stopped');
callback();
});
});Handle different terminal sizes and capabilities:
vorpal
.command('responsive-ui', 'Shows responsive UI elements')
.action(function(args, callback) {
const self = this;
const terminalWidth = process.stdout.columns || 80;
const narrow = terminalWidth < 60;
if (narrow) {
// Simplified UI for narrow terminals
self.prompt([
{
type: 'input',
name: 'name',
message: 'Name:'
},
{
type: 'confirm',
name: 'proceed',
message: 'OK?'
}
], function(result) {
self.log('Done:', result.name);
callback();
});
} else {
// Full UI for wider terminals
self.prompt([
{
type: 'input',
name: 'fullName',
message: 'Please enter your full name:'
},
{
type: 'list',
name: 'role',
message: 'Select your role:',
choices: ['Administrator', 'Developer', 'User', 'Guest']
},
{
type: 'confirm',
name: 'proceed',
message: 'Proceed with these settings?'
}
], function(result) {
self.log('Configuration complete:');
self.log('Name:', result.fullName);
self.log('Role:', result.role);
callback();
});
}
});Handle UI errors gracefully:
vorpal
.command('robust-ui', 'UI with error handling')
.action(function(args, callback) {
const self = this;
function safePrompt(options, retryCount = 0) {
const maxRetries = 3;
self.prompt(options)
.then(result => {
self.log('Success:', result);
callback();
})
.catch(err => {
if (retryCount < maxRetries) {
self.log(`Error occurred, retrying... (${retryCount + 1}/${maxRetries})`);
setTimeout(() => {
safePrompt(options, retryCount + 1);
}, 1000);
} else {
self.log('Max retries exceeded. Operation failed.');
callback(err);
}
});
}
safePrompt({
type: 'input',
name: 'data',
message: 'Enter data:'
});
});Install with Tessl CLI
npx tessl i tessl/npm-vorpal