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>
93 lines
2.7 KiB
JavaScript
93 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const { execSync, spawn } = require('child_process');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
|
|
console.log('📦 Claude Hooks post-install setup...');
|
|
|
|
// Check Python availability
|
|
try {
|
|
execSync('python3 --version', { stdio: 'pipe' });
|
|
console.log('✓ Python 3 found');
|
|
} catch {
|
|
console.error('❌ Python 3 is required but not found');
|
|
console.error('Please install Python 3.8+ and try again');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Install Python dependencies
|
|
console.log('📋 Installing Python dependencies...');
|
|
const packageRoot = path.dirname(__dirname);
|
|
const requirementsPath = path.join(packageRoot, 'requirements.txt');
|
|
|
|
if (fs.existsSync(requirementsPath)) {
|
|
try {
|
|
execSync(`python3 -m pip install -r "${requirementsPath}" --user --quiet`, {
|
|
stdio: 'pipe',
|
|
cwd: packageRoot
|
|
});
|
|
console.log('✓ Python dependencies installed');
|
|
} catch (error) {
|
|
console.log('⚠️ Some Python dependencies may not have installed');
|
|
console.log('You can install them manually: pip3 install -r requirements.txt');
|
|
}
|
|
} else {
|
|
console.log('⚠️ requirements.txt not found, skipping Python dependencies');
|
|
}
|
|
|
|
// Make scripts executable
|
|
console.log('🔧 Setting up permissions...');
|
|
const scriptsDir = path.join(packageRoot, 'scripts');
|
|
const hooksDir = path.join(packageRoot, 'hooks');
|
|
|
|
[scriptsDir, hooksDir].forEach(dir => {
|
|
if (fs.existsSync(dir)) {
|
|
const files = fs.readdirSync(dir);
|
|
files.forEach(file => {
|
|
if (file.endsWith('.py') || file.endsWith('.sh')) {
|
|
const filePath = path.join(dir, file);
|
|
try {
|
|
fs.chmodSync(filePath, 0o755);
|
|
} catch (e) {
|
|
// Ignore chmod errors on systems that don't support it
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
console.log('✓ Permissions configured');
|
|
|
|
// Create runtime directories
|
|
console.log('📁 Creating runtime directories...');
|
|
const runtimeDir = path.join(packageRoot, '.claude_hooks');
|
|
const subdirs = ['backups', 'logs', 'patterns'];
|
|
|
|
try {
|
|
if (!fs.existsSync(runtimeDir)) {
|
|
fs.mkdirSync(runtimeDir, { recursive: true });
|
|
}
|
|
|
|
subdirs.forEach(subdir => {
|
|
const subdirPath = path.join(runtimeDir, subdir);
|
|
if (!fs.existsSync(subdirPath)) {
|
|
fs.mkdirSync(subdirPath, { recursive: true });
|
|
}
|
|
});
|
|
|
|
console.log('✓ Runtime directories created');
|
|
} catch (error) {
|
|
console.log('⚠️ Could not create runtime directories:', error.message);
|
|
}
|
|
|
|
console.log('');
|
|
console.log('🎉 Claude Hooks installed successfully!');
|
|
console.log('');
|
|
console.log('Next steps:');
|
|
console.log('1. Run: claude-hooks init');
|
|
console.log('2. Restart Claude Code to activate hooks');
|
|
console.log('3. Test with: claude-hooks test');
|
|
console.log('');
|
|
console.log('For help: claude-hooks --help'); |