From ef57dd58799bb0d3b67a07b26dc03fa6ce00975a Mon Sep 17 00:00:00 2001 From: catlog22 Date: Wed, 1 Oct 2025 22:26:23 +0800 Subject: [PATCH] feat: Add native Linux/macOS installation support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create Install-Claude.sh for native Bash installation - Update install-remote.sh to call Install-Claude.sh instead of PowerShell - Move installation section to top of README files - Add prominent shell installation instructions for all platforms - Support true cross-platform installation without PowerShell dependency Installation methods: - Windows: PowerShell (install-remote.ps1 + Install-Claude.ps1) - Linux/macOS: Bash (install-remote.sh + Install-Claude.sh) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- Install-Claude.sh | 783 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 35 ++- README_CN.md | 35 ++- install-remote.sh | 352 +++++++++++++++++++++ 4 files changed, 1179 insertions(+), 26 deletions(-) create mode 100644 Install-Claude.sh create mode 100644 install-remote.sh diff --git a/Install-Claude.sh b/Install-Claude.sh new file mode 100644 index 00000000..8dc0a2ef --- /dev/null +++ b/Install-Claude.sh @@ -0,0 +1,783 @@ +#!/usr/bin/env bash +# Claude Code Workflow System Interactive Installer +# Installation script for Claude Code Workflow System with Agent coordination and distributed memory system. +# Installs globally to user profile directory (~/.claude) by default. + +set -e # Exit on error + +# Script metadata +SCRIPT_NAME="Claude Code Workflow System Installer" +VERSION="2.1.0" + +# Colors for output +COLOR_RESET='\033[0m' +COLOR_SUCCESS='\033[0;32m' +COLOR_INFO='\033[0;36m' +COLOR_WARNING='\033[0;33m' +COLOR_ERROR='\033[0;31m' +COLOR_PROMPT='\033[0;35m' + +# Default parameters +INSTALL_MODE="" +TARGET_PATH="" +FORCE=false +NON_INTERACTIVE=false +BACKUP_ALL=true # Enabled by default +NO_BACKUP=false + +# Functions +function write_color() { + local message="$1" + local color="${2:-$COLOR_RESET}" + echo -e "${color}${message}${COLOR_RESET}" +} + +function show_banner() { + echo "" + # CLAUDE - Cyan color + write_color ' ______ __ __ ' "$COLOR_INFO" + write_color ' / \ | \ | \ ' "$COLOR_INFO" + write_color '| $$$$$$\| $$ ______ __ __ ____| $$ ______ ' "$COLOR_INFO" + write_color '| $$ \$$| $$ | \ | \ | \ / $$ / \ ' "$COLOR_INFO" + write_color '| $$ | $$ \$$$$$$\| $$ | $$| $$$$$$$| $$$$$$\ ' "$COLOR_INFO" + write_color '| $$ __ | $$ / $$| $$ | $$| $$ | $$| $$ $$ ' "$COLOR_INFO" + write_color '| $$__/ \| $$| $$$$$$$| $$__/ $$| $$__| $$| $$$$$$$$ ' "$COLOR_INFO" + write_color ' \$$ $$| $$ \$$ $$ \$$ $$ \$$ $$ \$$ \ ' "$COLOR_INFO" + write_color ' \$$$$$$ \$$ \$$$$$$$ \$$$$$$ \$$$$$$$ \$$$$$$$ ' "$COLOR_INFO" + echo "" + + # CODE - Green color + write_color ' ______ __ ' "$COLOR_SUCCESS" + write_color '/ \ | \ ' "$COLOR_SUCCESS" + write_color '| $$$$$$\ ______ ____| $$ ______ ' "$COLOR_SUCCESS" + write_color '| $$ \$$ / \ / $$ / \ ' "$COLOR_SUCCESS" + write_color '| $$ | $$$$$$\| $$$$$$$| $$$$$$\ ' "$COLOR_SUCCESS" + write_color '| $$ __ | $$ | $$| $$ | $$| $$ $$ ' "$COLOR_SUCCESS" + write_color '| $$__/ \| $$__/ $$| $$__| $$| $$$$$$$$ ' "$COLOR_SUCCESS" + write_color ' \$$ $$ \$$ $$ \$$ $$ \$$ \ ' "$COLOR_SUCCESS" + write_color ' \$$$$$$ \$$$$$$ \$$$$$$$ \$$$$$$$ ' "$COLOR_SUCCESS" + echo "" + + # WORKFLOW - Yellow color + write_color '__ __ __ ______ __ ' "$COLOR_WARNING" + write_color '| \ _ | \ | \ / \ | \ ' "$COLOR_WARNING" + write_color '| $$ / \ | $$ ______ ______ | $$ __ | $$$$$$\| $$ ______ __ __ __ ' "$COLOR_WARNING" + write_color '| $$/ $\| $$ / \ / \ | $$ / \| $$_ \$$| $$ / \ | \ | \ | \' "$COLOR_WARNING" + write_color '| $$ $$$\ $$| $$$$$$\| $$$$$$\| $$_/ $$| $$ \ | $$| $$$$$$\| $$ | $$ | $$' "$COLOR_WARNING" + write_color '| $$ $$\$$\$$| $$ | $$| $$ \$$| $$ $$ | $$$$ | $$| $$ | $$| $$ | $$ | $$' "$COLOR_WARNING" + write_color '| $$$$ \$$$$| $$__/ $$| $$ | $$$$$$\ | $$ | $$| $$__/ $$| $$_/ $$_/ $$' "$COLOR_WARNING" + write_color '| $$$ \$$$ \$$ $$| $$ | $$ \$$\| $$ | $$ \$$ $$ \$$ $$ $$' "$COLOR_WARNING" + write_color ' \$$ \$$ \$$$$$$ \$$ \$$ \$$ \$$ \$$ \$$$$$$ \$$$$$\$$$$' "$COLOR_WARNING" + echo "" +} + +function show_header() { + show_banner + write_color " $SCRIPT_NAME v$VERSION" "$COLOR_INFO" + write_color " Unified workflow system with comprehensive coordination" "$COLOR_INFO" + write_color "========================================================================" "$COLOR_INFO" + + if [ "$NO_BACKUP" = true ]; then + write_color "WARNING: Backup disabled - existing files will be overwritten!" "$COLOR_WARNING" + else + write_color "Auto-backup enabled - existing files will be backed up" "$COLOR_SUCCESS" + fi + echo "" +} + +function test_prerequisites() { + # Test bash version + if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then + write_color "ERROR: Bash 4.0 or higher is required" "$COLOR_ERROR" + write_color "Current version: ${BASH_VERSION}" "$COLOR_ERROR" + return 1 + fi + + # Test source files exist + local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local claude_dir="$script_dir/.claude" + local claude_md="$script_dir/CLAUDE.md" + + if [ ! -d "$claude_dir" ]; then + write_color "ERROR: .claude directory not found in $script_dir" "$COLOR_ERROR" + return 1 + fi + + if [ ! -f "$claude_md" ]; then + write_color "ERROR: CLAUDE.md file not found in $script_dir" "$COLOR_ERROR" + return 1 + fi + + write_color "✓ Prerequisites check passed" "$COLOR_SUCCESS" + return 0 +} + +function get_user_choice() { + local prompt="$1" + shift + local options=("$@") + local default_index=0 + + if [ "$NON_INTERACTIVE" = true ]; then + write_color "Non-interactive mode: Using default '${options[$default_index]}'" "$COLOR_INFO" + echo "${options[$default_index]}" + return + fi + + echo "" + write_color "$prompt" "$COLOR_PROMPT" + echo "" + + for i in "${!options[@]}"; do + echo " $((i + 1)). ${options[$i]}" + done + + while true; do + read -p "Please select (1-${#options[@]}): " choice + + if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then + echo "${options[$((choice - 1))]}" + return + fi + + write_color "Invalid selection. Please enter a number between 1 and ${#options[@]}" "$COLOR_WARNING" + done +} + +function confirm_action() { + local message="$1" + local default_yes="${2:-false}" + + if [ "$FORCE" = true ]; then + write_color "Force mode: Proceeding with '$message'" "$COLOR_INFO" + return 0 + fi + + if [ "$NON_INTERACTIVE" = true ]; then + if [ "$default_yes" = true ]; then + write_color "Non-interactive mode: $message - Yes" "$COLOR_INFO" + return 0 + else + write_color "Non-interactive mode: $message - No" "$COLOR_INFO" + return 1 + fi + fi + + local prompt + if [ "$default_yes" = true ]; then + prompt="(Y/n)" + else + prompt="(y/N)" + fi + + while true; do + read -p "$message $prompt " response + + if [ -z "$response" ]; then + [ "$default_yes" = true ] && return 0 || return 1 + fi + + case "${response,,}" in + y|yes) return 0 ;; + n|no) return 1 ;; + *) write_color "Please answer 'y' or 'n'" "$COLOR_WARNING" ;; + esac + done +} + +function get_backup_directory() { + local target_dir="$1" + local timestamp=$(date +"%Y%m%d-%H%M%S") + local backup_dir="${target_dir}/claude-backup-${timestamp}" + + mkdir -p "$backup_dir" + echo "$backup_dir" +} + +function backup_file_to_folder() { + local file_path="$1" + local backup_folder="$2" + + if [ ! -f "$file_path" ]; then + return 1 + fi + + local file_name=$(basename "$file_path") + local file_dir=$(dirname "$file_path") + local relative_path="" + + # Try to determine relative path structure + if [[ "$file_dir" == *".claude"* ]]; then + relative_path="${file_dir#*.claude/}" + fi + + # Create subdirectory structure in backup if needed + local backup_sub_dir="$backup_folder" + if [ -n "$relative_path" ]; then + backup_sub_dir="${backup_folder}/${relative_path}" + mkdir -p "$backup_sub_dir" + fi + + local backup_file_path="${backup_sub_dir}/${file_name}" + + if cp "$file_path" "$backup_file_path"; then + write_color "Backed up: $file_name" "$COLOR_INFO" + return 0 + else + write_color "WARNING: Failed to backup file $file_path" "$COLOR_WARNING" + return 1 + fi +} + +function backup_directory_to_folder() { + local dir_path="$1" + local backup_folder="$2" + + if [ ! -d "$dir_path" ]; then + return 1 + fi + + local dir_name=$(basename "$dir_path") + local backup_dir_path="${backup_folder}/${dir_name}" + + if cp -r "$dir_path" "$backup_dir_path"; then + write_color "Backed up directory: $dir_name" "$COLOR_INFO" + return 0 + else + write_color "WARNING: Failed to backup directory $dir_path" "$COLOR_WARNING" + return 1 + fi +} + +function copy_directory_recursive() { + local source="$1" + local destination="$2" + + if [ ! -d "$source" ]; then + write_color "ERROR: Source directory does not exist: $source" "$COLOR_ERROR" + return 1 + fi + + mkdir -p "$destination" + + if cp -r "$source/"* "$destination/"; then + write_color "✓ Directory copied: $source -> $destination" "$COLOR_SUCCESS" + return 0 + else + write_color "ERROR: Failed to copy directory" "$COLOR_ERROR" + return 1 + fi +} + +function copy_file_to_destination() { + local source="$1" + local destination="$2" + local description="${3:-file}" + local backup_folder="${4:-}" + + if [ -f "$destination" ]; then + # Use BackupAll mode for automatic backup + if [ "$BACKUP_ALL" = true ] && [ "$NO_BACKUP" = false ]; then + if [ -n "$backup_folder" ]; then + backup_file_to_folder "$destination" "$backup_folder" + write_color "Auto-backed up: $description" "$COLOR_SUCCESS" + fi + cp "$source" "$destination" + write_color "$description updated (with backup)" "$COLOR_SUCCESS" + return 0 + elif [ "$NO_BACKUP" = true ]; then + if confirm_action "$description already exists. Replace it? (NO BACKUP)" false; then + cp "$source" "$destination" + write_color "$description updated (no backup)" "$COLOR_WARNING" + return 0 + else + write_color "Skipping $description installation" "$COLOR_WARNING" + return 1 + fi + elif confirm_action "$description already exists. Replace it?" false; then + if [ -n "$backup_folder" ]; then + backup_file_to_folder "$destination" "$backup_folder" + write_color "Existing $description backed up" "$COLOR_SUCCESS" + fi + cp "$source" "$destination" + write_color "$description updated" "$COLOR_SUCCESS" + return 0 + else + write_color "Skipping $description installation" "$COLOR_WARNING" + return 1 + fi + else + # Ensure destination directory exists + local dest_dir=$(dirname "$destination") + mkdir -p "$dest_dir" + cp "$source" "$destination" + write_color "✓ $description installed" "$COLOR_SUCCESS" + return 0 + fi +} + +function merge_directory_contents() { + local source="$1" + local destination="$2" + local description="${3:-directory contents}" + local backup_folder="${4:-}" + + if [ ! -d "$source" ]; then + write_color "WARNING: Source $description not found: $source" "$COLOR_WARNING" + return 1 + fi + + mkdir -p "$destination" + write_color "Created destination directory: $destination" "$COLOR_INFO" + + local merged_count=0 + local skipped_count=0 + + # Find all files recursively + while IFS= read -r -d '' file; do + local relative_path="${file#$source/}" + local dest_path="${destination}/${relative_path}" + local dest_dir=$(dirname "$dest_path") + + mkdir -p "$dest_dir" + + if [ -f "$dest_path" ]; then + local file_name=$(basename "$relative_path") + + if [ "$BACKUP_ALL" = true ] && [ "$NO_BACKUP" = false ]; then + if [ -n "$backup_folder" ]; then + backup_file_to_folder "$dest_path" "$backup_folder" + write_color "Auto-backed up: $file_name" "$COLOR_INFO" + fi + cp "$file" "$dest_path" + ((merged_count++)) + elif [ "$NO_BACKUP" = true ]; then + if confirm_action "File '$relative_path' already exists. Replace it? (NO BACKUP)" false; then + cp "$file" "$dest_path" + ((merged_count++)) + else + write_color "Skipped $file_name (no backup)" "$COLOR_WARNING" + ((skipped_count++)) + fi + elif confirm_action "File '$relative_path' already exists. Replace it?" false; then + if [ -n "$backup_folder" ]; then + backup_file_to_folder "$dest_path" "$backup_folder" + write_color "Backed up existing $file_name" "$COLOR_INFO" + fi + cp "$file" "$dest_path" + ((merged_count++)) + else + write_color "Skipped $file_name" "$COLOR_WARNING" + ((skipped_count++)) + fi + else + cp "$file" "$dest_path" + ((merged_count++)) + fi + done < <(find "$source" -type f -print0) + + write_color "✓ Merged $merged_count files, skipped $skipped_count files" "$COLOR_SUCCESS" + return 0 +} + +function install_global() { + write_color "Installing Claude Code Workflow System globally..." "$COLOR_INFO" + + local user_home="$HOME" + local global_claude_dir="${user_home}/.claude" + local global_claude_md="${global_claude_dir}/CLAUDE.md" + + write_color "Global installation path: $user_home" "$COLOR_INFO" + + # Source paths + local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local source_claude_dir="${script_dir}/.claude" + local source_claude_md="${script_dir}/CLAUDE.md" + + # Create backup folder if needed + local backup_folder="" + if [ "$NO_BACKUP" = false ]; then + if [ -d "$global_claude_dir" ] && [ "$(ls -A "$global_claude_dir" 2>/dev/null)" ]; then + backup_folder=$(get_backup_directory "$user_home") + write_color "Backup folder created: $backup_folder" "$COLOR_INFO" + elif [ -f "$global_claude_md" ]; then + backup_folder=$(get_backup_directory "$user_home") + write_color "Backup folder created: $backup_folder" "$COLOR_INFO" + fi + fi + + # Merge .claude directory contents + write_color "Merging .claude directory contents..." "$COLOR_INFO" + merge_directory_contents "$source_claude_dir" "$global_claude_dir" ".claude directory contents" "$backup_folder" + + # Handle CLAUDE.md file + write_color "Installing CLAUDE.md to global .claude directory..." "$COLOR_INFO" + copy_file_to_destination "$source_claude_md" "$global_claude_md" "CLAUDE.md" "$backup_folder" + + # Remove empty backup folder + if [ -n "$backup_folder" ] && [ -d "$backup_folder" ]; then + if [ -z "$(ls -A "$backup_folder" 2>/dev/null)" ]; then + rm -rf "$backup_folder" + write_color "Removed empty backup folder" "$COLOR_INFO" + fi + fi + + return 0 +} + +function install_path() { + local target_dir="$1" + + write_color "Installing Claude Code Workflow System in hybrid mode..." "$COLOR_INFO" + write_color "Local path: $target_dir" "$COLOR_INFO" + + local user_home="$HOME" + local global_claude_dir="${user_home}/.claude" + write_color "Global path: $user_home" "$COLOR_INFO" + + # Source paths + local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local source_claude_dir="${script_dir}/.claude" + local source_claude_md="${script_dir}/CLAUDE.md" + + # Local paths + local local_claude_dir="${target_dir}/.claude" + + # Create backup folder if needed + local backup_folder="" + if [ "$NO_BACKUP" = false ]; then + if [ -d "$local_claude_dir" ] || [ -d "$global_claude_dir" ]; then + backup_folder=$(get_backup_directory "$target_dir") + write_color "Backup folder created: $backup_folder" "$COLOR_INFO" + fi + fi + + # Create local .claude directory + mkdir -p "$local_claude_dir" + write_color "✓ Created local .claude directory" "$COLOR_SUCCESS" + + # Local folders to install + local local_folders=("agents" "commands" "output-styles") + + write_color "Installing local components (agents, commands, output-styles)..." "$COLOR_INFO" + for folder in "${local_folders[@]}"; do + local source_folder="${source_claude_dir}/${folder}" + local dest_folder="${local_claude_dir}/${folder}" + + if [ -d "$source_folder" ]; then + if [ -d "$dest_folder" ] && [ -n "$backup_folder" ]; then + backup_directory_to_folder "$dest_folder" "$backup_folder" + fi + + copy_directory_recursive "$source_folder" "$dest_folder" + write_color "✓ Installed local folder: $folder" "$COLOR_SUCCESS" + else + write_color "WARNING: Source folder not found: $folder" "$COLOR_WARNING" + fi + done + + # Global components - exclude local folders + write_color "Installing global components to $global_claude_dir..." "$COLOR_INFO" + + local merged_count=0 + + while IFS= read -r -d '' file; do + local relative_path="${file#$source_claude_dir/}" + local top_folder=$(echo "$relative_path" | cut -d'/' -f1) + + # Skip local folders + if [[ " ${local_folders[*]} " =~ " ${top_folder} " ]]; then + continue + fi + + local dest_path="${global_claude_dir}/${relative_path}" + local dest_dir=$(dirname "$dest_path") + + mkdir -p "$dest_dir" + + if [ -f "$dest_path" ]; then + if [ "$BACKUP_ALL" = true ] && [ "$NO_BACKUP" = false ]; then + if [ -n "$backup_folder" ]; then + backup_file_to_folder "$dest_path" "$backup_folder" + fi + cp "$file" "$dest_path" + ((merged_count++)) + elif [ "$NO_BACKUP" = true ]; then + if confirm_action "File '$relative_path' already exists in global location. Replace it? (NO BACKUP)" false; then + cp "$file" "$dest_path" + ((merged_count++)) + fi + elif confirm_action "File '$relative_path' already exists in global location. Replace it?" false; then + if [ -n "$backup_folder" ]; then + backup_file_to_folder "$dest_path" "$backup_folder" + fi + cp "$file" "$dest_path" + ((merged_count++)) + fi + else + cp "$file" "$dest_path" + ((merged_count++)) + fi + done < <(find "$source_claude_dir" -type f -print0) + + write_color "✓ Merged $merged_count files to global location" "$COLOR_SUCCESS" + + # Handle CLAUDE.md file in global .claude directory + local global_claude_md="${global_claude_dir}/CLAUDE.md" + write_color "Installing CLAUDE.md to global .claude directory..." "$COLOR_INFO" + copy_file_to_destination "$source_claude_md" "$global_claude_md" "CLAUDE.md" "$backup_folder" + + # Remove empty backup folder + if [ -n "$backup_folder" ] && [ -d "$backup_folder" ]; then + if [ -z "$(ls -A "$backup_folder" 2>/dev/null)" ]; then + rm -rf "$backup_folder" + write_color "Removed empty backup folder" "$COLOR_INFO" + fi + fi + + return 0 +} + +function get_installation_mode() { + if [ -n "$INSTALL_MODE" ]; then + write_color "Installation mode: $INSTALL_MODE" "$COLOR_INFO" + echo "$INSTALL_MODE" + return + fi + + local modes=( + "Global - Install to user profile (~/.claude/)" + "Path - Install to custom directory (partial local + global)" + ) + + local selection=$(get_user_choice "Choose installation mode:" "${modes[@]}") + + if [[ "$selection" == Global* ]]; then + echo "Global" + elif [[ "$selection" == Path* ]]; then + echo "Path" + else + echo "Global" + fi +} + +function get_installation_path() { + local mode="$1" + + if [ "$mode" = "Global" ]; then + echo "$HOME" + return + fi + + if [ -n "$TARGET_PATH" ]; then + if [ -d "$TARGET_PATH" ]; then + echo "$TARGET_PATH" + return + fi + write_color "WARNING: Specified target path does not exist: $TARGET_PATH" "$COLOR_WARNING" + fi + + # Interactive path selection + while true; do + echo "" + write_color "Enter the target directory path for installation:" "$COLOR_PROMPT" + write_color "(This will install agents, commands, output-styles locally, other files globally)" "$COLOR_INFO" + read -p "Path: " path + + if [ -z "$path" ]; then + write_color "Path cannot be empty" "$COLOR_WARNING" + continue + fi + + # Expand ~ and environment variables + path=$(eval echo "$path") + + if [ -d "$path" ]; then + echo "$path" + return + fi + + write_color "Path does not exist: $path" "$COLOR_WARNING" + if confirm_action "Create this directory?" true; then + if mkdir -p "$path"; then + write_color "✓ Directory created successfully" "$COLOR_SUCCESS" + echo "$path" + return + else + write_color "ERROR: Failed to create directory" "$COLOR_ERROR" + fi + fi + done +} + +function show_summary() { + local mode="$1" + local path="$2" + local success="$3" + + echo "" + if [ "$success" = true ]; then + write_color "✓ Installation completed successfully!" "$COLOR_SUCCESS" + else + write_color "Installation completed with warnings" "$COLOR_WARNING" + fi + + write_color "Installation Details:" "$COLOR_INFO" + echo " Mode: $mode" + + if [ "$mode" = "Path" ]; then + echo " Local Path: $path" + echo " Global Path: $HOME" + echo " Local Components: agents, commands, output-styles" + echo " Global Components: workflows, scripts, python_script, etc." + else + echo " Path: $path" + fi + + if [ "$NO_BACKUP" = true ]; then + echo " Backup: Disabled (no backup created)" + elif [ "$BACKUP_ALL" = true ]; then + echo " Backup: Enabled (automatic backup of all existing files)" + else + echo " Backup: Enabled (default behavior)" + fi + + echo "" + write_color "Next steps:" "$COLOR_INFO" + echo "1. Review CLAUDE.md - Customize guidelines for your project" + echo "2. Configure settings - Edit .claude/settings.local.json as needed" + echo "3. Start using Claude Code with Agent workflow coordination!" + echo "4. Use /workflow commands for task execution" + echo "5. Use /update-memory commands for memory system management" + + echo "" + write_color "Documentation: https://github.com/catlog22/Claude-Code-Workflow" "$COLOR_INFO" + write_color "Features: Unified workflow system with comprehensive file output generation" "$COLOR_INFO" +} + +function parse_arguments() { + while [[ $# -gt 0 ]]; do + case "$1" in + -InstallMode) + INSTALL_MODE="$2" + shift 2 + ;; + -TargetPath) + TARGET_PATH="$2" + shift 2 + ;; + -Force) + FORCE=true + shift + ;; + -NonInteractive) + NON_INTERACTIVE=true + shift + ;; + -BackupAll) + BACKUP_ALL=true + NO_BACKUP=false + shift + ;; + -NoBackup) + NO_BACKUP=true + BACKUP_ALL=false + shift + ;; + --help|-h) + show_help + exit 0 + ;; + *) + write_color "Unknown option: $1" "$COLOR_ERROR" + show_help + exit 1 + ;; + esac + done +} + +function show_help() { + cat << EOF +$SCRIPT_NAME v$VERSION + +Usage: $0 [OPTIONS] + +Options: + -InstallMode Installation mode: Global or Path + -TargetPath Target path for Path installation mode + -Force Skip confirmation prompts + -NonInteractive Run in non-interactive mode with default options + -BackupAll Automatically backup all existing files (default) + -NoBackup Disable automatic backup functionality + --help, -h Show this help message + +Examples: + # Interactive installation + $0 + + # Global installation without prompts + $0 -InstallMode Global -Force + + # Path installation with custom directory + $0 -InstallMode Path -TargetPath /opt/claude-code-workflow + + # Installation without backup + $0 -NoBackup + +EOF +} + +function main() { + show_header + + # Test prerequisites + write_color "Checking system requirements..." "$COLOR_INFO" + if ! test_prerequisites; then + write_color "Prerequisites check failed!" "$COLOR_ERROR" + return 1 + fi + + local mode=$(get_installation_mode) + local install_path="" + local success=false + + if [ "$mode" = "Global" ]; then + install_path="$HOME" + if install_global; then + success=true + fi + elif [ "$mode" = "Path" ]; then + install_path=$(get_installation_path "$mode") + if install_path "$install_path"; then + success=true + fi + fi + + show_summary "$mode" "$install_path" "$success" + + # Wait for user confirmation in interactive mode + if [ "$NON_INTERACTIVE" != true ]; then + echo "" + write_color "Installation completed. Press Enter to exit..." "$COLOR_PROMPT" + read -r + fi + + if [ "$success" = true ]; then + return 0 + else + return 1 + fi +} + +# Initialize backup behavior - backup is enabled by default unless NoBackup is specified +if [ "$NO_BACKUP" = false ]; then + BACKUP_ALL=true +fi + +# Parse command line arguments +parse_arguments "$@" + +# Run main function +main +exit $? diff --git a/README.md b/README.md index 5dc29d4a..0df47327 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,27 @@ --- +## ⚙️ Installation + +### 🚀 **Quick Installation via Shell** + +**For PowerShell (Windows):** +```powershell +Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content +``` + +**For Bash/Zsh (Linux/macOS):** +```bash +bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) +``` + +### ✅ **Verify Installation** +```bash +/workflow:session:list +``` + +--- + ## 📋 Overview **Claude Code Workflow (CCW)** is a next-generation multi-agent automation framework for software development that orchestrates complex development tasks through intelligent workflow management and autonomous execution. @@ -584,19 +605,7 @@ Test workflow automatically generates multi-level tests: --- -## ⚙️ Installation & Configuration - -### 🚀 **Quick Installation** -```powershell -Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content -``` - -### ✅ **Verify Installation** -```bash -/workflow:session:list -``` - -### ⚙️ **Essential Configuration** +## ⚙️ Essential Configuration #### **Gemini CLI Setup** ```json diff --git a/README_CN.md b/README_CN.md index 958f74cb..e2b56833 100644 --- a/README_CN.md +++ b/README_CN.md @@ -13,6 +13,27 @@ --- +## ⚙️ 安装 + +### 🚀 **通过 Shell 快速安装** + +**PowerShell (Windows):** +```powershell +Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content +``` + +**Bash/Zsh (Linux/macOS):** +```bash +bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) +``` + +### ✅ **验证安装** +```bash +/workflow:session:list +``` + +--- + ## 📋 概述 **Claude Code Workflow (CCW)** 是新一代多智能体自动化开发框架,通过智能工作流管理和自主执行协调复杂的软件开发任务。 @@ -277,19 +298,7 @@ graph LR - `related`: 仅更新受近期变更影响的模块 - `full`: 完整的项目级文档刷新 -## 安装 - -### 快速安装 -```powershell -Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content -``` - -### 验证安装 -```bash -/workflow:session:list -``` - -### 必需配置 +## 必需配置 对于Gemini CLI集成,配置您的设置: ```json { diff --git a/install-remote.sh b/install-remote.sh new file mode 100644 index 00000000..21d764f5 --- /dev/null +++ b/install-remote.sh @@ -0,0 +1,352 @@ +#!/usr/bin/env bash +# Claude Code Workflow (CCW) - Remote Installation Script +# One-liner remote installation for Claude Code Workflow system + +set -e # Exit on error + +# Script metadata +SCRIPT_NAME="Claude Code Workflow (CCW) Remote Installer" +VERSION="2.1.1" +BRANCH="${BRANCH:-main}" + +# Colors for output +COLOR_RESET='\033[0m' +COLOR_SUCCESS='\033[0;32m' +COLOR_INFO='\033[0;36m' +COLOR_WARNING='\033[0;33m' +COLOR_ERROR='\033[0;31m' + +# Variables +INSTALL_GLOBAL=false +INSTALL_DIR="" +FORCE=false +NO_BACKUP=false +NON_INTERACTIVE=false +BACKUP_ALL=false + +# Functions +function write_color() { + local message="$1" + local color="${2:-$COLOR_RESET}" + echo -e "${color}${message}${COLOR_RESET}" +} + +function show_header() { + write_color "==== $SCRIPT_NAME v$VERSION ====" "$COLOR_INFO" + write_color "========================================================" "$COLOR_INFO" + echo "" +} + +function test_prerequisites() { + # Test bash version + if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then + write_color "ERROR: Bash 4.0 or higher is required" "$COLOR_ERROR" + write_color "Current version: ${BASH_VERSION}" "$COLOR_ERROR" + return 1 + fi + + # Test required commands + for cmd in curl unzip; do + if ! command -v "$cmd" &> /dev/null; then + write_color "ERROR: Required command '$cmd' not found" "$COLOR_ERROR" + write_color "Please install: $cmd" "$COLOR_ERROR" + return 1 + fi + done + + # Test internet connectivity + if curl -sSf --connect-timeout 10 "https://github.com" &> /dev/null; then + write_color "✓ Network connection OK" "$COLOR_SUCCESS" + else + write_color "ERROR: Cannot connect to GitHub" "$COLOR_ERROR" + write_color "Please check your network connection" "$COLOR_ERROR" + return 1 + fi + + return 0 +} + +function get_temp_directory() { + local temp_dir + temp_dir=$(mktemp -d -t claude-code-workflow-install.XXXXXX) + echo "$temp_dir" +} + +function download_repository() { + local temp_dir="$1" + local branch="${2:-main}" + local repo_url="https://github.com/catlog22/Claude-Code-Workflow" + local zip_url="${repo_url}/archive/refs/heads/${branch}.zip" + local zip_path="${temp_dir}/repo.zip" + + write_color "Downloading from GitHub..." "$COLOR_INFO" + write_color "Source: $repo_url" "$COLOR_INFO" + write_color "Branch: $branch" "$COLOR_INFO" + + if curl -fsSL -o "$zip_path" "$zip_url"; then + local file_size + file_size=$(du -h "$zip_path" | cut -f1) + write_color "✓ Download complete ($file_size)" "$COLOR_SUCCESS" + echo "$zip_path" + return 0 + else + write_color "Download failed" "$COLOR_ERROR" + return 1 + fi +} + +function extract_repository() { + local zip_path="$1" + local temp_dir="$2" + + write_color "Extracting files..." "$COLOR_INFO" + + if unzip -q "$zip_path" -d "$temp_dir"; then + # Find the extracted directory (usually repo-name-branch) + local repo_dir + repo_dir=$(find "$temp_dir" -maxdepth 1 -type d -name "Claude-Code-Workflow-*" | head -n 1) + + if [ -n "$repo_dir" ]; then + write_color "✓ Extraction complete: $repo_dir" "$COLOR_SUCCESS" + echo "$repo_dir" + return 0 + else + write_color "Could not find extracted repository directory" "$COLOR_ERROR" + return 1 + fi + else + write_color "Extraction failed" "$COLOR_ERROR" + return 1 + fi +} + +function invoke_local_installer() { + local repo_dir="$1" + local installer_path="${repo_dir}/Install-Claude.sh" + + # Make installer executable + if [ -f "$installer_path" ]; then + chmod +x "$installer_path" + else + write_color "ERROR: Install-Claude.sh not found" "$COLOR_ERROR" + return 1 + fi + + write_color "Running local installer..." "$COLOR_INFO" + echo "" + + # Build parameters for local installer + local params=() + + if [ "$INSTALL_GLOBAL" = true ]; then + params+=("-InstallMode" "Global") + fi + + if [ -n "$INSTALL_DIR" ]; then + params+=("-InstallMode" "Path" "-TargetPath" "$INSTALL_DIR") + fi + + if [ "$FORCE" = true ]; then + params+=("-Force") + fi + + if [ "$NO_BACKUP" = true ]; then + params+=("-NoBackup") + fi + + if [ "$NON_INTERACTIVE" = true ]; then + params+=("-NonInteractive") + fi + + if [ "$BACKUP_ALL" = true ]; then + params+=("-BackupAll") + fi + + # Execute installer + if (cd "$repo_dir" && "$installer_path" "${params[@]}"); then + return 0 + else + write_color "Installation script failed" "$COLOR_ERROR" + return 1 + fi +} + +function cleanup_temp_files() { + local temp_dir="$1" + + if [ -d "$temp_dir" ]; then + if rm -rf "$temp_dir"; then + write_color "✓ Temporary files cleaned up" "$COLOR_INFO" + else + write_color "WARNING: Failed to clean temporary files" "$COLOR_WARNING" + fi + fi +} + +function wait_for_user() { + local message="${1:-Press Enter to continue...}" + + if [ "$NON_INTERACTIVE" != true ]; then + echo "" + write_color "$message" "$COLOR_INFO" + read -r + echo "" + fi +} + +function parse_arguments() { + while [[ $# -gt 0 ]]; do + case "$1" in + --global) + INSTALL_GLOBAL=true + shift + ;; + --directory) + INSTALL_DIR="$2" + shift 2 + ;; + --force) + FORCE=true + shift + ;; + --no-backup) + NO_BACKUP=true + shift + ;; + --non-interactive) + NON_INTERACTIVE=true + shift + ;; + --backup-all) + BACKUP_ALL=true + shift + ;; + --branch) + BRANCH="$2" + shift 2 + ;; + --help) + show_help + exit 0 + ;; + *) + write_color "Unknown option: $1" "$COLOR_ERROR" + show_help + exit 1 + ;; + esac + done +} + +function show_help() { + cat << EOF +$SCRIPT_NAME v$VERSION + +Usage: $0 [OPTIONS] + +Options: + --global Install to global user directory (~/.claude) + --directory DIR Install to custom directory + --force Force installation without prompts + --no-backup Skip backup creation + --non-interactive Non-interactive mode (no prompts) + --backup-all Backup all files before installation + --branch BRANCH Specify GitHub branch (default: main) + --help Show this help message + +Examples: + # Interactive installation + $0 + + # Global installation without prompts + $0 --global --non-interactive + + # Custom directory installation + $0 --directory /opt/claude-code-workflow + +EOF +} + +function main() { + show_header + + write_color "This will download and install Claude Code Workflow System from GitHub." "$COLOR_INFO" + echo "" + + # Test prerequisites + write_color "Checking system requirements..." "$COLOR_INFO" + if ! test_prerequisites; then + wait_for_user "System check failed! Press Enter to exit..." + exit 1 + fi + + # Confirm installation + if [ "$NON_INTERACTIVE" != true ] && [ "$FORCE" != true ]; then + echo "" + write_color "SECURITY NOTE:" "$COLOR_WARNING" + echo "- This script will download and execute Claude Code Workflow from GitHub" + echo "- Repository: https://github.com/catlog22/Claude-Code-Workflow" + echo "- Branch: $BRANCH (latest stable version)" + echo "- Features: Intelligent workflow orchestration with multi-agent coordination" + echo "- Please ensure you trust this source" + echo "" + + read -p "Continue with installation? (y/N) " -r choice + if [[ ! $choice =~ ^[Yy]$ ]]; then + write_color "Installation cancelled" "$COLOR_WARNING" + exit 0 + fi + fi + + # Create temp directory + local temp_dir + temp_dir=$(get_temp_directory) + write_color "Temporary directory: $temp_dir" "$COLOR_INFO" + + local success=false + + # Download repository + local zip_path + if zip_path=$(download_repository "$temp_dir" "$BRANCH"); then + # Extract repository + local repo_dir + if repo_dir=$(extract_repository "$zip_path" "$temp_dir"); then + # Run local installer + if invoke_local_installer "$repo_dir"; then + success=true + echo "" + write_color "✓ Remote installation completed successfully!" "$COLOR_SUCCESS" + else + write_color "Installation script failed" "$COLOR_ERROR" + fi + else + write_color "Extraction failed" "$COLOR_ERROR" + fi + else + write_color "Download failed" "$COLOR_ERROR" + fi + + # Cleanup + cleanup_temp_files "$temp_dir" + + if [ "$success" = true ]; then + echo "" + write_color "Next steps:" "$COLOR_INFO" + echo "1. Review CLAUDE.md for project-specific guidelines" + echo "2. Try /workflow commands for Agent coordination" + echo "3. Use /update-memory to manage distributed documentation" + + wait_for_user "Remote installation done! Press Enter to exit..." + exit 0 + else + echo "" + wait_for_user "Installation failed! Press Enter to exit..." + exit 1 + fi +} + +# Parse command line arguments +parse_arguments "$@" + +# Run main function +main