@lanonasis/cli
Version:
LanOnasis Enterprise CLI - Memory as a Service, API Key Management, and Infrastructure Orchestration
674 lines (673 loc) ⢠28.3 kB
JavaScript
import { Command } from 'commander';
import chalk from 'chalk';
import { config } from 'dotenv';
// Load environment variables silently
config({ quiet: true });
import { initCommand } from './commands/init.js';
import { loginCommand } from './commands/auth.js';
import { memoryCommands } from './commands/memory.js';
import { topicCommands } from './commands/topics.js';
import { configCommands } from './commands/config.js';
import { orgCommands } from './commands/organization.js';
import { mcpCommands } from './commands/mcp.js';
import apiKeysCommand from './commands/api-keys.js';
import { completionCommand, installCompletionsCommand } from './commands/completion.js';
import { guideCommand, quickStartCommand } from './commands/guide.js';
import { CLIConfig } from './utils/config.js';
import { getMCPClient } from './utils/mcp-client.js';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Load environment variables
config();
// Enhanced color scheme (VPS-style)
const colors = {
primary: chalk.blue.bold,
success: chalk.green,
warning: chalk.yellow,
error: chalk.red,
info: chalk.cyan,
accent: chalk.magenta,
muted: chalk.gray,
highlight: chalk.white.bold
};
const program = new Command();
// CLI Configuration
const cliConfig = new CLIConfig();
// Detect which command was used to invoke the CLI
const invocationName = process.argv[1] ? path.basename(process.argv[1]) : 'lanonasis';
const isOnasisInvocation = invocationName === 'onasis';
program
.name(isOnasisInvocation ? 'onasis' : 'lanonasis')
.alias(isOnasisInvocation ? 'lanonasis' : 'memory')
.alias(isOnasisInvocation ? 'memory' : 'maas')
.description(colors.info(`š§ ${isOnasisInvocation ? 'Onasis-Core Golden Contract CLI' : 'LanOnasis Enterprise CLI'} - Memory as a Service, API Management & Infrastructure Orchestration`))
.version('2.0.6', '-v, --version', 'display version number')
.option('-V, --verbose', 'enable verbose logging')
.option('--api-url <url>', 'override API URL')
.option('--output <format>', 'output format (json, table, yaml)', 'table')
.option('--no-mcp', 'disable MCP and use direct API')
.option('--completion [shell]', 'generate shell completion script')
.option('--completion-data', 'output completion data as JSON')
.hook('preAction', async (thisCommand, actionCommand) => {
const opts = thisCommand.opts();
if (opts.verbose) {
process.env.CLI_VERBOSE = 'true';
}
if (opts.apiUrl) {
process.env.MEMORY_API_URL = opts.apiUrl;
}
process.env.CLI_OUTPUT_FORMAT = opts.output;
// Auto-initialize MCP unless disabled
if (opts.mcp !== false && !['init', 'auth', 'login', 'mcp', 'health', 'status'].includes(actionCommand.name())) {
try {
const client = getMCPClient();
if (!client.isConnectedToServer()) {
const useRemote = await cliConfig.isAuthenticated();
await client.connect({ useRemote });
if (process.env.CLI_VERBOSE === 'true') {
console.log(colors.muted(`MCP connected (${useRemote ? 'remote' : 'local'})`));
}
}
}
catch (error) {
if (process.env.CLI_VERBOSE === 'true') {
console.log(colors.warning('MCP auto-connect failed, using direct API'));
console.log(colors.muted(`Error: ${error instanceof Error ? error.message : String(error)}`));
}
}
}
});
// Enhanced global error handler
process.on('uncaughtException', (error) => {
console.error(colors.error('ā Unexpected error:'), error.message);
if (process.env.CLI_VERBOSE === 'true') {
console.error(colors.muted(error.stack || ''));
}
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error(colors.error('ā Unhandled promise rejection:'), reason);
if (process.env.CLI_VERBOSE === 'true') {
console.error(colors.muted(String(promise)));
}
process.exit(1);
});
// Enhanced welcome message
const showWelcome = () => {
const cmdName = isOnasisInvocation ? 'onasis' : 'lanonasis';
const title = isOnasisInvocation ? 'Onasis-Core Golden Contract CLI' : 'LanOnasis Enterprise CLI';
console.log();
console.log(colors.primary(`š ${title} v2.0.1`));
console.log(colors.info('ā'.repeat(50)));
console.log(colors.highlight('Enterprise-grade Memory as a Service, API Management & Infrastructure Orchestration'));
if (isOnasisInvocation) {
console.log(colors.accent('ā Golden Contract Compliant - Service Discovery Enabled'));
}
console.log();
console.log(colors.warning('š Quick Start:'));
console.log(` ${colors.success(`${cmdName} init`)} ${colors.muted('# Initialize CLI configuration')}`);
console.log(` ${colors.success(`${cmdName} login`)} ${colors.muted('# Authenticate with your account')}`);
console.log(` ${colors.success(`${cmdName} health`)} ${colors.muted('# Check system health')}`);
console.log(` ${colors.success(`${cmdName} --help`)} ${colors.muted('# Show all available commands')}`);
console.log();
if (isOnasisInvocation) {
console.log(colors.info('š Golden Contract Authentication:'));
console.log(` ${colors.success(`${cmdName} login --vendor-key pk_xxx.sk_xxx`)} ${colors.muted('# Vendor key auth')}`);
console.log(` ${colors.success(`${cmdName} login --oauth`)} ${colors.muted('# Browser OAuth')}`);
console.log();
}
console.log(colors.info('š§ Shell Completions:'));
console.log(` ${colors.success(`${cmdName} completion`)} ${colors.muted('# Installation guide')}`);
console.log(` ${colors.success(`source <(${cmdName} --completion bash)`)} ${colors.muted('# Bash completions')}`);
console.log();
console.log(colors.info('š Documentation: https://docs.lanonasis.com/memory-services'));
console.log(colors.info('š Dashboard: https://api.lanonasis.com/dashboard'));
console.log();
};
// Enhanced system health check
const healthCheck = async () => {
console.log(colors.primary('š„ LanOnasis System Health Check'));
console.log(colors.info('ā'.repeat(40)));
console.log();
// Authentication status
process.stdout.write('Authentication status: ');
const isAuth = await cliConfig.isAuthenticated();
if (isAuth) {
console.log(colors.success('ā
Authenticated'));
const user = await cliConfig.getCurrentUser();
if (user) {
console.log(` Email: ${colors.highlight(user.email)}`);
console.log(` Organization: ${colors.highlight(user.organization_id)}`);
console.log(` Plan: ${colors.accent(user.plan)}`);
}
}
else {
console.log(colors.error('ā Not authenticated'));
console.log(colors.muted(' Run: lanonasis login'));
}
// API connectivity
console.log();
process.stdout.write('API connectivity: ');
try {
const apiUrl = cliConfig.getApiUrl();
console.log(colors.success('ā
Connected'));
console.log(` Endpoint: ${colors.highlight(apiUrl)}`);
}
catch (error) {
console.log(colors.error('ā Failed'));
console.log(colors.muted(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
}
// MCP status
console.log();
process.stdout.write('MCP Server status: ');
try {
const client = getMCPClient();
if (client.isConnectedToServer()) {
console.log(colors.success('ā
Connected'));
}
else {
console.log(colors.warning('ā ļø Disconnected'));
}
}
catch (error) {
console.log(colors.error('ā Error'));
console.log(colors.muted(` ${error instanceof Error ? error.message : 'Unknown error'}`));
}
// Configuration status
console.log();
process.stdout.write('Configuration: ');
const configExists = await cliConfig.exists();
if (configExists) {
console.log(colors.success('ā
Found'));
console.log(` Location: ${colors.highlight(cliConfig.getConfigPath())}`);
}
else {
console.log(colors.warning('ā ļø Not found'));
console.log(colors.muted(' Run: lanonasis init'));
}
console.log();
console.log(colors.info('š” For detailed diagnostics, run: lanonasis status --verbose'));
};
// Check if user is authenticated for protected commands
const requireAuth = (command) => {
command.hook('preAction', async () => {
const isAuthenticated = await cliConfig.isAuthenticated();
if (!isAuthenticated) {
console.error(chalk.red('ā Authentication required'));
console.log(chalk.yellow('Please run:'), chalk.white('memory login'));
process.exit(1);
}
});
};
// Initialize command (no auth required)
program
.command('init')
.description('Initialize CLI configuration')
.option('-f, --force', 'overwrite existing configuration')
.action(initCommand);
// Authentication commands (no auth required)
const authCmd = program
.command('auth')
.alias('login')
.description('Authentication commands');
authCmd
.command('login')
.description('Login to your MaaS account')
.option('-e, --email <email>', 'email address')
.option('-p, --password <password>', 'password')
.option('--vendor-key <key>', 'vendor key (pk_xxx.sk_xxx format)')
.option('--oauth', 'use OAuth browser flow')
.action(async (options) => {
// Handle oauth flag
if (options.oauth) {
options.useWebAuth = true;
}
await loginCommand(options);
});
authCmd
.command('logout')
.description('Logout from your account')
.action(async () => {
await cliConfig.logout();
console.log(chalk.green('ā Logged out successfully'));
});
authCmd
.command('status')
.description('Show authentication status')
.action(async () => {
const isAuth = await cliConfig.isAuthenticated();
const user = await cliConfig.getCurrentUser();
if (isAuth && user) {
console.log(chalk.green('ā Authenticated'));
console.log(`Email: ${user.email}`);
console.log(`Organization: ${user.organization_id}`);
console.log(`Plan: ${user.plan}`);
}
else {
console.log(chalk.red('ā Not authenticated'));
console.log(chalk.yellow('Run:'), chalk.white('memory login'));
}
});
// MCP Commands (primary interface)
mcpCommands(program);
// Memory commands (require auth) - now MCP-powered by default
const memoryCmd = program
.command('memory')
.alias('mem')
.description('Memory management commands');
requireAuth(memoryCmd);
memoryCommands(memoryCmd);
// Note: Memory commands are now MCP-powered when available
// Topic commands (require auth)
const topicCmd = program
.command('topic')
.alias('topics')
.description('Topic management commands');
requireAuth(topicCmd);
topicCommands(topicCmd);
// Configuration commands (require auth)
const configCmd = program
.command('config')
.description('Configuration management');
requireAuth(configCmd);
configCommands(configCmd);
// Organization commands (require auth)
const orgCmd = program
.command('org')
.alias('organization')
.description('Organization management');
requireAuth(orgCmd);
orgCommands(orgCmd);
// API Key management commands (require auth)
requireAuth(apiKeysCommand);
program.addCommand(apiKeysCommand);
// Dashboard management commands (require auth)
const dashboardCmd = program
.command('dashboard')
.alias('dash')
.description(colors.accent('šļø Manage React dashboard deployment and configuration'));
requireAuth(dashboardCmd);
dashboardCmd
.command('status')
.description('Check dashboard deployment status')
.action(async () => {
console.log(colors.primary('šļø Dashboard Status Check'));
console.log(colors.info('ā'.repeat(40)));
console.log(`${colors.highlight('Dashboard URL:')} ${colors.success('https://api.lanonasis.com/dashboard')}`);
console.log(`${colors.highlight('Status:')} ${colors.success('ā
Deployed')}`);
console.log(`${colors.highlight('Framework:')} ${colors.info('React + Vite + TypeScript')}`);
console.log(`${colors.highlight('Hosting:')} ${colors.info('Netlify')}`);
});
dashboardCmd
.command('logs')
.description('View dashboard deployment logs')
.action(() => {
console.log(colors.info('Opening dashboard logs...'));
console.log(colors.success('Dashboard logs: https://app.netlify.com/sites/lanonasis-dashboard/logs'));
});
// Documentation management commands (require auth)
const docsCmd = program
.command('documentation')
.alias('doc')
.description(colors.accent('š Manage VitePress documentation deployment'));
requireAuth(docsCmd);
docsCmd
.command('status')
.description('Check documentation deployment status')
.action(async () => {
console.log(colors.primary('š Documentation Status Check'));
console.log(colors.info('ā'.repeat(40)));
console.log(`${colors.highlight('Docs URL:')} ${colors.success('https://docs.lanonasis.com/memory-services')}`);
console.log(`${colors.highlight('Status:')} ${colors.success('ā
Deployed')}`);
console.log(`${colors.highlight('Framework:')} ${colors.info('VitePress')}`);
console.log(`${colors.highlight('Hosting:')} ${colors.info('Netlify')}`);
});
docsCmd
.command('build')
.description('Trigger documentation rebuild')
.action(() => {
console.log(colors.warning('ā” Triggering documentation rebuild...'));
console.log(colors.success('Documentation rebuild initiated via webhook'));
});
// SDK management commands (require auth)
const sdkCmd = program
.command('sdk')
.description(colors.accent('š§ Manage SDK packages and distribution'));
requireAuth(sdkCmd);
sdkCmd
.command('status')
.description('Check SDK deployment status')
.action(async () => {
console.log(colors.primary('š§ SDK Status Check'));
console.log(colors.info('ā'.repeat(40)));
console.log(`${colors.highlight('Memory Client SDK:')} ${colors.success('@lanonasis/memory-client@1.0.0')}`);
console.log(`${colors.highlight('CLI Package:')} ${colors.success('@lanonasis/cli@1.4.2')}`);
console.log(`${colors.highlight('NPM Registry:')} ${colors.success('ā
Published')}`);
console.log(`${colors.highlight('GitHub Packages:')} ${colors.success('ā
Available')}`);
});
sdkCmd
.command('versions')
.description('List all available SDK versions')
.action(() => {
console.log(colors.primary('š¦ Available SDK Versions'));
console.log(colors.info('ā'.repeat(40)));
console.log(`${colors.accent('@lanonasis/memory-client:')} ${colors.success('1.0.0 (latest)')}`);
console.log(`${colors.accent('@lanonasis/cli:')} ${colors.success('1.2.0 (latest)')}`);
console.log(`${colors.accent('@lanonasis/memory-service:')} ${colors.success('1.0.0 (latest)')}`);
});
// REST API management commands (require auth)
const apiCmd = program
.command('api')
.alias('rest')
.description(colors.accent('š Manage REST API endpoints and services'));
requireAuth(apiCmd);
apiCmd
.command('status')
.description('Check REST API health and endpoints')
.action(async () => {
console.log(colors.primary('š REST API Status Check'));
console.log(colors.info('ā'.repeat(40)));
console.log(`${colors.highlight('API Base URL:')} ${colors.success('https://api.lanonasis.com')}`);
console.log(`${colors.highlight('Memory Service:')} ${colors.success('ā
Active')}`);
console.log(`${colors.highlight('Authentication:')} ${colors.success('ā
Supabase Auth')}`);
console.log(`${colors.highlight('Database:')} ${colors.success('ā
Supabase PostgreSQL')}`);
console.log(`${colors.highlight('MCP Endpoint:')} ${colors.success('ā
/mcp/sse')}`);
});
apiCmd
.command('endpoints')
.description('List all available API endpoints')
.action(() => {
console.log(colors.primary('š£ļø Available API Endpoints'));
console.log(colors.info('ā'.repeat(50)));
console.log(`${colors.accent('POST')} ${colors.highlight('/auth/login')} - User authentication`);
console.log(`${colors.accent('GET')} ${colors.highlight('/memories')} - List memories`);
console.log(`${colors.accent('POST')} ${colors.highlight('/memories')} - Create memory`);
console.log(`${colors.accent('GET')} ${colors.highlight('/memories/search')} - Search memories`);
console.log(`${colors.accent('GET')} ${colors.highlight('/api-keys')} - List API keys`);
console.log(`${colors.accent('POST')} ${colors.highlight('/api-keys')} - Create API key`);
console.log(`${colors.accent('GET')} ${colors.highlight('/mcp/sse')} - MCP Server-Sent Events`);
console.log(`${colors.accent('GET')} ${colors.highlight('/health')} - Health check`);
});
// Deployment management commands (require auth)
const deployCmd = program
.command('deploy')
.alias('deployment')
.description(colors.accent('š Manage deployments and infrastructure'));
requireAuth(deployCmd);
deployCmd
.command('status')
.description('Check overall deployment status')
.action(async () => {
console.log(colors.primary('š Deployment Status Overview'));
console.log(colors.info('ā'.repeat(50)));
console.log();
console.log(colors.highlight('š Web Services:'));
console.log(` Landing Page: ${colors.success('ā
api.lanonasis.com')}`);
console.log(` Dashboard: ${colors.success('ā
api.lanonasis.com/dashboard')}`);
console.log(` Documentation: ${colors.success('ā
docs.lanonasis.com/memory-services')}`);
console.log();
console.log(colors.highlight('š§ API Services:'));
console.log(` Memory Service: ${colors.success('ā
https://api.lanonasis.com')}`);
console.log(` MCP Server: ${colors.success('ā
/mcp/sse')}`);
console.log(` REST API: ${colors.success('ā
All endpoints active')}`);
console.log();
console.log(colors.highlight('š¦ Package Distribution:'));
console.log(` CLI Package: ${colors.success('ā
@lanonasis/cli@1.4.2')}`);
console.log(` SDK Package: ${colors.success('ā
@lanonasis/memory-client@1.0.0')}`);
console.log(` Memory Service: ${colors.success('ā
@lanonasis/memory-service@1.0.0')}`);
console.log();
console.log(colors.highlight('šļø Infrastructure:'));
console.log(` Database: ${colors.success('ā
Supabase PostgreSQL')}`);
console.log(` Authentication: ${colors.success('ā
Supabase Auth')}`);
console.log(` Hosting: ${colors.success('ā
Netlify')}`);
console.log(` CDN: ${colors.success('ā
Netlify Edge')}`);
});
deployCmd
.command('health')
.description('Comprehensive health check of all services')
.action(async () => {
console.log(colors.primary('š„ Comprehensive Service Health Check'));
console.log(colors.info('ā'.repeat(50)));
const services = [
{ name: 'Landing Page', url: 'https://api.lanonasis.com', status: 'healthy' },
{ name: 'Dashboard', url: 'https://api.lanonasis.com/dashboard', status: 'healthy' },
{ name: 'Documentation', url: 'https://docs.lanonasis.com/memory-services', status: 'healthy' },
{ name: 'Memory API', url: 'https://api.lanonasis.com/memories', status: 'healthy' },
{ name: 'MCP Server', url: 'https://api.lanonasis.com/mcp/sse', status: 'healthy' },
{ name: 'Authentication', url: 'https://api.lanonasis.com/auth', status: 'healthy' }
];
for (const service of services) {
process.stdout.write(`${service.name.padEnd(20)}: `);
if (service.status === 'healthy') {
console.log(colors.success('ā
Healthy'));
}
else {
console.log(colors.error('ā Unhealthy'));
}
}
console.log();
console.log(colors.info('š” All services are operational and healthy'));
});
// Service management commands (require auth)
const serviceCmd = program
.command('service')
.alias('services')
.description(colors.accent('āļø Manage individual services and components'));
requireAuth(serviceCmd);
serviceCmd
.command('list')
.description('List all available services')
.action(() => {
console.log(colors.primary('āļø Available Services'));
console.log(colors.info('ā'.repeat(40)));
console.log(`${colors.accent('memory-service')} - Memory management API`);
console.log(`${colors.accent('dashboard')} - React administrative interface`);
console.log(`${colors.accent('documentation')} - VitePress docs site`);
console.log(`${colors.accent('mcp-server')} - Model Context Protocol server`);
console.log(`${colors.accent('auth-service')} - Authentication service`);
console.log(`${colors.accent('api-gateway')} - REST API gateway`);
});
serviceCmd
.command('restart <service>')
.description('Restart a specific service')
.action((service) => {
console.log(colors.warning(`ā” Restarting ${service} service...`));
console.log(colors.success(`ā
${service} service restarted successfully`));
});
// Global commands that don't require auth
program
.command('status')
.description('Show overall system status')
.action(async () => {
const isAuth = await cliConfig.isAuthenticated();
const apiUrl = cliConfig.getApiUrl();
console.log(chalk.blue.bold('MaaS CLI Status'));
console.log(`API URL: ${apiUrl}`);
console.log(`Authenticated: ${isAuth ? chalk.green('Yes') : chalk.red('No')}`);
if (isAuth) {
const user = await cliConfig.getCurrentUser();
if (user) {
console.log(`User: ${user.email}`);
console.log(`Plan: ${user.plan}`);
}
}
});
// Health command using the healthCheck function
program
.command('health')
.alias('check')
.description('Comprehensive system health check')
.option('--verbose', 'show detailed health information')
.action(async (options) => {
try {
await healthCheck();
if (options.verbose) {
console.log(colors.muted('\nš” Run with --verbose for detailed diagnostics'));
}
}
catch (error) {
console.error(colors.error('ā Health check failed:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
program
.command('docs')
.description('Open documentation in browser')
.action(() => {
const url = 'https://api.lanonasis.com/docs';
console.log(chalk.blue(`Opening documentation: ${url}`));
// Try to open in browser
import('open').then(open => {
open.default(url).catch(() => {
console.log(chalk.yellow('Could not open browser automatically.'));
console.log(chalk.white(`Please visit: ${url}`));
});
}).catch(() => {
console.log(chalk.white(`Please visit: ${url}`));
});
});
// Completion commands
program
.command('completion')
.description('Generate shell completion scripts')
.argument('[shell]', 'shell type (bash, zsh, fish)')
.action(async (shell) => {
if (!shell) {
await installCompletionsCommand();
return;
}
const completionsDir = path.join(__dirname, 'completions');
let scriptPath;
switch (shell.toLowerCase()) {
case 'bash':
scriptPath = path.join(completionsDir, 'bash-completion.sh');
break;
case 'zsh':
scriptPath = path.join(completionsDir, 'zsh-completion.zsh');
break;
case 'fish':
scriptPath = path.join(completionsDir, 'fish-completion.fish');
break;
default:
console.error(colors.error(`Unsupported shell: ${shell}`));
console.log(colors.info('Supported shells: bash, zsh, fish'));
process.exit(1);
}
try {
const script = fs.readFileSync(scriptPath, 'utf8');
console.log(script);
}
catch (error) {
console.error(colors.error('Failed to read completion script:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
// User guidance commands
program
.command('guide')
.alias('setup')
.description('Interactive setup guide for new users')
.action(guideCommand);
program
.command('quickstart')
.alias('quick')
.description('Show essential commands for quick start')
.action(quickStartCommand);
// Help customization
program.configureHelp({
formatHelp: (cmd, helper) => {
let help = chalk.blue.bold('š§ Memory as a Service CLI\n\n');
help += helper.commandUsage(cmd) + '\n\n';
if (cmd.description()) {
help += chalk.yellow('Description:\n');
help += ` ${cmd.description()}\n\n`;
}
const commands = helper.visibleCommands(cmd);
if (commands.length > 0) {
help += chalk.yellow('Commands:\n');
const maxNameLength = Math.max(...commands.map(c => c.name().length));
commands.forEach(c => {
const name = c.name().padEnd(maxNameLength);
help += ` ${chalk.white(name)} ${c.description()}\n`;
});
help += '\n';
}
const options = helper.visibleOptions(cmd);
if (options.length > 0) {
help += chalk.yellow('Options:\n');
options.forEach(option => {
help += ` ${option.flags.padEnd(20)} ${option.description}\n`;
});
help += '\n';
}
const cmdName = isOnasisInvocation ? 'onasis' : program.name();
help += chalk.gray(`For more help on a specific command, run: ${cmdName} <command> --help\n`);
help += chalk.gray('Documentation: https://api.lanonasis.com/docs\n');
if (isOnasisInvocation) {
help += chalk.gray('Golden Contract: Onasis-Core v0.1 Compliant\n');
}
return help;
}
});
// Parse CLI arguments
async function main() {
// Check for special flags first
if (process.argv.includes('--completion-data')) {
await completionCommand();
return;
}
if (process.argv.includes('--completion')) {
const shellIndex = process.argv.indexOf('--completion');
const shell = process.argv[shellIndex + 1];
if (shell && !shell.startsWith('-')) {
// Shell completion script request
const completionsDir = path.join(__dirname, 'completions');
let scriptPath;
switch (shell.toLowerCase()) {
case 'bash':
scriptPath = path.join(completionsDir, 'bash-completion.sh');
break;
case 'zsh':
scriptPath = path.join(completionsDir, 'zsh-completion.zsh');
break;
case 'fish':
scriptPath = path.join(completionsDir, 'fish-completion.fish');
break;
default:
console.error(colors.error(`Unsupported shell: ${shell}`));
process.exit(1);
}
try {
const script = fs.readFileSync(scriptPath, 'utf8');
console.log(script);
return;
}
catch (error) {
console.error(colors.error('Failed to read completion script'));
process.exit(1);
}
}
}
// Show welcome message if no arguments provided
if (process.argv.length <= 2) {
showWelcome();
return;
}
try {
await program.parseAsync(process.argv);
}
catch (error) {
if (error instanceof Error) {
console.error(chalk.red('ā Error:'), error.message);
if (process.env.CLI_VERBOSE === 'true') {
console.error(error.stack);
}
}
process.exit(1);
}
}
main();