UNPKG

claudewatch

Version:

Automated validation and self-healing system for Claude Code projects

179 lines (162 loc) 5.45 kB
#!/usr/bin/env node const { program } = require('commander'); const chalk = require('chalk'); const ora = require('ora'); const prompts = require('prompts'); const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const { initProject, runValidation, runSelfHealing, showStatus, generateReport, cleanup } = require('../lib'); program .name('claudewatch') .description('Automated validation and self-healing for Claude Code projects') .version(require('../package.json').version); program .command('init') .description('Initialize ClaudeWatch in your project') .option('-y, --yes', 'Skip prompts and use defaults') .action(async (options) => { console.log(chalk.blue('\nInitializing ClaudeWatch...\n')); if (!options.yes) { const response = await prompts([ { type: 'text', name: 'baseUrl', message: 'What is your development server URL?', initial: 'http://localhost:3000' }, { type: 'confirm', name: 'selfHealing', message: 'Enable self-healing mode?', initial: true }, { type: 'multiselect', name: 'validationTypes', message: 'Which validation types to enable?', choices: [ { title: 'Visual Elements', value: 'visual', selected: true }, { title: 'Accessibility', value: 'accessibility', selected: true }, { title: 'Performance', value: 'performance', selected: true }, { title: 'Forms', value: 'forms', selected: true }, { title: 'APIs', value: 'api', selected: true }, { title: 'Console Errors', value: 'console', selected: true }, { title: 'Broken Links', value: 'links', selected: true } ] } ]); await initProject(response); } else { await initProject({}); } }); program .command('validate') .alias('test') .description('Run validation tests') .option('-c, --config <path>', 'Path to custom config file') .action(async (options) => { const spinner = ora('Running validation tests...').start(); try { const result = await runValidation(options.config); if (result.success) { spinner.succeed(chalk.green('All validations passed!')); } else { spinner.fail(chalk.red('Validation failed')); process.exit(1); } } catch (error) { spinner.fail(chalk.red(`Error: ${error.message}`)); process.exit(1); } }); program .command('self-heal') .alias('heal') .description('Run self-healing validation (auto-fixes issues)') .option('-m, --max-attempts <number>', 'Maximum healing attempts', '5') .action(async (options) => { console.log(chalk.blue('\nStarting self-healing validation...\n')); try { const result = await runSelfHealing({ maxAttempts: parseInt(options.maxAttempts) }); if (result.success) { console.log(chalk.green('\nAll issues fixed!')); } else { console.log(chalk.yellow('\nSome issues remain')); process.exit(1); } } catch (error) { console.error(chalk.red(`Error: ${error.message}`)); process.exit(1); } }); program .command('status') .description('Show ClaudeWatch status and configuration') .action(async () => { await showStatus(); }); program .command('report') .description('Show validation reports and history') .option('-n, --number <count>', 'Number of recent reports to show', '10') .action(async (options) => { await generateReport(parseInt(options.number)); }); program .command('cleanup') .description('Clean up old validation logs and screenshots') .option('-d, --days <number>', 'Keep files from last N days', '7') .option('--dry-run', 'Show what would be deleted without deleting') .action(async (options) => { await cleanup({ keepDays: parseInt(options.days), dryRun: options.dryRun }); }); program .command('config') .description('Open ClaudeWatch configuration file') .action(() => { const configPath = path.join(process.cwd(), '.claudewatch', 'config.js'); if (fs.existsSync(configPath)) { console.log(chalk.blue(`Opening config at: ${configPath}`)); try { execSync(`${process.env.EDITOR || 'code'} ${configPath}`); } catch (error) { console.log(chalk.yellow('Could not open in editor. Config location:')); console.log(configPath); } } else { console.log(chalk.red('Config file not found. Run `claudewatch init` first.')); } }); program .command('claude-setup') .description('Quick setup optimized for Claude Code') .action(async () => { console.log(chalk.blue('\nSetting up ClaudeWatch for Claude Code...\n')); await initProject({ baseUrl: 'http://localhost:3000', selfHealing: true, validationTypes: ['visual', 'accessibility', 'performance', 'forms', 'api', 'console', 'links'], claudeOptimized: true }); console.log(chalk.green('\nClaudeWatch is ready for Claude Code!')); console.log(chalk.gray('\nClaude will now automatically validate your work.')); console.log(chalk.gray('The self-healing system will fix common issues.\n')); }); program.parse(process.argv); if (!process.argv.slice(2).length) { program.outputHelp(); }