UNPKG

@pimzino/claude-code-spec-workflow

Version:

Automated workflows for Claude Code. Includes spec-driven development (Requirements → Design → Tasks → Implementation) with intelligent task execution, optional steering documents and streamlined bug fix workflow (Report → Analyze → Fix → Verify). We have

110 lines 5.39 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const multi_server_1 = require("./multi-server"); const tunnel_1 = require("./tunnel"); const program = new commander_1.Command(); program .name('claude-spec-dashboard') .description('Launch a real-time dashboard for Claude Code Spec Workflow') .version('1.3.0'); program .option('-p, --port <port>', 'Port to run the dashboard on', '8247') .option('-o, --open', 'Open dashboard in browser automatically') .option('-t, --tunnel', 'Create a secure tunnel to share the dashboard') .option('--tunnel-password <password>', 'Password-protect the tunnel') .option('--tunnel-provider <provider>', 'Tunnel provider to use (cloudflare, ngrok, auto)', 'ngrok') .option('--ngrok', 'Create a secure tunnel using Ngrok (alias for --tunnel --tunnel-provider ngrok)') .option('--cloudflare', 'Create a secure tunnel using Cloudflare (alias for --tunnel --tunnel-provider cloudflare)') .action(async (options) => { // Handle alias options if (options.ngrok) { options.tunnel = true; options.tunnelProvider = 'ngrok'; } if (options.cloudflare) { options.tunnel = true; options.tunnelProvider = 'cloudflare'; } console.log(chalk_1.default.cyan.bold('🚀 Claude Code Spec Dashboard')); console.log(chalk_1.default.gray('Real-time spec and task monitoring')); console.log(); const spinner = (0, ora_1.default)(options.tunnel ? 'Starting dashboard server and creating tunnel...' : 'Starting dashboard server...').start(); try { const server = new multi_server_1.MultiProjectDashboardServer({ port: parseInt(options.port), autoOpen: options.open, tunnel: options.tunnel, tunnelPassword: options.tunnelPassword, tunnelProvider: options.tunnelProvider, }); await server.start(); // Check if tunnel was created const tunnelStatus = server.getTunnelStatus(); if (tunnelStatus.active && tunnelStatus.info) { spinner.succeed(chalk_1.default.green(`Dashboard running at http://localhost:${options.port}`)); console.log(); console.log(chalk_1.default.cyan.bold('╔════════════════════════════════════════════╗')); console.log(chalk_1.default.cyan.bold('║ 🔗 Tunnel Active ║')); console.log(chalk_1.default.cyan.bold('╚════════════════════════════════════════════╝')); console.log(); console.log(chalk_1.default.white.bold('Share this URL:')); console.log(chalk_1.default.green.bold(tunnelStatus.info.url)); console.log(chalk_1.default.gray('(Copy the URL above to share)')); console.log(); if (tunnelStatus.info.passwordProtected) { console.log(chalk_1.default.yellow('Password: ') + chalk_1.default.yellow.bold(options.tunnelPassword)); console.log(); } console.log(chalk_1.default.gray('Provider: ') + tunnelStatus.info.provider); console.log(chalk_1.default.gray('Local dashboard: ') + `http://localhost:${options.port}`); console.log(); console.log(chalk_1.default.gray('Press Ctrl+C to stop')); console.log(); } else { spinner.succeed(chalk_1.default.green(`Dashboard running at http://localhost:${options.port}`)); console.log(); console.log(chalk_1.default.gray('Press Ctrl+C to stop the server')); console.log(); } // Handle graceful shutdown process.on('SIGINT', async () => { console.log(chalk_1.default.yellow('\n\nShutting down dashboard...')); const forceExitTimeout = setTimeout(() => { console.log(chalk_1.default.red('Force exiting...')); process.exit(1); }, 5000); try { await server.stop(); clearTimeout(forceExitTimeout); process.exit(0); } catch (error) { console.error(chalk_1.default.red('Error during shutdown:'), error); process.exit(1); } }); } catch (error) { spinner.fail('Failed to start dashboard'); // Enhanced error handling for tunnel errors if (error instanceof tunnel_1.TunnelProviderError) { console.log(); console.error(chalk_1.default.red.bold('❌ Tunnel Error')); console.log(chalk_1.default.red(error.getUserFriendlyMessage())); } else { console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : error); } process.exit(1); } }); program.parse(process.argv); //# sourceMappingURL=cli.js.map