claude-code-tracker/install-hooks.sh
Ryan Malloy 1e1d4a995d Add comprehensive hook installation system and update documentation
Major Features Added:
• Automated hook installation scripts (install-hooks.sh and setup-hooks)
• User-scope installation with automatic domain configuration
• 7 pre-configured hook profiles for different user types
• Comprehensive documentation updates across all guides

Hook Installation System:
• ./setup-hooks - One-liner installation for most users
• ./install-hooks.sh - Full-featured installer with profile selection
• Automatic domain replacement using $DOMAIN environment variable
• Settings backup and verification capabilities
• Safe uninstallation with rollback support

Documentation Enhancements:
• Updated README.md with complete project overview and proper git repository URL
• Enhanced Getting Started guide with automated hook installation
• Improved Docker deployment guide with hook installation step
• Reorganized documentation index with better visual hierarchy
• Added repository URL: https://git.supported.systems/claude/claude-code-tracker.git

Technical Improvements:
• Rebuilt Docker containers with all latest changes
• Verified application health and functionality
• Updated all installation examples with correct repository URL
• Improved quick start workflow with 3-step visual process

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 09:30:37 -06:00

377 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 "$@"