Launch your command line tool with ease by handling configuration discovery, local module resolution, and process management.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core lifecycle management for CLI tool execution, handling the complete flow from initialization through environment preparation to final execution with automatic configuration discovery and process management.
Creates a new Liftoff instance configured for launching CLI applications with specified options for configuration discovery, module resolution, and process management.
/**
* Creates a new Liftoff instance for launching CLI applications
* @param opts - Configuration options for the CLI launcher
*/
function Liftoff(opts: LiftoffOptions): Liftoff;
interface LiftoffOptions {
/** Name of the CLI tool (automatically sets processTitle, moduleName, configName if not specified) */
name?: string;
/** Title to set for the process (required if name not provided) */
processTitle?: string;
/** Name of the local module to find and require (required if name not provided) */
moduleName?: string;
/** Base name of configuration files to search for (required if name not provided) */
configName?: string;
/** File extensions and their corresponding loader modules */
extensions?: { [ext: string]: string | null };
/** V8 flags to apply during process respawn */
v8flags?: string[] | ((callback: (err: Error | null, flags?: string[]) => void) => void);
/** Function to handle shell completions */
completions?: (type: string) => void;
/** Array of configuration file search specifications */
configFiles?: ConfigFileSpec[];
/** Additional search paths for configuration discovery */
searchPaths?: string[];
}
interface ConfigFileSpec {
/** Base name of the config file to search for */
name?: string;
/** Path to search in (required) */
path: string;
/** File extensions to try when searching */
extensions?: string[] | { [ext: string]: string | null };
/** Base directory for resolving relative paths */
cwd?: string;
/** Whether to search up the directory tree */
findUp?: boolean;
}Usage Examples:
const Liftoff = require('liftoff');
// Simple configuration using name sugar
const MyApp = new Liftoff({
name: 'myapp' // Sets processTitle, moduleName, and configName automatically
});
// Advanced configuration with custom options
const AdvancedApp = new Liftoff({
processTitle: 'my-advanced-cli',
moduleName: 'my-advanced-cli',
configName: 'advancedfile',
extensions: {
'.js': null,
'.json': null,
'.coffee': 'coffee-script/register',
'.ts': 'ts-node/register'
},
v8flags: ['--harmony', '--experimental-modules'],
configFiles: [
{ name: '.myapprc', path: '~' },
{ name: 'myappfile', path: '.', findUp: true }
]
});Prepares the execution environment by building the environment object and invoking the callback with the calculated environment, setting the process title and context.
/**
* Prepares the execution environment and invokes callback
* @param opts - Options for environment building
* @param callback - Function called with prepared environment
*/
prepare(opts: EnvironmentOptions, callback: (env: Environment) => void): void;
interface EnvironmentOptions {
/** Override current working directory */
cwd?: string;
/** Explicit path to configuration file (skip discovery) */
configPath?: string;
/** Modules to preload before execution */
preload?: string | string[];
/** Completion data for shell completions */
completion?: any;
}Usage Examples:
const MyApp = new Liftoff({ name: 'myapp' });
// Basic preparation
MyApp.prepare({}, function(env) {
console.log('Environment prepared:', env);
// env contains cwd, configPath, modulePath, etc.
});
// Preparation with options
MyApp.prepare({
cwd: './my-project',
preload: ['babel-register'],
configPath: './custom-config.js'
}, function(env) {
// Continue with execution
MyApp.execute(env, function(env, argv) {
console.log('Application started');
});
});Starts the application based on the prepared environment, handling v8 flag detection, process respawning if needed, and module preloading before invoking the final callback.
/**
* Execute application with prepared environment
* @param env - Environment object from prepare()
* @param callback - Function called after execution setup (not called if completion mode)
* @note If env.completion is truthy and completions function is defined, executes completion mode instead
*/
execute(env: Environment, callback: (env: Environment, argv: string[]) => void): void;
/**
* Execute application with forced flags
* @param env - Environment object from prepare()
* @param forcedFlags - Additional flags to force process respawn
* @param callback - Function called after execution setup (not called if completion mode)
* @note If env.completion is truthy and completions function is defined, executes completion mode instead
*/
execute(env: Environment, forcedFlags: string[], callback: (env: Environment, argv: string[]) => void): void;Usage Examples:
const MyApp = new Liftoff({ name: 'myapp' });
MyApp.prepare({}, function(env) {
// Basic execution
MyApp.execute(env, function(env, argv) {
console.log('CLI arguments:', argv);
console.log('Config path:', env.configPath);
console.log('Module path:', env.modulePath);
// Your CLI application logic here
if (env.configPath) {
const config = require(env.configPath);
console.log('Loaded config:', config);
}
});
});
// Execution with forced flags
MyApp.prepare({}, function(env) {
MyApp.execute(env, ['--trace-deprecation'], function(env, argv) {
// Application runs with additional --trace-deprecation flag
console.log('Running with forced flags');
});
});const Liftoff = require('liftoff');
const path = require('path');
// Create CLI tool launcher
const MyTool = new Liftoff({
name: 'mytool',
extensions: {
'.js': null,
'.json': null,
'.coffee': 'coffee-script/register'
},
v8flags: ['--harmony']
});
// Set up event listeners for debugging
MyTool.on('preload:before', function(name) {
console.log('Loading module:', name);
});
MyTool.on('preload:success', function(name, module) {
console.log('Successfully loaded:', name);
});
MyTool.on('respawn', function(flags, child) {
console.log('Respawned with flags:', flags);
console.log('Child PID:', child.pid);
});
// Parse command line arguments
const argv = require('minimist')(process.argv.slice(2));
// Complete lifecycle
MyTool.prepare({
cwd: argv.cwd,
configPath: argv.mytoolfile,
preload: argv.preload
}, function(env) {
// Environment is prepared, now execute
MyTool.execute(env, function(env, argv) {
// Main application logic
console.log('MyTool started successfully!');
console.log('Working directory:', env.cwd);
console.log('Config file:', env.configPath || 'none found');
console.log('Local module:', env.modulePath || 'none found');
// Load configuration if available
if (env.configPath) {
try {
const config = require(env.configPath);
console.log('Configuration loaded:', config);
} catch (e) {
console.error('Failed to load config:', e.message);
}
}
// Your CLI tool implementation here
runMyTool(env, argv);
});
});
function runMyTool(env, argv) {
// Implementation of your CLI tool
console.log('Running with arguments:', argv);
}