claude-code-tracker/install-hooks.sh

377 lines
11 KiB
Bash
Raw Permalink Normal View History

#!/bin/bash
# Claude Code Tracker - Hook Installation Script
# Automatically installs hooks for Claude Code using domain from environment
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CLAUDE_CONFIG_DIR="$HOME/.config/claude-code"
CLAUDE_SETTINGS_FILE="$CLAUDE_CONFIG_DIR/settings.json"
# Hook profiles available
AVAILABLE_PROFILES=(
"basic"
"essential"
"comprehensive"
"developer"
"power_user"
"research"
"team"
)
print_header() {
echo -e "${BLUE}╔════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Claude Code Tracker Hooks ║${NC}"
echo -e "${BLUE}║ Installation Script ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════╝${NC}"
echo ""
}
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
print_info() {
echo -e "${BLUE}${NC} $1"
}
check_requirements() {
print_info "Checking requirements..."
# Check if Claude Code is installed
if ! command -v claude-code &> /dev/null; then
print_error "Claude Code is not installed or not in PATH"
print_info "Please install Claude Code first: https://claude.ai/code"
exit 1
fi
# Check if jq is available for JSON manipulation
if ! command -v jq &> /dev/null; then
print_warning "jq is not installed. Using fallback JSON handling."
USE_JQ=false
else
USE_JQ=true
fi
# Check domain configuration
if [[ -z "$DOMAIN" ]]; then
# Try to read from .env file
if [[ -f "$SCRIPT_DIR/.env" ]]; then
source "$SCRIPT_DIR/.env"
fi
if [[ -z "$DOMAIN" ]]; then
print_error "DOMAIN environment variable is not set"
print_info "Please set DOMAIN environment variable or create .env file"
print_info "Example: export DOMAIN=claude.l.supported.systems"
exit 1
fi
fi
print_success "Domain configured: $DOMAIN"
print_success "Requirements check passed"
}
create_claude_config_dir() {
if [[ ! -d "$CLAUDE_CONFIG_DIR" ]]; then
print_info "Creating Claude Code configuration directory..."
mkdir -p "$CLAUDE_CONFIG_DIR"
print_success "Created directory: $CLAUDE_CONFIG_DIR"
fi
}
backup_existing_settings() {
if [[ -f "$CLAUDE_SETTINGS_FILE" ]]; then
local backup_file="${CLAUDE_SETTINGS_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
print_info "Backing up existing settings to: $backup_file"
cp "$CLAUDE_SETTINGS_FILE" "$backup_file"
print_success "Backup created"
fi
}
get_hook_profile_path() {
local profile="$1"
echo "$SCRIPT_DIR/claude-hooks-${profile}.json"
}
list_available_profiles() {
echo -e "${BLUE}Available hook profiles:${NC}"
echo ""
for profile in "${AVAILABLE_PROFILES[@]}"; do
local profile_file
profile_file=$(get_hook_profile_path "$profile")
if [[ -f "$profile_file" ]]; then
local description
if [[ "$USE_JQ" == true ]]; then
description=$(jq -r '.metadata.description // "No description available"' "$profile_file" 2>/dev/null || echo "No description available")
else
description="Hook configuration for $profile users"
fi
echo -e " ${GREEN}$profile${NC} - $description"
else
echo -e " ${RED}$profile${NC} - Profile file not found"
fi
done
echo ""
}
update_hook_domain() {
local input_file="$1"
local output_file="$2"
print_info "Updating hook URLs with domain: $DOMAIN"
# Replace placeholder domain with actual domain
sed "s/\${DOMAIN}/$DOMAIN/g; s/localhost:8000/$DOMAIN/g; s/http:\/\/$DOMAIN/https:\/\/$DOMAIN/g" "$input_file" > "$output_file"
print_success "Hook URLs updated"
}
install_hooks() {
local profile="$1"
local profile_file
profile_file=$(get_hook_profile_path "$profile")
if [[ ! -f "$profile_file" ]]; then
print_error "Hook profile file not found: $profile_file"
exit 1
fi
print_info "Installing hooks from profile: $profile"
# Create temporary file with updated domain
local temp_file="/tmp/claude-hooks-${profile}-$(date +%s).json"
update_hook_domain "$profile_file" "$temp_file"
# Merge with existing settings or create new
local final_settings="$temp_file"
if [[ -f "$CLAUDE_SETTINGS_FILE" ]] && [[ "$USE_JQ" == true ]]; then
print_info "Merging with existing Claude Code settings..."
# Merge hook configurations
local merged_file="/tmp/claude-settings-merged-$(date +%s).json"
jq -s '.[0] * .[1]' "$CLAUDE_SETTINGS_FILE" "$temp_file" > "$merged_file"
final_settings="$merged_file"
print_success "Settings merged"
fi
# Install the hooks
cp "$final_settings" "$CLAUDE_SETTINGS_FILE"
# Cleanup temp files
rm -f "$temp_file"
if [[ -f "$merged_file" ]]; then
rm -f "$merged_file"
fi
print_success "Hooks installed successfully!"
}
show_installation_summary() {
local profile="$1"
echo ""
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ Installation Complete! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}Profile installed:${NC} $profile"
echo -e "${BLUE}Domain configured:${NC} $DOMAIN"
echo -e "${BLUE}Settings file:${NC} $CLAUDE_SETTINGS_FILE"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo "1. Start using Claude Code in any project"
echo "2. Visit https://$DOMAIN/dashboard to view your tracking data"
echo "3. Check the documentation at https://$DOMAIN/dashboard/docs"
echo ""
echo -e "${BLUE}To test the installation:${NC}"
echo " claude-code --help"
echo ""
}
verify_installation() {
print_info "Verifying installation..."
if [[ -f "$CLAUDE_SETTINGS_FILE" ]]; then
if [[ "$USE_JQ" == true ]]; then
if jq empty "$CLAUDE_SETTINGS_FILE" 2>/dev/null; then
print_success "Settings file is valid JSON"
local hook_count
hook_count=$(jq -r '.hooks | length // 0' "$CLAUDE_SETTINGS_FILE" 2>/dev/null || echo "0")
print_success "Number of hooks configured: $hook_count"
return 0
else
print_error "Settings file contains invalid JSON"
return 1
fi
else
print_success "Settings file exists"
return 0
fi
else
print_error "Settings file was not created"
return 1
fi
}
show_help() {
echo "Claude Code Tracker - Hook Installation Script"
echo ""
echo "Usage: $0 [OPTIONS] [PROFILE]"
echo ""
echo "PROFILE: Hook profile to install (default: comprehensive)"
echo ""
echo "Options:"
echo " -l, --list List available profiles"
echo " -d, --domain DOMAIN Set the domain (overrides DOMAIN env var)"
echo " -h, --help Show this help message"
echo " --verify Verify existing installation"
echo " --uninstall Remove all hooks from settings"
echo ""
echo "Examples:"
echo " $0 # Install comprehensive profile"
echo " $0 basic # Install basic profile"
echo " $0 -d example.com # Install with custom domain"
echo " $0 --list # List available profiles"
echo ""
echo "Environment Variables:"
echo " DOMAIN Target domain for the Claude Code Tracker"
echo ""
}
uninstall_hooks() {
print_info "Uninstalling Claude Code Tracker hooks..."
if [[ ! -f "$CLAUDE_SETTINGS_FILE" ]]; then
print_warning "No settings file found, nothing to uninstall"
return 0
fi
backup_existing_settings
if [[ "$USE_JQ" == true ]]; then
# Remove hooks section but keep other settings
jq 'del(.hooks)' "$CLAUDE_SETTINGS_FILE" > "${CLAUDE_SETTINGS_FILE}.tmp"
mv "${CLAUDE_SETTINGS_FILE}.tmp" "$CLAUDE_SETTINGS_FILE"
print_success "Hooks removed from settings"
else
print_warning "Cannot automatically remove hooks without jq. Manual removal required."
print_info "Edit $CLAUDE_SETTINGS_FILE and remove the 'hooks' section"
fi
}
main() {
local profile="comprehensive"
local list_profiles=false
local verify_only=false
local uninstall_only=false
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-l|--list)
list_profiles=true
shift
;;
-d|--domain)
DOMAIN="$2"
shift 2
;;
--verify)
verify_only=true
shift
;;
--uninstall)
uninstall_only=true
shift
;;
-*)
print_error "Unknown option: $1"
show_help
exit 1
;;
*)
profile="$1"
shift
;;
esac
done
print_header
# Handle special modes
if [[ "$list_profiles" == true ]]; then
check_requirements
list_available_profiles
exit 0
fi
if [[ "$verify_only" == true ]]; then
check_requirements
verify_installation
exit $?
fi
if [[ "$uninstall_only" == true ]]; then
check_requirements
create_claude_config_dir
uninstall_hooks
print_success "Uninstallation complete"
exit 0
fi
# Main installation flow
check_requirements
create_claude_config_dir
backup_existing_settings
# Validate profile
if [[ ! " ${AVAILABLE_PROFILES[@]} " =~ " $profile " ]]; then
print_error "Unknown profile: $profile"
echo ""
list_available_profiles
exit 1
fi
# Install hooks
install_hooks "$profile"
# Verify installation
if verify_installation; then
show_installation_summary "$profile"
else
print_error "Installation verification failed"
exit 1
fi
}
# Run main function with all arguments
main "$@"