mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
feat: Enhanced installer with ASCII art banner and arrow key navigation
Major improvements: - Add colorful ASCII art banner (CLAUDE/CODE/WORKFLOW in Cyan/Green/Yellow) - Implement arrow key navigation (↑/↓) for installation mode selection - Add new Path installation mode (hybrid: local agents/commands/output-styles + global workflows/scripts) - Fix parameter type conversion error for $success variable - Improve console capability detection with graceful fallback to numbered menu - Use single-quoted strings to properly escape $ symbols in ASCII art Technical enhancements: - New Get-UserChoiceWithArrows function with keyboard input handling - New Install-Path function for hybrid installation - Enhanced Show-Banner with three-section colored ASCII art - Better error handling and stack trace output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -48,15 +48,17 @@
|
||||
#>
|
||||
|
||||
param(
|
||||
[ValidateSet("Global")]
|
||||
[string]$InstallMode = "Global",
|
||||
|
||||
[ValidateSet("Global", "Path")]
|
||||
[string]$InstallMode = "",
|
||||
|
||||
[string]$TargetPath = "",
|
||||
|
||||
[switch]$Force,
|
||||
|
||||
|
||||
[switch]$NonInteractive,
|
||||
|
||||
|
||||
[switch]$BackupAll,
|
||||
|
||||
|
||||
[switch]$NoBackup
|
||||
)
|
||||
|
||||
@@ -95,13 +97,54 @@ function Write-ColorOutput {
|
||||
Write-Host $Message -ForegroundColor $Color
|
||||
}
|
||||
|
||||
function Show-Banner {
|
||||
Write-Host ""
|
||||
# CLAUDE - Cyan color
|
||||
Write-Host ' ______ __ __ ' -ForegroundColor Cyan
|
||||
Write-Host ' / \ | \ | \ ' -ForegroundColor Cyan
|
||||
Write-Host '| $$$$$$\| $$ ______ __ __ ____| $$ ______ ' -ForegroundColor Cyan
|
||||
Write-Host '| $$ \$$| $$ | \ | \ | \ / $$ / \ ' -ForegroundColor Cyan
|
||||
Write-Host '| $$ | $$ \$$$$$$\| $$ | $$| $$$$$$$| $$$$$$\ ' -ForegroundColor Cyan
|
||||
Write-Host '| $$ __ | $$ / $$| $$ | $$| $$ | $$| $$ $$ ' -ForegroundColor Cyan
|
||||
Write-Host '| $$__/ \| $$| $$$$$$$| $$__/ $$| $$__| $$| $$$$$$$$ ' -ForegroundColor Cyan
|
||||
Write-Host ' \$$ $$| $$ \$$ $$ \$$ $$ \$$ $$ \$$ \ ' -ForegroundColor Cyan
|
||||
Write-Host ' \$$$$$$ \$$ \$$$$$$$ \$$$$$$ \$$$$$$$ \$$$$$$$ ' -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# CODE - Green color
|
||||
Write-Host ' ______ __ ' -ForegroundColor Green
|
||||
Write-Host '/ \ | \ ' -ForegroundColor Green
|
||||
Write-Host '| $$$$$$\ ______ ____| $$ ______ ' -ForegroundColor Green
|
||||
Write-Host '| $$ \$$ / \ / $$ / \ ' -ForegroundColor Green
|
||||
Write-Host '| $$ | $$$$$$\| $$$$$$$| $$$$$$\ ' -ForegroundColor Green
|
||||
Write-Host '| $$ __ | $$ | $$| $$ | $$| $$ $$ ' -ForegroundColor Green
|
||||
Write-Host '| $$__/ \| $$__/ $$| $$__| $$| $$$$$$$$ ' -ForegroundColor Green
|
||||
Write-Host ' \$$ $$ \$$ $$ \$$ $$ \$$ \ ' -ForegroundColor Green
|
||||
Write-Host ' \$$$$$$ \$$$$$$ \$$$$$$$ \$$$$$$$ ' -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# WORKFLOW - Yellow color
|
||||
Write-Host '__ __ __ ______ __ ' -ForegroundColor Yellow
|
||||
Write-Host '| \ _ | \ | \ / \ | \ ' -ForegroundColor Yellow
|
||||
Write-Host '| $$ / \ | $$ ______ ______ | $$ __ | $$$$$$\| $$ ______ __ __ __ ' -ForegroundColor Yellow
|
||||
Write-Host '| $$/ $\| $$ / \ / \ | $$ / \| $$_ \$$| $$ / \ | \ | \ | \' -ForegroundColor Yellow
|
||||
Write-Host '| $$ $$$\ $$| $$$$$$\| $$$$$$\| $$_/ $$| $$ \ | $$| $$$$$$\| $$ | $$ | $$' -ForegroundColor Yellow
|
||||
Write-Host '| $$ $$\$$\$$| $$ | $$| $$ \$$| $$ $$ | $$$$ | $$| $$ | $$| $$ | $$ | $$' -ForegroundColor Yellow
|
||||
Write-Host '| $$$$ \$$$$| $$__/ $$| $$ | $$$$$$\ | $$ | $$| $$__/ $$| $$_/ $$_/ $$' -ForegroundColor Yellow
|
||||
Write-Host '| $$$ \$$$ \$$ $$| $$ | $$ \$$\| $$ | $$ \$$ $$ \$$ $$ $$' -ForegroundColor Yellow
|
||||
Write-Host ' \$$ \$$ \$$$$$$ \$$ \$$ \$$ \$$ \$$ \$$$$$$ \$$$$$\$$$$' -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
function Show-Header {
|
||||
Write-ColorOutput "==== $ScriptName v$Version ====" $ColorInfo
|
||||
Write-ColorOutput "========================================================" $ColorInfo
|
||||
Show-Banner
|
||||
Write-ColorOutput " $ScriptName v$Version" $ColorInfo
|
||||
Write-ColorOutput " Unified workflow system with comprehensive coordination" $ColorInfo
|
||||
Write-ColorOutput "========================================================================" $ColorInfo
|
||||
if ($NoBackup) {
|
||||
Write-ColorOutput "WARNING: Backup disabled - existing files will be overwritten without backup!" $ColorWarning
|
||||
Write-ColorOutput "WARNING: Backup disabled - existing files will be overwritten!" $ColorWarning
|
||||
} else {
|
||||
Write-ColorOutput "Auto-backup enabled - existing files will be backed up before replacement" $ColorSuccess
|
||||
Write-ColorOutput "Auto-backup enabled - existing files will be backed up" $ColorSuccess
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
@@ -133,18 +176,130 @@ function Test-Prerequisites {
|
||||
return $true
|
||||
}
|
||||
|
||||
function Get-UserChoiceWithArrows {
|
||||
param(
|
||||
[string]$Prompt,
|
||||
[string[]]$Options,
|
||||
[int]$DefaultIndex = 0
|
||||
)
|
||||
|
||||
if ($NonInteractive) {
|
||||
Write-ColorOutput "Non-interactive mode: Using default '$($Options[$DefaultIndex])'" $ColorInfo
|
||||
return $Options[$DefaultIndex]
|
||||
}
|
||||
|
||||
# Test if we can use console features (interactive terminal)
|
||||
$canUseConsole = $true
|
||||
try {
|
||||
$null = [Console]::CursorVisible
|
||||
$null = $Host.UI.RawUI.ReadKey
|
||||
}
|
||||
catch {
|
||||
$canUseConsole = $false
|
||||
}
|
||||
|
||||
# Fallback to simple numbered menu if console not available
|
||||
if (-not $canUseConsole) {
|
||||
Write-ColorOutput "Arrow navigation not available in this environment. Using numbered menu." $ColorWarning
|
||||
return Get-UserChoice -Prompt $Prompt -Options $Options -Default $Options[$DefaultIndex]
|
||||
}
|
||||
|
||||
$selectedIndex = $DefaultIndex
|
||||
$cursorVisible = $true
|
||||
|
||||
try {
|
||||
$cursorVisible = [Console]::CursorVisible
|
||||
[Console]::CursorVisible = $false
|
||||
}
|
||||
catch {
|
||||
# Silently continue if cursor control fails
|
||||
}
|
||||
|
||||
try {
|
||||
Write-Host ""
|
||||
Write-ColorOutput $Prompt $ColorPrompt
|
||||
Write-Host ""
|
||||
|
||||
while ($true) {
|
||||
# Display options
|
||||
for ($i = 0; $i -lt $Options.Count; $i++) {
|
||||
$prefix = if ($i -eq $selectedIndex) { " > " } else { " " }
|
||||
$color = if ($i -eq $selectedIndex) { $ColorSuccess } else { "White" }
|
||||
|
||||
# Clear line and write option
|
||||
Write-Host "`r$prefix$($Options[$i])".PadRight(80) -ForegroundColor $color
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " Use " -NoNewline -ForegroundColor DarkGray
|
||||
Write-Host "UP/DOWN" -NoNewline -ForegroundColor Yellow
|
||||
Write-Host " arrows to navigate, " -NoNewline -ForegroundColor DarkGray
|
||||
Write-Host "ENTER" -NoNewline -ForegroundColor Yellow
|
||||
Write-Host " to select, or type " -NoNewline -ForegroundColor DarkGray
|
||||
Write-Host "1-$($Options.Count)" -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "" -ForegroundColor DarkGray
|
||||
|
||||
# Read key
|
||||
$key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
|
||||
# Handle arrow keys
|
||||
if ($key.VirtualKeyCode -eq 38) {
|
||||
# Up arrow
|
||||
$selectedIndex = if ($selectedIndex -gt 0) { $selectedIndex - 1 } else { $Options.Count - 1 }
|
||||
}
|
||||
elseif ($key.VirtualKeyCode -eq 40) {
|
||||
# Down arrow
|
||||
$selectedIndex = if ($selectedIndex -lt ($Options.Count - 1)) { $selectedIndex + 1 } else { 0 }
|
||||
}
|
||||
elseif ($key.VirtualKeyCode -eq 13) {
|
||||
# Enter key
|
||||
Write-Host ""
|
||||
return $Options[$selectedIndex]
|
||||
}
|
||||
elseif ($key.Character -match '^\d$') {
|
||||
# Number key
|
||||
$num = [int]::Parse($key.Character)
|
||||
if ($num -ge 1 -and $num -le $Options.Count) {
|
||||
Write-Host ""
|
||||
return $Options[$num - 1]
|
||||
}
|
||||
}
|
||||
|
||||
# Move cursor back up to redraw menu
|
||||
$linesToMove = $Options.Count + 2
|
||||
try {
|
||||
for ($i = 0; $i -lt $linesToMove; $i++) {
|
||||
[Console]::SetCursorPosition(0, [Console]::CursorTop - 1)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# If cursor positioning fails, just continue
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
[Console]::CursorVisible = $cursorVisible
|
||||
}
|
||||
catch {
|
||||
# Silently continue if cursor control fails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-UserChoice {
|
||||
param(
|
||||
[string]$Prompt,
|
||||
[string[]]$Options,
|
||||
[string]$Default = $null
|
||||
)
|
||||
|
||||
|
||||
if ($NonInteractive -and $Default) {
|
||||
Write-ColorOutput "Non-interactive mode: Using default '$Default'" $ColorInfo
|
||||
return $Default
|
||||
}
|
||||
|
||||
|
||||
Write-ColorOutput $Prompt $ColorPrompt
|
||||
for ($i = 0; $i -lt $Options.Count; $i++) {
|
||||
if ($Default -and $Options[$i] -eq $Default) {
|
||||
@@ -154,18 +309,18 @@ function Get-UserChoice {
|
||||
}
|
||||
Write-Host " $($i + 1). $($Options[$i])$marker"
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
$input = Read-Host "Please select (1-$($Options.Count))"
|
||||
if ([string]::IsNullOrWhiteSpace($input) -and $Default) {
|
||||
return $Default
|
||||
}
|
||||
|
||||
|
||||
$index = $null
|
||||
if ([int]::TryParse($input, [ref]$index) -and $index -ge 1 -and $index -le $Options.Count) {
|
||||
return $Options[$index - 1]
|
||||
}
|
||||
|
||||
|
||||
Write-ColorOutput "Invalid selection. Please enter a number between 1 and $($Options.Count)" $ColorWarning
|
||||
} while ($true)
|
||||
}
|
||||
@@ -457,19 +612,19 @@ function Merge-DirectoryContents {
|
||||
|
||||
function Install-Global {
|
||||
Write-ColorOutput "Installing Claude Code Workflow System globally..." $ColorInfo
|
||||
|
||||
|
||||
# Determine user profile directory
|
||||
$userProfile = [Environment]::GetFolderPath("UserProfile")
|
||||
$globalClaudeDir = Join-Path $userProfile ".claude"
|
||||
$globalClaudeMd = Join-Path $globalClaudeDir "CLAUDE.md"
|
||||
|
||||
|
||||
Write-ColorOutput "Global installation path: $userProfile" $ColorInfo
|
||||
|
||||
|
||||
# Source paths
|
||||
$sourceDir = $PSScriptRoot
|
||||
$sourceClaudeDir = Join-Path $sourceDir ".claude"
|
||||
$sourceClaudeMd = Join-Path $sourceDir "CLAUDE.md"
|
||||
|
||||
|
||||
# Create backup folder if needed (default behavior unless NoBackup is specified)
|
||||
$backupFolder = $null
|
||||
if (-not $NoBackup) {
|
||||
@@ -485,15 +640,15 @@ function Install-Global {
|
||||
Write-ColorOutput "Backup folder created: $backupFolder" $ColorInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Merge .claude directory contents (don't replace entire directory)
|
||||
Write-ColorOutput "Merging .claude directory contents..." $ColorInfo
|
||||
$claudeMerged = Merge-DirectoryContents -Source $sourceClaudeDir -Destination $globalClaudeDir -Description ".claude directory contents" -BackupFolder $backupFolder
|
||||
|
||||
|
||||
# Handle CLAUDE.md file in .claude directory
|
||||
Write-ColorOutput "Installing CLAUDE.md to global .claude directory..." $ColorInfo
|
||||
$claudeMdInstalled = Copy-FileToDestination -Source $sourceClaudeMd -Destination $globalClaudeMd -Description "CLAUDE.md" -BackupFolder $backupFolder
|
||||
|
||||
|
||||
if ($backupFolder -and (Test-Path $backupFolder)) {
|
||||
$backupFiles = Get-ChildItem $backupFolder -Recurse -File -ErrorAction SilentlyContinue
|
||||
if (-not $backupFiles -or ($backupFiles | Measure-Object).Count -eq 0) {
|
||||
@@ -502,16 +657,207 @@ function Install-Global {
|
||||
Write-ColorOutput "Removed empty backup folder" $ColorInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $true
|
||||
}
|
||||
|
||||
function Install-Path {
|
||||
param(
|
||||
[string]$TargetDirectory
|
||||
)
|
||||
|
||||
Write-ColorOutput "Installing Claude Code Workflow System in hybrid mode..." $ColorInfo
|
||||
Write-ColorOutput "Local path: $TargetDirectory" $ColorInfo
|
||||
|
||||
# Determine user profile directory for global files
|
||||
$userProfile = [Environment]::GetFolderPath("UserProfile")
|
||||
$globalClaudeDir = Join-Path $userProfile ".claude"
|
||||
|
||||
Write-ColorOutput "Global path: $userProfile" $ColorInfo
|
||||
|
||||
# Source paths
|
||||
$sourceDir = $PSScriptRoot
|
||||
$sourceClaudeDir = Join-Path $sourceDir ".claude"
|
||||
$sourceClaudeMd = Join-Path $sourceDir "CLAUDE.md"
|
||||
|
||||
# Local paths - only for agents, commands, output-styles
|
||||
$localClaudeDir = Join-Path $TargetDirectory ".claude"
|
||||
|
||||
# Create backup folder if needed
|
||||
$backupFolder = $null
|
||||
if (-not $NoBackup) {
|
||||
if ((Test-Path $localClaudeDir) -or (Test-Path $globalClaudeDir)) {
|
||||
$backupFolder = Get-BackupDirectory -TargetDirectory $TargetDirectory
|
||||
Write-ColorOutput "Backup folder created: $backupFolder" $ColorInfo
|
||||
}
|
||||
}
|
||||
|
||||
# Create local .claude directory
|
||||
if (-not (Test-Path $localClaudeDir)) {
|
||||
New-Item -ItemType Directory -Path $localClaudeDir -Force | Out-Null
|
||||
Write-ColorOutput "Created local .claude directory" $ColorSuccess
|
||||
}
|
||||
|
||||
# Local folders to install (agents, commands, output-styles)
|
||||
$localFolders = @("agents", "commands", "output-styles")
|
||||
|
||||
Write-ColorOutput "Installing local components (agents, commands, output-styles)..." $ColorInfo
|
||||
foreach ($folder in $localFolders) {
|
||||
$sourceFolderPath = Join-Path $sourceClaudeDir $folder
|
||||
$destFolderPath = Join-Path $localClaudeDir $folder
|
||||
|
||||
if (Test-Path $sourceFolderPath) {
|
||||
if (Test-Path $destFolderPath) {
|
||||
if ($backupFolder) {
|
||||
Backup-DirectoryToFolder -DirectoryPath $destFolderPath -BackupFolder $backupFolder
|
||||
}
|
||||
}
|
||||
|
||||
Copy-DirectoryRecursive -Source $sourceFolderPath -Destination $destFolderPath
|
||||
Write-ColorOutput "Installed local folder: $folder" $ColorSuccess
|
||||
} else {
|
||||
Write-ColorOutput "WARNING: Source folder not found: $folder" $ColorWarning
|
||||
}
|
||||
}
|
||||
|
||||
# Global components - exclude local folders
|
||||
Write-ColorOutput "Installing global components to $globalClaudeDir..." $ColorInfo
|
||||
|
||||
# Get all items from source, excluding local folders
|
||||
$sourceItems = Get-ChildItem -Path $sourceClaudeDir -Recurse -File | Where-Object {
|
||||
$relativePath = $_.FullName.Substring($sourceClaudeDir.Length + 1)
|
||||
$topFolder = $relativePath.Split([System.IO.Path]::DirectorySeparatorChar)[0]
|
||||
$topFolder -notin $localFolders
|
||||
}
|
||||
|
||||
$mergedCount = 0
|
||||
foreach ($item in $sourceItems) {
|
||||
$relativePath = $item.FullName.Substring($sourceClaudeDir.Length + 1)
|
||||
$destinationPath = Join-Path $globalClaudeDir $relativePath
|
||||
|
||||
# Ensure destination directory exists
|
||||
$destinationDir = Split-Path $destinationPath -Parent
|
||||
if (-not (Test-Path $destinationDir)) {
|
||||
New-Item -ItemType Directory -Path $destinationDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Handle file merging
|
||||
if (Test-Path $destinationPath) {
|
||||
if ($BackupAll -and -not $NoBackup) {
|
||||
if ($backupFolder) {
|
||||
Backup-FileToFolder -FilePath $destinationPath -BackupFolder $backupFolder
|
||||
}
|
||||
Copy-Item -Path $item.FullName -Destination $destinationPath -Force
|
||||
$mergedCount++
|
||||
} elseif ($NoBackup) {
|
||||
if (Confirm-Action "File '$relativePath' already exists in global location. Replace it? (NO BACKUP)" -DefaultYes:$false) {
|
||||
Copy-Item -Path $item.FullName -Destination $destinationPath -Force
|
||||
$mergedCount++
|
||||
}
|
||||
} elseif (Confirm-Action "File '$relativePath' already exists in global location. Replace it?" -DefaultYes:$false) {
|
||||
if ($backupFolder) {
|
||||
Backup-FileToFolder -FilePath $destinationPath -BackupFolder $backupFolder
|
||||
}
|
||||
Copy-Item -Path $item.FullName -Destination $destinationPath -Force
|
||||
$mergedCount++
|
||||
}
|
||||
} else {
|
||||
Copy-Item -Path $item.FullName -Destination $destinationPath -Force
|
||||
$mergedCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-ColorOutput "Merged $mergedCount files to global location" $ColorSuccess
|
||||
|
||||
# Handle CLAUDE.md file in global .claude directory
|
||||
$globalClaudeMd = Join-Path $globalClaudeDir "CLAUDE.md"
|
||||
Write-ColorOutput "Installing CLAUDE.md to global .claude directory..." $ColorInfo
|
||||
Copy-FileToDestination -Source $sourceClaudeMd -Destination $globalClaudeMd -Description "CLAUDE.md" -BackupFolder $backupFolder
|
||||
|
||||
if ($backupFolder -and (Test-Path $backupFolder)) {
|
||||
$backupFiles = Get-ChildItem $backupFolder -Recurse -File -ErrorAction SilentlyContinue
|
||||
if (-not $backupFiles -or ($backupFiles | Measure-Object).Count -eq 0) {
|
||||
Remove-Item -Path $backupFolder -Force
|
||||
Write-ColorOutput "Removed empty backup folder" $ColorInfo
|
||||
}
|
||||
}
|
||||
|
||||
return $true
|
||||
}
|
||||
|
||||
|
||||
function Get-InstallationMode {
|
||||
Write-ColorOutput "Installation mode: Global (installing to user profile ~/.claude/)" $ColorInfo
|
||||
if ($InstallMode) {
|
||||
Write-ColorOutput "Installation mode: $InstallMode" $ColorInfo
|
||||
return $InstallMode
|
||||
}
|
||||
|
||||
$modes = @(
|
||||
"Global - Install to user profile (~/.claude/)",
|
||||
"Path - Install to custom directory (partial local + global)"
|
||||
)
|
||||
|
||||
Write-Host ""
|
||||
$selection = Get-UserChoiceWithArrows -Prompt "Choose installation mode:" -Options $modes -DefaultIndex 0
|
||||
|
||||
if ($selection -like "Global*") {
|
||||
return "Global"
|
||||
} elseif ($selection -like "Path*") {
|
||||
return "Path"
|
||||
}
|
||||
|
||||
return "Global"
|
||||
}
|
||||
|
||||
function Get-InstallationPath {
|
||||
param(
|
||||
[string]$Mode
|
||||
)
|
||||
|
||||
if ($Mode -eq "Global") {
|
||||
return [Environment]::GetFolderPath("UserProfile")
|
||||
}
|
||||
|
||||
if ($TargetPath) {
|
||||
if (Test-Path $TargetPath) {
|
||||
return $TargetPath
|
||||
}
|
||||
Write-ColorOutput "WARNING: Specified target path does not exist: $TargetPath" $ColorWarning
|
||||
}
|
||||
|
||||
# Interactive path selection
|
||||
do {
|
||||
Write-Host ""
|
||||
Write-ColorOutput "Enter the target directory path for installation:" $ColorPrompt
|
||||
Write-ColorOutput "(This will install agents, commands, output-styles locally, other files globally)" $ColorInfo
|
||||
$path = Read-Host "Path"
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($path)) {
|
||||
Write-ColorOutput "Path cannot be empty" $ColorWarning
|
||||
continue
|
||||
}
|
||||
|
||||
# Expand environment variables and relative paths
|
||||
$expandedPath = [System.Environment]::ExpandEnvironmentVariables($path)
|
||||
$expandedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($expandedPath)
|
||||
|
||||
if (Test-Path $expandedPath) {
|
||||
return $expandedPath
|
||||
}
|
||||
|
||||
Write-ColorOutput "Path does not exist: $expandedPath" $ColorWarning
|
||||
if (Confirm-Action "Create this directory?" -DefaultYes) {
|
||||
try {
|
||||
New-Item -ItemType Directory -Path $expandedPath -Force | Out-Null
|
||||
Write-ColorOutput "Directory created successfully" $ColorSuccess
|
||||
return $expandedPath
|
||||
} catch {
|
||||
Write-ColorOutput "Failed to create directory: $($_.Exception.Message)" $ColorError
|
||||
}
|
||||
}
|
||||
} while ($true)
|
||||
}
|
||||
|
||||
|
||||
function Show-Summary {
|
||||
param(
|
||||
@@ -519,17 +865,26 @@ function Show-Summary {
|
||||
[string]$Path,
|
||||
[bool]$Success
|
||||
)
|
||||
|
||||
|
||||
Write-Host ""
|
||||
if ($Success) {
|
||||
Write-ColorOutput "Installation completed successfully!" $ColorSuccess
|
||||
} else {
|
||||
Write-ColorOutput "Installation completed with warnings" $ColorWarning
|
||||
}
|
||||
|
||||
|
||||
Write-ColorOutput "Installation Details:" $ColorInfo
|
||||
Write-Host " Mode: $Mode"
|
||||
Write-Host " Path: $Path"
|
||||
|
||||
if ($Mode -eq "Path") {
|
||||
Write-Host " Local Path: $Path"
|
||||
Write-Host " Global Path: $([Environment]::GetFolderPath('UserProfile'))"
|
||||
Write-Host " Local Components: agents, commands, output-styles"
|
||||
Write-Host " Global Components: workflows, scripts, python_script, etc."
|
||||
} else {
|
||||
Write-Host " Path: $Path"
|
||||
}
|
||||
|
||||
if ($NoBackup) {
|
||||
Write-Host " Backup: Disabled (no backup created)"
|
||||
} elseif ($BackupAll) {
|
||||
@@ -537,7 +892,7 @@ function Show-Summary {
|
||||
} else {
|
||||
Write-Host " Backup: Enabled (default behavior)"
|
||||
}
|
||||
|
||||
|
||||
Write-Host ""
|
||||
Write-ColorOutput "Next steps:" $ColorInfo
|
||||
Write-Host "1. Review CLAUDE.md - Customize guidelines for your project"
|
||||
@@ -545,7 +900,7 @@ function Show-Summary {
|
||||
Write-Host "3. Start using Claude Code with Agent workflow coordination!"
|
||||
Write-Host "4. Use /workflow commands for task execution"
|
||||
Write-Host "5. Use /update-memory commands for memory system management"
|
||||
|
||||
|
||||
Write-Host ""
|
||||
Write-ColorOutput "Documentation: https://github.com/catlog22/Claude-CCW" $ColorInfo
|
||||
Write-ColorOutput "Features: Unified workflow system with comprehensive file output generation" $ColorInfo
|
||||
@@ -553,48 +908,57 @@ function Show-Summary {
|
||||
|
||||
function Main {
|
||||
Show-Header
|
||||
|
||||
|
||||
# Test prerequisites
|
||||
Write-ColorOutput "Checking system requirements..." $ColorInfo
|
||||
if (-not (Test-Prerequisites)) {
|
||||
Write-ColorOutput "Prerequisites check failed!" $ColorError
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
# Get installation mode
|
||||
$mode = Get-InstallationMode
|
||||
$installPath = ""
|
||||
$success = $false
|
||||
|
||||
$installPath = [Environment]::GetFolderPath("UserProfile")
|
||||
$success = Install-Global
|
||||
|
||||
Show-Summary -Mode $mode -Path $installPath -Success $success
|
||||
|
||||
|
||||
if ($mode -eq "Global") {
|
||||
$installPath = [Environment]::GetFolderPath("UserProfile")
|
||||
$result = Install-Global
|
||||
$success = $result -eq $true
|
||||
}
|
||||
elseif ($mode -eq "Path") {
|
||||
$installPath = Get-InstallationPath -Mode $mode
|
||||
$result = Install-Path -TargetDirectory $installPath
|
||||
$success = $result -eq $true
|
||||
}
|
||||
|
||||
Show-Summary -Mode $mode -Path $installPath -Success ([bool]$success)
|
||||
|
||||
# Wait for user confirmation before exit in interactive mode
|
||||
if (-not $NonInteractive) {
|
||||
Write-Host ""
|
||||
Write-ColorOutput "Installation completed. Press any key to exit..." $ColorPrompt
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
}
|
||||
|
||||
|
||||
if ($success) {
|
||||
return 0
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
} catch {
|
||||
Write-ColorOutput "CRITICAL ERROR: $($_.Exception.Message)" $ColorError
|
||||
|
||||
Write-ColorOutput "Stack trace: $($_.ScriptStackTrace)" $ColorError
|
||||
|
||||
# Wait for user confirmation before exit in interactive mode
|
||||
if (-not $NonInteractive) {
|
||||
Write-Host ""
|
||||
Write-ColorOutput "An error occurred. Press any key to exit..." $ColorPrompt
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
}
|
||||
|
||||
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user