Add NPM distribution support with hybrid installation approach
Major changes: - Add package.json with NPM packaging configuration - Create Node.js CLI interface (bin/claude-hooks.js) with full command set - Convert bash scripts to Python for better npm integration - Add npm postinstall/preuninstall hooks for automatic setup - Update bootstrap prompt to recommend NPM method with git fallback - Enhance README with NPM-first documentation - Maintain backward compatibility with existing git installation Features: - npm install -g claude-hooks for easy distribution - claude-hooks init/status/test/backup/uninstall commands - Automatic Python dependency installation - Conflict detection and prevention - Hybrid approach supporting both npm and git workflows This resolves installation complexity while maintaining developer flexibility. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1e169a5d45
commit
9445e09c48
13 changed files with 1055 additions and 107 deletions
127
bin/claude-hooks.js
Normal file
127
bin/claude-hooks.js
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const { Command } = require('commander');
|
||||
const chalk = require('chalk');
|
||||
const { execSync, spawn } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
|
||||
const program = new Command();
|
||||
const packageRoot = path.dirname(__dirname);
|
||||
|
||||
// Helper to run Python scripts
|
||||
function runPythonScript(scriptName, args = []) {
|
||||
const scriptPath = path.join(packageRoot, 'scripts', scriptName);
|
||||
return spawn('python3', [scriptPath, ...args], {
|
||||
stdio: 'inherit',
|
||||
cwd: packageRoot
|
||||
});
|
||||
}
|
||||
|
||||
// Helper to check installation status
|
||||
function checkStatus() {
|
||||
const hooksConfig = path.join(os.homedir(), '.config', 'claude', 'hooks.json');
|
||||
const hasHooks = fs.existsSync(hooksConfig);
|
||||
|
||||
console.log(chalk.blue('Claude Hooks Status:'));
|
||||
console.log(hasHooks ? chalk.green('✓ Hooks configuration installed') : chalk.red('✗ No hooks configuration found'));
|
||||
|
||||
try {
|
||||
execSync('python3 --version', { stdio: 'pipe' });
|
||||
console.log(chalk.green('✓ Python 3 available'));
|
||||
} catch {
|
||||
console.log(chalk.red('✗ Python 3 not found'));
|
||||
}
|
||||
|
||||
return hasHooks;
|
||||
}
|
||||
|
||||
program
|
||||
.name('claude-hooks')
|
||||
.description('Intelligent hooks system for Claude Code')
|
||||
.version(require('../package.json').version);
|
||||
|
||||
program
|
||||
.command('init')
|
||||
.description('Initialize Claude Hooks (run after npm install)')
|
||||
.option('--force', 'Force reinstallation even if already configured')
|
||||
.action((options) => {
|
||||
console.log(chalk.blue('Initializing Claude Hooks...'));
|
||||
|
||||
if (!options.force && checkStatus()) {
|
||||
console.log(chalk.yellow('⚠️ Claude Hooks already configured. Use --force to reinstall.'));
|
||||
return;
|
||||
}
|
||||
|
||||
const initScript = runPythonScript('install.py');
|
||||
initScript.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
console.log(chalk.green('\n🎉 Claude Hooks initialized successfully!'));
|
||||
console.log(chalk.blue('Next steps:'));
|
||||
console.log('1. Restart Claude Code to activate hooks');
|
||||
console.log('2. Try: claude-hooks test');
|
||||
} else {
|
||||
console.log(chalk.red('❌ Initialization failed'));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
program
|
||||
.command('status')
|
||||
.description('Show Claude Hooks installation status')
|
||||
.action(() => {
|
||||
checkStatus();
|
||||
});
|
||||
|
||||
program
|
||||
.command('test')
|
||||
.description('Run Claude Hooks tests')
|
||||
.action(() => {
|
||||
console.log(chalk.blue('Running Claude Hooks tests...'));
|
||||
const testScript = runPythonScript('test.py');
|
||||
testScript.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
console.log(chalk.green('✅ All tests passed!'));
|
||||
} else {
|
||||
console.log(chalk.red('❌ Some tests failed'));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
program
|
||||
.command('uninstall')
|
||||
.description('Remove Claude Hooks configuration')
|
||||
.action(() => {
|
||||
console.log(chalk.blue('Uninstalling Claude Hooks...'));
|
||||
const uninstallScript = runPythonScript('uninstall.py');
|
||||
uninstallScript.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
console.log(chalk.green('✅ Claude Hooks uninstalled successfully'));
|
||||
console.log(chalk.yellow('Note: To completely remove, run: npm uninstall -g claude-hooks'));
|
||||
} else {
|
||||
console.log(chalk.red('❌ Uninstall failed'));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
program
|
||||
.command('backup')
|
||||
.description('Manually trigger a backup')
|
||||
.action(() => {
|
||||
console.log(chalk.blue('Creating manual backup...'));
|
||||
const backupScript = runPythonScript('manual-backup.py');
|
||||
backupScript.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
console.log(chalk.green('✅ Backup created successfully'));
|
||||
} else {
|
||||
console.log(chalk.red('❌ Backup failed'));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
program.parse();
|
||||
Loading…
Add table
Add a link
Reference in a new issue