#!/bin/bash # ============================================================================ # Claude Workflow Script - Lansare Claude automat cu monitorizare progres # ============================================================================ # Funcționalități: # - Selectare proiect din workspace # - Mod feature (worktree) vs. mod temporar (fără worktree) # - Lansare Claude cu -p (non-interactiv) și stream-json pentru progres # - Monitorizare în timp real a progresului # ============================================================================ set -e WORKSPACE="/workspace" WORKTREES_BASE="/workspace/.worktrees" LOG_DIR="/workspace/.claude-logs" # Inițializare NVM pentru Node [ -f ~/.nvm/nvm.sh ] && source ~/.nvm/nvm.sh # Culori pentru output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' NC='\033[0m' # No Color BOLD='\033[1m' # ============================================================================ # Funcții utilitare # ============================================================================ print_header() { echo -e "\n${BOLD}${BLUE}═══════════════════════════════════════════════════════════════${NC}" echo -e "${BOLD}${CYAN} $1${NC}" echo -e "${BOLD}${BLUE}═══════════════════════════════════════════════════════════════${NC}\n" } print_section() { echo -e "\n${BOLD}${MAGENTA}▸ $1${NC}\n" } print_success() { echo -e "${GREEN}✓ $1${NC}" } print_error() { echo -e "${RED}✗ $1${NC}" } print_info() { echo -e "${YELLOW}ℹ $1${NC}" } # ============================================================================ # Selectare Proiect # ============================================================================ select_project() { print_section "Proiecte disponibile" projects=() i=1 for dir in "$WORKSPACE"/*/; do if [ -d "$dir/.git" ]; then name=$(basename "$dir") projects+=("$dir") branch=$(cd "$dir" && git branch --show-current 2>/dev/null || echo "n/a") echo -e " ${BOLD}$i)${NC} $name ${CYAN}[$branch]${NC}" ((i++)) fi done if [ ${#projects[@]} -eq 0 ]; then print_error "Nu am găsit proiecte Git în $WORKSPACE" exit 1 fi echo "" read -p "Alege proiect [1-$((i-1))]: " proj_choice if [ -z "$proj_choice" ] || [ "$proj_choice" -lt 1 ] || [ "$proj_choice" -gt ${#projects[@]} ]; then print_error "Selecție invalidă" exit 1 fi PROJECT_DIR="${projects[$((proj_choice-1))]}" PROJECT_NAME=$(basename "$PROJECT_DIR") print_success "Proiect selectat: $PROJECT_NAME" } # ============================================================================ # Selectare Mod de Lucru # ============================================================================ select_work_mode() { print_section "Mod de lucru" echo -e " ${BOLD}1)${NC} ${GREEN}Feature nou${NC} ${CYAN}(worktree separat)${NC}" echo -e " └─ Creează branch + worktree izolat pentru dezvoltare" echo "" echo -e " ${BOLD}2)${NC} ${YELLOW}Task temporar${NC} ${CYAN}(fără worktree)${NC}" echo -e " └─ Documente, analiză, rezultate temporare" echo "" echo -e " ${BOLD}3)${NC} ${BLUE}Mod interactiv${NC} ${CYAN}(claude normal)${NC}" echo -e " └─ Pornește Claude interactiv pe branch-ul curent" echo "" echo -e " ${BOLD}4)${NC} ${MAGENTA}Gestionare worktrees${NC}" echo -e " └─ Vezi, șterge worktrees existente" echo "" read -p "Alege mod [1-4]: " mode_choice case $mode_choice in 1) WORK_MODE="feature" ;; 2) WORK_MODE="temp" ;; 3) WORK_MODE="interactive" ;; 4) WORK_MODE="manage" ;; *) print_error "Opțiune invalidă" exit 1 ;; esac } # ============================================================================ # Selectare tip feature (pentru modul feature) # ============================================================================ select_feature_type() { print_section "Tip feature" echo -e " ${BOLD}1)${NC} feature/ - Funcționalitate nouă" echo -e " ${BOLD}2)${NC} fix/ - Bug fix" echo -e " ${BOLD}3)${NC} refactor/ - Refactorizare cod" echo -e " ${BOLD}4)${NC} docs/ - Documentație" echo -e " ${BOLD}5)${NC} test/ - Teste" echo -e " ${BOLD}6)${NC} chore/ - Mentenanță" echo -e " ${BOLD}7)${NC} [custom] - Prefix personalizat" echo "" read -p "Alege tip [1-7]: " type_choice case $type_choice in 1) BRANCH_PREFIX="feature" ;; 2) BRANCH_PREFIX="fix" ;; 3) BRANCH_PREFIX="refactor" ;; 4) BRANCH_PREFIX="docs" ;; 5) BRANCH_PREFIX="test" ;; 6) BRANCH_PREFIX="chore" ;; 7) read -p "Prefix custom: " BRANCH_PREFIX ;; *) BRANCH_PREFIX="feature" ;; esac } # ============================================================================ # Obține descrierea task-ului # ============================================================================ get_task_description() { print_section "Descriere task" echo -e "${CYAN}Descrie ce vrei să facă Claude:${NC}" echo "" read -p "> " TASK_DESCRIPTION if [ -z "$TASK_DESCRIPTION" ]; then print_error "Trebuie să dai o descriere" exit 1 fi # Întreabă dacă vrea să adauge mai multe detalii echo "" read -p "Detalii adiționale (sau Enter pentru a continua): " extra if [ -n "$extra" ]; then TASK_DESCRIPTION="$TASK_DESCRIPTION. $extra" fi } # ============================================================================ # Creează worktree pentru feature # ============================================================================ create_worktree() { local branch_name="$1" local worktree_path="$WORKTREES_BASE/$PROJECT_NAME/$branch_name" mkdir -p "$WORKTREES_BASE/$PROJECT_NAME" cd "$PROJECT_DIR" # Actualizează main/master DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo "main") print_info "Actualizez $DEFAULT_BRANCH..." git fetch origin "$DEFAULT_BRANCH" 2>/dev/null || true # Creează worktree print_info "Creez worktree: $worktree_path" if [ -d "$worktree_path" ]; then print_error "Worktree există deja: $worktree_path" read -p "Șterge și recreează? [y/N]: " confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then git worktree remove "$worktree_path" --force 2>/dev/null || rm -rf "$worktree_path" git branch -D "$branch_name" 2>/dev/null || true else exit 1 fi fi git worktree add -b "$branch_name" "$worktree_path" "origin/$DEFAULT_BRANCH" WORKING_DIR="$worktree_path" print_success "Worktree creat: $worktree_path" } # ============================================================================ # Rulează Claude cu monitorizare progres # ============================================================================ run_claude_with_progress() { local work_dir="$1" local prompt="$2" local log_file="$3" cd "$work_dir" print_section "Lansare Claude" echo -e "${CYAN}Director:${NC} $work_dir" echo -e "${CYAN}Log:${NC} $log_file" echo -e "${CYAN}Prompt:${NC} $prompt" echo "" # Pregătește log directory mkdir -p "$LOG_DIR" local start_time=$(date +%s) # Header pentru progress echo -e "${BOLD}${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}${BLUE}║${NC} ${CYAN}Claude Code - Execuție în curs${NC} ${BOLD}${BLUE}║${NC}" echo -e "${BOLD}${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}" echo "" # Salvează prompt-ul într-un fișier temporar pentru a evita probleme cu escape local prompt_file=$(mktemp) echo "$prompt" > "$prompt_file" # Rulează Claude cu stream-json și procesează output-ul în timp real # --allowedTools pre-aprobă tool-urile necesare pentru execuție automată # --max-turns limitează iterațiile pentru siguranță claude -p "$(cat "$prompt_file")" \ --output-format stream-json \ --verbose \ --allowedTools "Bash,Read,Edit,Write,Grep,Glob,LSP" \ --max-turns 20 2>&1 | tee "$log_file" | while IFS= read -r line; do # Parsează JSON și extrage informații relevante if echo "$line" | jq -e . >/dev/null 2>&1; then # Extrage tipul mesajului msg_type=$(echo "$line" | jq -r '.type // empty' 2>/dev/null) case "$msg_type" in "assistant") # Mesaj de la Claude - extrage text content=$(echo "$line" | jq -r ' .message.content[]? | select(.type == "text") | .text // empty ' 2>/dev/null | head -c 150) if [ -n "$content" ]; then echo -e "${GREEN}◉${NC} $content" fi ;; "user") # Tool result echo -e "${CYAN} ↪${NC} Tool result received" ;; "result") # Rezultat final result_text=$(echo "$line" | jq -r '.result // empty' 2>/dev/null | head -c 200) echo "" echo -e "${GREEN}✓ REZULTAT:${NC}" echo -e "$result_text" ;; *) # Verifică pentru tool_use în content tool_name=$(echo "$line" | jq -r '.message.content[]? | select(.type == "tool_use") | .name // empty' 2>/dev/null | head -1) if [ -n "$tool_name" ]; then echo -e "${YELLOW}⚙${NC} Tool: ${BOLD}$tool_name${NC}" fi ;; esac fi done local exit_code=${PIPESTATUS[0]} local end_time=$(date +%s) local duration=$((end_time - start_time)) rm -f "$prompt_file" echo "" echo -e "${BOLD}${BLUE}════════════════════════════════════════════════════════════════${NC}" if [ $exit_code -eq 0 ]; then print_success "Claude a terminat în ${duration}s" else print_error "Claude a terminat cu eroare (cod: $exit_code) în ${duration}s" fi echo -e "${CYAN}Log salvat:${NC} $log_file" echo -e "${BOLD}${BLUE}════════════════════════════════════════════════════════════════${NC}" return $exit_code } # ============================================================================ # Gestionare worktrees # ============================================================================ manage_worktrees() { print_section "Worktrees existente pentru $PROJECT_NAME" cd "$PROJECT_DIR" echo -e "${CYAN}Worktrees:${NC}" git worktree list echo "" echo -e " ${BOLD}1)${NC} Șterge un worktree" echo -e " ${BOLD}2)${NC} Navighează la un worktree" echo -e " ${BOLD}3)${NC} Înapoi" echo "" read -p "Alege [1-3]: " manage_choice case $manage_choice in 1) read -p "Path worktree de șters: " wt_path if [ -n "$wt_path" ]; then git worktree remove "$wt_path" --force print_success "Worktree șters" fi ;; 2) read -p "Path worktree: " wt_path if [ -d "$wt_path" ]; then cd "$wt_path" print_success "Navigat la $wt_path" exec bash fi ;; 3) return ;; esac } # ============================================================================ # Main # ============================================================================ main() { print_header "Claude Workflow Manager" # 1. Selectare proiect select_project # 2. Selectare mod de lucru select_work_mode case $WORK_MODE in "feature") # Mod feature cu worktree select_feature_type echo "" read -p "Nume scurt feature (ex: add-login, fix-auth): " feature_name if [ -z "$feature_name" ]; then print_error "Trebuie să dai un nume pentru feature" exit 1 fi BRANCH_NAME="${BRANCH_PREFIX}/${feature_name}" get_task_description # Creează worktree create_worktree "$BRANCH_NAME" # Generează log file LOG_FILE="$LOG_DIR/${PROJECT_NAME}_${feature_name}_$(date +%Y%m%d_%H%M%S).log" # Rulează Claude run_claude_with_progress "$WORKING_DIR" "$TASK_DESCRIPTION" "$LOG_FILE" echo "" echo -e "${CYAN}Pentru a continua manual:${NC}" echo -e " cd $WORKING_DIR" echo -e " claude" ;; "temp") # Mod temporar fără worktree get_task_description # Folosește directorul proiectului direct WORKING_DIR="$PROJECT_DIR" # Generează log file LOG_FILE="$LOG_DIR/${PROJECT_NAME}_temp_$(date +%Y%m%d_%H%M%S).log" # Rulează Claude run_claude_with_progress "$WORKING_DIR" "$TASK_DESCRIPTION" "$LOG_FILE" ;; "interactive") # Mod interactiv normal cd "$PROJECT_DIR" print_info "Pornesc Claude interactiv în $PROJECT_NAME..." exec claude ;; "manage") # Gestionare worktrees manage_worktrees ;; esac } # Rulează main main "$@"