mirror of
https://github.com/harivansh-afk/claude-code-vertical.git
synced 2026-04-15 08:03:42 +00:00
227 lines
5.8 KiB
Bash
Executable file
227 lines
5.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Claude Code Vertical - Install Script
|
|
#
|
|
# Installs skills and slash commands to your project's .claude directory
|
|
# Uses symlinks so updates to the source are automatically reflected
|
|
#
|
|
# Usage:
|
|
# ./install.sh # Install to current directory
|
|
# ./install.sh /path/to/dir # Install to specified directory
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors (disable if not a terminal)
|
|
if [[ -t 1 ]]; then
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
else
|
|
RED='' GREEN='' YELLOW='' BLUE='' BOLD='' NC=''
|
|
fi
|
|
|
|
# Get the directory where this script lives (source of truth)
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Target directory - default to current directory
|
|
TARGET_DIR="${1:-.}"
|
|
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
|
|
|
|
# What we're installing
|
|
COMPONENTS=(
|
|
"commands:commands"
|
|
"skills:skills"
|
|
"skill-index:skill-index"
|
|
"lib:lib"
|
|
)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Functions
|
|
# ------------------------------------------------------------------------------
|
|
|
|
log_info() {
|
|
printf "${BLUE}[info]${NC} %s\n" "$1"
|
|
}
|
|
|
|
log_success() {
|
|
printf "${GREEN}[ok]${NC} %s\n" "$1"
|
|
}
|
|
|
|
log_warn() {
|
|
printf "${YELLOW}[warn]${NC} %s\n" "$1"
|
|
}
|
|
|
|
log_error() {
|
|
printf "${RED}[error]${NC} %s\n" "$1"
|
|
}
|
|
|
|
log_header() {
|
|
printf "\n${BOLD}%s${NC}\n" "$1"
|
|
printf "%s\n" "$(printf '=%.0s' $(seq 1 ${#1}))"
|
|
}
|
|
|
|
check_prerequisites() {
|
|
log_header "Checking prerequisites"
|
|
|
|
# Check if source directories exist
|
|
for component in "${COMPONENTS[@]}"; do
|
|
local src="${component%%:*}"
|
|
if [[ ! -d "$SCRIPT_DIR/$src" ]]; then
|
|
log_error "Source directory not found: $SCRIPT_DIR/$src"
|
|
exit 1
|
|
fi
|
|
done
|
|
log_success "All source directories found"
|
|
|
|
# Check if target is a git repo (optional warning)
|
|
if [[ ! -d "$TARGET_DIR/.git" ]]; then
|
|
log_warn "Target is not a git repository: $TARGET_DIR"
|
|
log_info "Continuing anyway - this is not required"
|
|
else
|
|
log_success "Target is a git repository"
|
|
fi
|
|
|
|
# Check for tmux
|
|
if command -v tmux &> /dev/null; then
|
|
log_success "tmux is installed ($(tmux -V))"
|
|
else
|
|
log_warn "tmux is not installed - install with: brew install tmux"
|
|
fi
|
|
}
|
|
|
|
create_directories() {
|
|
log_header "Creating directories"
|
|
|
|
local claude_dir="$TARGET_DIR/.claude"
|
|
|
|
if [[ -d "$claude_dir" ]]; then
|
|
log_info ".claude directory already exists"
|
|
else
|
|
mkdir -p "$claude_dir"
|
|
log_success "Created $claude_dir"
|
|
fi
|
|
|
|
# Create vertical plans directory
|
|
mkdir -p "$claude_dir/vertical/plans"
|
|
log_success "Created $claude_dir/vertical/plans"
|
|
}
|
|
|
|
install_component() {
|
|
local src_name="$1"
|
|
local dest_name="$2"
|
|
local src_path="$SCRIPT_DIR/$src_name"
|
|
local dest_path="$TARGET_DIR/.claude/$dest_name"
|
|
|
|
# Remove existing symlink or directory
|
|
if [[ -L "$dest_path" ]]; then
|
|
rm "$dest_path"
|
|
log_info "Removed existing symlink: $dest_path"
|
|
elif [[ -d "$dest_path" ]]; then
|
|
log_warn "Directory exists (not a symlink): $dest_path"
|
|
printf " Replace with symlink? [y/N] "
|
|
read -r response
|
|
if [[ "$response" =~ ^[Yy]$ ]]; then
|
|
rm -rf "$dest_path"
|
|
log_info "Removed existing directory"
|
|
else
|
|
log_warn "Skipping $dest_name"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Create symlink
|
|
ln -s "$src_path" "$dest_path"
|
|
log_success "Linked $dest_name -> $src_path"
|
|
}
|
|
|
|
install_components() {
|
|
log_header "Installing components"
|
|
|
|
for component in "${COMPONENTS[@]}"; do
|
|
local src="${component%%:*}"
|
|
local dest="${component##*:}"
|
|
install_component "$src" "$dest"
|
|
done
|
|
}
|
|
|
|
verify_installation() {
|
|
log_header "Verifying installation"
|
|
|
|
local claude_dir="$TARGET_DIR/.claude"
|
|
local all_ok=true
|
|
|
|
for component in "${COMPONENTS[@]}"; do
|
|
local dest="${component##*:}"
|
|
local dest_path="$claude_dir/$dest"
|
|
|
|
if [[ -L "$dest_path" && -d "$dest_path" ]]; then
|
|
local count=$(find -L "$dest_path" -type f | wc -l | tr -d ' ')
|
|
log_success "$dest: $count files"
|
|
else
|
|
log_error "$dest: not found or broken symlink"
|
|
all_ok=false
|
|
fi
|
|
done
|
|
|
|
if $all_ok; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
print_summary() {
|
|
log_header "Installation complete"
|
|
|
|
printf "\n${BOLD}Installed to:${NC} %s/.claude/\n" "$TARGET_DIR"
|
|
printf "\n${BOLD}Available commands:${NC}\n"
|
|
printf " /plan Start interactive planning session\n"
|
|
printf " /build <id> Execute a plan with parallel weavers\n"
|
|
printf " /status [id] Check plan and weaver status\n"
|
|
|
|
printf "\n${BOLD}Quick start:${NC}\n"
|
|
printf " cd %s\n" "$TARGET_DIR"
|
|
printf " claude\n"
|
|
printf " > /plan\n"
|
|
|
|
printf "\n${BOLD}Tmux helpers:${NC}\n"
|
|
printf " source %s/.claude/lib/tmux.sh\n" "$TARGET_DIR"
|
|
printf " vertical_status\n"
|
|
|
|
printf "\n"
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Main
|
|
# ------------------------------------------------------------------------------
|
|
|
|
main() {
|
|
printf "${BOLD}Claude Code Vertical Installer${NC}\n"
|
|
printf "Source: %s\n" "$SCRIPT_DIR"
|
|
printf "Target: %s\n" "$TARGET_DIR"
|
|
|
|
# Don't install to self
|
|
if [[ "$SCRIPT_DIR" == "$TARGET_DIR" ]]; then
|
|
log_error "Cannot install to source directory"
|
|
log_info "Run from your project directory or specify a target:"
|
|
printf " %s/install.sh /path/to/your/project\n" "$SCRIPT_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
check_prerequisites
|
|
create_directories
|
|
install_components
|
|
|
|
if verify_installation; then
|
|
print_summary
|
|
else
|
|
log_error "Installation completed with errors"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main "$@"
|