claude-hooks/scripts/manual-backup.py
Ryan Malloy 9445e09c48 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>
2025-07-19 21:03:13 -06:00

114 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""Manual Backup Script for Claude Hooks"""
import os
import sys
import json
from pathlib import Path
from datetime import datetime
# Add lib directory to path
sys.path.insert(0, str(Path(__file__).parent.parent / "lib"))
try:
from backup_manager import BackupManager
from session_state import SessionState
except ImportError as e:
print(f"Error importing backup modules: {e}")
print("Please ensure Claude Hooks is properly installed.")
sys.exit(1)
# Colors for terminal output
class Colors:
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
NC = '\033[0m' # No Color
def print_colored(message, color):
print(f"{color}{message}{Colors.NC}")
def print_status(message, status="INFO"):
colors = {
"SUCCESS": Colors.GREEN,
"ERROR": Colors.RED,
"WARNING": Colors.YELLOW,
"INFO": Colors.BLUE
}
print_colored(f"[{status}] {message}", colors.get(status, Colors.NC))
def main():
print_colored("Claude Hooks Manual Backup", Colors.BLUE)
print("=" * 30)
# Get package root and setup paths
package_root = Path(__file__).parent.parent
runtime_dir = package_root / ".claude_hooks"
try:
# Initialize backup manager
backup_manager = BackupManager(str(runtime_dir / "backups"))
session_state = SessionState(str(runtime_dir))
print("Creating manual backup...")
# Get current working directory (where user is working)
cwd = Path.cwd()
print(f"Backing up from: {cwd}")
# Create backup context
backup_context = {
"trigger": "manual",
"timestamp": datetime.now().isoformat(),
"cwd": str(cwd),
"session_info": session_state.get_session_summary()
}
# Perform backup
backup_id = backup_manager.create_backup(
project_path=str(cwd),
context=backup_context,
force=True # Allow manual backup even if recent backup exists
)
if backup_id:
print_status(f"Backup created successfully: {backup_id}", "SUCCESS")
# Show backup details
backup_info = backup_manager.get_backup_info(backup_id)
if backup_info:
print()
print_colored("Backup Details:", Colors.BLUE)
print(f"📁 Backup ID: {backup_id}")
print(f"📅 Created: {backup_info.get('timestamp', 'Unknown')}")
print(f"📂 Location: {backup_info.get('path', 'Unknown')}")
if 'files_backed_up' in backup_info:
file_count = len(backup_info['files_backed_up'])
print(f"📄 Files: {file_count}")
if file_count > 0 and file_count <= 10:
print(" Files backed up:")
for file_path in backup_info['files_backed_up'][:10]:
print(f" - {file_path}")
elif file_count > 10:
print(" Sample files backed up:")
for file_path in backup_info['files_backed_up'][:5]:
print(f" - {file_path}")
print(f" ... and {file_count - 5} more")
print()
print_colored("Backup completed successfully! 🎉", Colors.GREEN)
else:
print_status("Backup failed - check logs for details", "ERROR")
return 1
except Exception as e:
print_status(f"Backup error: {e}", "ERROR")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())