claude-git-hooks 1.5.1 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-git-hooks",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "description": "Git hooks con Claude CLI para análisis de código y generación automática de mensajes de commit",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -1,23 +1,23 @@
1
1
  #!/bin/bash
2
2
 
3
- # Git Pre-commit Hook para evaluación de código con Claude CLI
3
+ # Git Pre-commit Hook for code evaluation with Claude CLI
4
4
  # Archivo: .git/hooks/pre-commit
5
5
 
6
6
  set -e
7
7
 
8
- # Configuración
8
+ # Configuration
9
9
  CLAUDE_CLI="claude"
10
10
  TEMP_DIR="/tmp/code-review-$$"
11
- MAX_FILE_SIZE=100000 # 100KB máximo por archivo
11
+ MAX_FILE_SIZE=100000 # 100KB maximum per file
12
12
 
13
- # Colores para output
13
+ # Colors for output
14
14
  RED='\033[0;31m'
15
15
  GREEN='\033[0;32m'
16
16
  YELLOW='\033[1;33m'
17
17
  BLUE='\033[0;34m'
18
18
  NC='\033[0m' # No Color
19
19
 
20
- # Función para logging
20
+ # Function for logging
21
21
  log() {
22
22
  echo -e "${GREEN}[PRE-COMMIT]${NC} $1"
23
23
  }
@@ -30,10 +30,10 @@ warning() {
30
30
  echo -e "${YELLOW}[WARNING]${NC} $1"
31
31
  }
32
32
 
33
- # Verificar versión al inicio (antes de cualquier análisis)
34
- # Intentar encontrar el script check-version.sh
33
+ # Check version at start (before any analysis)
34
+ # Try to find the check-version.sh script
35
35
  CHECK_VERSION_SCRIPT=""
36
- # Buscar en múltiples ubicaciones posibles
36
+ # Search in multiple possible locations
37
37
  SCRIPT_PATHS=(
38
38
  "$(dirname "$0")/check-version.sh"
39
39
  "/usr/local/lib/node_modules/claude-git-hooks/templates/check-version.sh"
@@ -49,37 +49,37 @@ for path in "${SCRIPT_PATHS[@]}"; do
49
49
  fi
50
50
  done
51
51
 
52
- # Si encontramos el script, ejecutarlo
52
+ # If we find the script, execute it
53
53
  if [ -n "$CHECK_VERSION_SCRIPT" ]; then
54
- # Source el script para tener acceso a la función
54
+ # Source the script to have access to the function
55
55
  source "$CHECK_VERSION_SCRIPT"
56
56
  check_version
57
57
  fi
58
58
 
59
- # Función para generar prompt de resolución AI-friendly
59
+ # Function to generate AI-friendly resolution prompt
60
60
  generate_resolution_prompt() {
61
61
  local RESOLUTION_FILE="./claude_resolution_prompt.md"
62
62
  local RESOLUTION_TEMPLATE=".claude/CLAUDE_RESOLUTION_PROMPT.md"
63
63
 
64
64
  if [ ! -f "$RESOLUTION_TEMPLATE" ]; then
65
- warning "No se encontró template de resolución: $RESOLUTION_TEMPLATE"
65
+ warning "Resolution template not found: $RESOLUTION_TEMPLATE"
66
66
  return
67
67
  fi
68
68
 
69
- # Obtener información del contexto
69
+ # Get context information
70
70
  local REPO_NAME=$(basename $(git rev-parse --show-toplevel))
71
71
  local BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
72
72
  local COMMIT_SHA="pending"
73
73
  local FILE_COUNT=$(echo "$JAVA_FILES" | wc -l)
74
74
 
75
- # Formatear los blocking issues para el prompt de resolución
75
+ # Format the blocking issues for the resolution prompt
76
76
  local ISSUES_FORMATTED=""
77
77
  local issue_num=1
78
78
 
79
- # Usar un archivo temporal para acumular los issues
79
+ # Use a temporary file to accumulate the issues
80
80
  local TEMP_ISSUES=$(mktemp)
81
81
 
82
- # Parsear cada blocking issue como objeto JSON
82
+ # Parse each blocking issue as JSON object
83
83
  echo "$JSON_RESPONSE" | jq -c '.blockingIssues[]?' 2>/dev/null | while IFS= read -r issue; do
84
84
  if [ -n "$issue" ]; then
85
85
  local desc=$(echo "$issue" | jq -r '.description')
@@ -97,31 +97,31 @@ generate_resolution_prompt() {
97
97
  fi
98
98
  done
99
99
 
100
- # Leer el contenido acumulado
100
+ # Read the accumulated content
101
101
  ISSUES_FORMATTED=$(cat "$TEMP_ISSUES")
102
102
  rm -f "$TEMP_ISSUES"
103
103
 
104
- # Generar el prompt desde el template
104
+ # Generate the prompt from the template
105
105
  cp "$RESOLUTION_TEMPLATE" "$RESOLUTION_FILE"
106
106
 
107
- # Reemplazar placeholders - usar comillas dobles y escapar caracteres especiales
107
+ # Replace placeholders - use double quotes and escape special characters
108
108
  sed -i "s|{{REPO_NAME}}|${REPO_NAME}|g" "$RESOLUTION_FILE"
109
109
  sed -i "s|{{BRANCH_NAME}}|${BRANCH_NAME}|g" "$RESOLUTION_FILE"
110
110
  sed -i "s|{{COMMIT_SHA}}|${COMMIT_SHA}|g" "$RESOLUTION_FILE"
111
111
  sed -i "s|{{FILE_COUNT}}|${FILE_COUNT}|g" "$RESOLUTION_FILE"
112
112
 
113
- # Crear archivo temporal para issues formateados
113
+ # Create temporary file for formatted issues
114
114
  local TEMP_ISSUES_FILE=$(mktemp)
115
115
  echo "$ISSUES_FORMATTED" > "$TEMP_ISSUES_FILE"
116
116
 
117
- # Reemplazar {{BLOCKING_ISSUES}} con el contenido
117
+ # Replace {{BLOCKING_ISSUES}} with content
118
118
  if [ -n "$ISSUES_FORMATTED" ]; then
119
119
  sed -i "/{{BLOCKING_ISSUES}}/r $TEMP_ISSUES_FILE" "$RESOLUTION_FILE"
120
120
  fi
121
121
  sed -i "s|{{BLOCKING_ISSUES}}||g" "$RESOLUTION_FILE"
122
122
  rm -f "$TEMP_ISSUES_FILE"
123
123
 
124
- # Agregar contenido de archivos afectados
124
+ # Add content from affected files
125
125
  local TEMP_FILES=$(mktemp)
126
126
  echo "$JSON_RESPONSE" | jq -r '.blockingIssues[].file' 2>/dev/null | sort -u | while IFS= read -r file; do
127
127
  if [ -f "$file" ]; then
@@ -134,7 +134,7 @@ generate_resolution_prompt() {
134
134
  fi
135
135
  done
136
136
 
137
- # Reemplazar {{FILE_CONTENTS}} con el contenido
137
+ # Replace {{FILE_CONTENTS}} with content
138
138
  if [ -s "$TEMP_FILES" ]; then
139
139
  sed -i "/{{FILE_CONTENTS}}/r $TEMP_FILES" "$RESOLUTION_FILE"
140
140
  fi
@@ -142,62 +142,62 @@ generate_resolution_prompt() {
142
142
  rm -f "$TEMP_FILES"
143
143
 
144
144
  echo
145
- echo -e "${YELLOW}=== PROMPT DE RESOLUCIÓN AI GENERADO ===${NC}"
146
- echo -e "${GREEN}Se ha generado un prompt AI-friendly en: ${BLUE}$RESOLUTION_FILE${NC}"
147
- echo -e "${YELLOW}Copia este archivo a una nueva instancia de Claude para resolver los problemas automáticamente.${NC}"
145
+ echo -e "${YELLOW}=== AI RESOLUTION PROMPT GENERATED ===${NC}"
146
+ echo -e "${GREEN}An AI-friendly prompt has been generated at: ${BLUE}$RESOLUTION_FILE${NC}"
147
+ echo -e "${YELLOW}Copy this file to a new Claude instance to resolve problems automatically.${NC}"
148
148
  echo
149
149
  }
150
150
 
151
- # Configurar archivos para modo SonarQube
151
+ # Configure files for SonarQube mode
152
152
  GUIDELINES_FILE=".claude/CLAUDE_PRE_COMMIT_SONAR.md"
153
153
  PROMPT_TEMPLATE=".claude/CLAUDE_ANALYSIS_PROMPT_SONAR.md"
154
154
 
155
155
 
156
- # Verificar que el template de prompt existe
156
+ # Check that the prompt template exists
157
157
  if [ ! -f "$PROMPT_TEMPLATE" ]; then
158
- error "No se encontró el template de prompt: $PROMPT_TEMPLATE"
159
- error "Los archivos de configuración de Claude parecen estar incompletos."
160
- error "Por favor, reinstala claude-git-hooks ejecutando:"
158
+ error "Prompt template not found: $PROMPT_TEMPLATE"
159
+ error "Claude configuration files appear to be incomplete."
160
+ error "Please reinstall claude-git-hooks by running:"
161
161
  error " claude-hooks install --force"
162
162
  exit 1
163
163
  fi
164
- # Función para limpiar archivos temporales
164
+ # Function to clean temporary files
165
165
  cleanup() {
166
166
  rm -rf "$TEMP_DIR"
167
167
  }
168
168
 
169
- # Configurar limpieza al salir
169
+ # Configure cleanup on exit
170
170
  trap cleanup EXIT
171
171
 
172
- # Crear directorio temporal
172
+ # Create temporary directory
173
173
  mkdir -p "$TEMP_DIR"
174
174
 
175
- # Verificar si Claude CLI está instalado (solo para análisis de código)
175
+ # Check if Claude CLI is installed (only for code analysis)
176
176
  if ! command -v "$CLAUDE_CLI" &> /dev/null; then
177
- error "Claude CLI no está instalado o no se encuentra en el PATH"
178
- error "Instala Claude CLI desde: https://github.com/anthropics/claude-cli"
177
+ error "Claude CLI is not installed or not found in PATH"
178
+ error "Install Claude CLI from: https://github.com/anthropics/claude-cli"
179
179
  exit 1
180
180
  fi
181
181
 
182
- # Ahora verificar si hay archivos Java para analizar
182
+ # Now check if there are Java files to analyze
183
183
  JAVA_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(java|xml|properties|yml|yaml)$' || true)
184
184
 
185
185
  if [ -z "$JAVA_FILES" ]; then
186
- log "No hay archivos Java/configuración para revisar"
186
+ log "No Java/configuration files to review"
187
187
  exit 0
188
188
  fi
189
189
 
190
- # Verificar si existe el archivo de pautas
190
+ # Check if the guidelines file exists
191
191
  if [ ! -f "$GUIDELINES_FILE" ]; then
192
- error "No se encontró el archivo de pautas: $GUIDELINES_FILE"
193
- error "Por favor, reinstala claude-git-hooks ejecutando:"
192
+ error "Guidelines file not found: $GUIDELINES_FILE"
193
+ error "Please reinstall claude-git-hooks by running:"
194
194
  error " claude-hooks install --force"
195
195
  exit 1
196
196
  fi
197
197
 
198
- log "Archivos Java/config a revisar: $(echo "$JAVA_FILES" | wc -l)"
198
+ log "Java/config files to review: $(echo "$JAVA_FILES" | wc -l)"
199
199
 
200
- # Función para filtrar contenido con SKIP-ANALYSIS
200
+ # Function to filter content with SKIP-ANALYSIS
201
201
  filter_skip_analysis() {
202
202
  local file_content="$1"
203
203
  local filtered_content=""
@@ -205,77 +205,77 @@ filter_skip_analysis() {
205
205
  local inside_skip_block=false
206
206
 
207
207
  while IFS= read -r line; do
208
- # Detectar SKIP-ANALYSIS para línea única
208
+ # Detect SKIP-ANALYSIS for single line
209
209
  if echo "$line" | grep -q "// SKIP-ANALYSIS"; then
210
210
  skip_next_line=true
211
211
  continue
212
212
  fi
213
213
 
214
- # Detectar inicio/fin de bloque SKIP_ANALYSIS_BLOCK
214
+ # Detect start/end of SKIP_ANALYSIS_BLOCK
215
215
  if echo "$line" | grep -q "// SKIP_ANALYSIS_BLOCK"; then
216
216
  if [ "$inside_skip_block" = true ]; then
217
- # Fin del bloque
217
+ # End of block
218
218
  inside_skip_block=false
219
219
  else
220
- # Inicio del bloque
220
+ # Start of block
221
221
  inside_skip_block=true
222
222
  fi
223
223
  continue
224
224
  fi
225
225
 
226
- # Si estamos dentro de un bloque, saltar la línea
226
+ # If we're inside a block, skip the line
227
227
  if [ "$inside_skip_block" = true ]; then
228
228
  continue
229
229
  fi
230
230
 
231
- # Si debemos saltar la siguiente línea (comentario único)
231
+ # If we should skip the next line (single comment)
232
232
  if [ "$skip_next_line" = true ]; then
233
233
  skip_next_line=false
234
234
  continue
235
235
  fi
236
236
 
237
- # Agregar línea al contenido filtrado
237
+ # Add line to filtered content
238
238
  filtered_content="${filtered_content}${line}"$'\n'
239
239
  done <<< "$file_content"
240
240
 
241
241
  echo "$filtered_content"
242
242
  }
243
243
 
244
- # Construir el prompt para análisis de código
244
+ # Build the prompt for code analysis
245
245
  PROMPT_FILE="$TEMP_DIR/code_review_prompt.txt"
246
246
 
247
- # Copiar el template de prompt
247
+ # Copy the prompt template
248
248
  cat "$PROMPT_TEMPLATE" > "$PROMPT_FILE"
249
249
 
250
- # Agregar las pautas
251
- echo "=== PAUTAS DE EVALUACIÓN ===" >> "$PROMPT_FILE"
250
+ # Add the guidelines
251
+ echo "=== EVALUATION GUIDELINES ===" >> "$PROMPT_FILE"
252
252
  cat "$GUIDELINES_FILE" >> "$PROMPT_FILE"
253
- echo -e "\n\n=== CAMBIOS A REVISAR ===\n" >> "$PROMPT_FILE"
253
+ echo -e "\n\n=== CHANGES TO REVIEW ===\n" >> "$PROMPT_FILE"
254
254
 
255
- # Procesar cada archivo Java
255
+ # Process each Java file
256
256
  FILE_COUNT=0
257
257
  for FILE in $JAVA_FILES; do
258
258
  if [ -f "$FILE" ]; then
259
259
  FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE" 2>/dev/null || echo "0")
260
260
 
261
261
  if [ "$FILE_SIZE" -gt "$MAX_FILE_SIZE" ]; then
262
- warning "Archivo $FILE demasiado grande ($FILE_SIZE bytes), saltando..."
262
+ warning "File $FILE too large ($FILE_SIZE bytes), skipping..."
263
263
  continue
264
264
  fi
265
265
 
266
266
  echo -e "\n--- Archivo: $FILE ---" >> "$PROMPT_FILE"
267
267
 
268
- # Obtener el diff y filtrarlo
269
- DIFF_CONTENT=$(git diff --cached "$FILE" 2>/dev/null || echo "No se pudo obtener diff")
268
+ # Get the diff and filter it
269
+ DIFF_CONTENT=$(git diff --cached "$FILE" 2>/dev/null || echo "Could not get diff")
270
270
  FILTERED_DIFF=$(filter_skip_analysis "$DIFF_CONTENT")
271
271
 
272
- # Mostrar el diff filtrado del archivo
272
+ # Show the filtered diff of the file
273
273
  echo -e "\nDiff:" >> "$PROMPT_FILE"
274
274
  echo "$FILTERED_DIFF" >> "$PROMPT_FILE"
275
275
 
276
- # Si es un archivo nuevo, mostrar contenido completo filtrado
276
+ # If it's a new file, show complete filtered content
277
277
  if git diff --cached --name-status | grep "^A.*$FILE" > /dev/null; then
278
- echo -e "\nContenido completo (archivo nuevo):" >> "$PROMPT_FILE"
278
+ echo -e "\nComplete content (new file):" >> "$PROMPT_FILE"
279
279
  FILE_CONTENT=$(git show ":$FILE" 2>/dev/null || cat "$FILE")
280
280
  FILTERED_CONTENT=$(filter_skip_analysis "$FILE_CONTENT")
281
281
  echo "$FILTERED_CONTENT" >> "$PROMPT_FILE"
@@ -286,45 +286,45 @@ for FILE in $JAVA_FILES; do
286
286
  done
287
287
 
288
288
  if [ "$FILE_COUNT" -eq 0 ]; then
289
- log "No se encontraron archivos válidos para revisar"
289
+ log "No valid files found to review"
290
290
  exit 0
291
291
  fi
292
292
 
293
293
  if [ "$FILE_COUNT" -gt 10 ]; then
294
- warning "Demasiados archivos para revisar ($FILE_COUNT)"
295
- warning "Considera dividir el commit en partes más pequeñas"
294
+ warning "Too many files to review ($FILE_COUNT)"
295
+ warning "Consider splitting the commit into smaller parts"
296
296
  exit 0
297
297
  fi
298
298
 
299
- log "Enviando $FILE_COUNT archivos para revisión con Claude..."
299
+ log "Sending $FILE_COUNT files for review with Claude..."
300
300
 
301
- # Enviar a Claude y capturar respuesta
301
+ # Send to Claude and capture response
302
302
  RESPONSE_FILE="$TEMP_DIR/code_review_response.txt"
303
303
 
304
- # Ejecutar Claude CLI y capturar la respuesta
304
+ # Execute Claude CLI and capture the response
305
305
  if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
306
- # Extraer el JSON de la respuesta
306
+ # Extract the JSON from the response
307
307
  JSON_RESPONSE=$(sed -n '/^{/,/^}/p' "$RESPONSE_FILE" | head -n 1000)
308
308
 
309
309
  if [ -z "$JSON_RESPONSE" ]; then
310
- error "No se recibió una respuesta JSON válida de Claude"
311
- error "Respuesta completa:"
310
+ error "Did not receive a valid JSON response from Claude"
311
+ error "Complete response:"
312
312
  cat "$RESPONSE_FILE"
313
313
  exit 1
314
314
  fi
315
315
 
316
- # Guardar JSON para debug si está activado
316
+ # Save JSON for debug if activated
317
317
  if [ -n "$DEBUG" ]; then
318
318
  echo "$JSON_RESPONSE" > ./debug-claude-response.json
319
- log "Respuesta guardada en debug-claude-response.json"
319
+ log "Response saved to debug-claude-response.json"
320
320
  fi
321
321
 
322
- # Parsear la respuesta usando jq
322
+ # Parse the response using jq
323
323
  APPROVED=$(echo "$JSON_RESPONSE" | jq -r '.approved // false')
324
324
  SCORE=$(echo "$JSON_RESPONSE" | jq -r '.score // 0')
325
325
  RECOMMENDATIONS=$(echo "$JSON_RESPONSE" | jq -r '.recommendations[]?' 2>/dev/null | sed '/^$/d')
326
326
 
327
- # Parsear blockingIssues como objetos y extraer las descripciones
327
+ # Parse blockingIssues as objects and extract descriptions
328
328
  BLOCKING_ISSUES=""
329
329
  BLOCKING_COUNT=$(echo "$JSON_RESPONSE" | jq '.blockingIssues | length' 2>/dev/null || echo "0")
330
330
 
@@ -335,7 +335,7 @@ if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
335
335
  QUALITY_GATE=$(echo "$JSON_RESPONSE" | jq -r '.QUALITY_GATE // ""' 2>/dev/null)
336
336
 
337
337
  if [ -n "$QUALITY_GATE" ] && [ "$QUALITY_GATE" != "null" ]; then
338
- # Mostrar resultados estilo SonarQube
338
+ # Show SonarQube style results
339
339
  echo
340
340
  echo "╔════════════════════════════════════════════════════════════════════╗"
341
341
  echo "║ CODE QUALITY ANALYSIS ║"
@@ -410,51 +410,51 @@ if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
410
410
  echo
411
411
  log "✅ Code analysis completed. Quality gate passed."
412
412
  else
413
- # Mostrar resultados en formato clásico
413
+ # Show results in classic format
414
414
  echo
415
- echo "=== RESULTADO DE LA REVISIÓN ==="
415
+ echo "=== REVIEW RESULTS ==="
416
416
  echo "Score: $SCORE/10"
417
417
 
418
418
  if [ -n "$RECOMMENDATIONS" ] && [ "$RECOMMENDATIONS" != "null" ]; then
419
419
  echo
420
- echo "=== RECOMENDACIONES ==="
420
+ echo "=== RECOMMENDATIONS ==="
421
421
  echo "$RECOMMENDATIONS" | sed 's/^/- /'
422
422
  fi
423
423
 
424
- # Verificar si el commit debe ser bloqueado
424
+ # Check if the commit should be blocked
425
425
  if [ "$APPROVED" = "false" ]; then
426
- error "❌ Commit rechazado por problemas críticos"
426
+ error "❌ Commit rejected due to critical issues"
427
427
  if [ -n "$BLOCKING_ISSUES" ] && [ "$BLOCKING_ISSUES" != "null" ]; then
428
428
  echo
429
- echo "=== PROBLEMAS CRÍTICOS ==="
429
+ echo "=== CRITICAL ISSUES ==="
430
430
  echo "$BLOCKING_ISSUES" | sed 's/^/- /'
431
431
 
432
- # Generar prompt de resolución AI-friendly
432
+ # Generate AI-friendly resolution prompt
433
433
  generate_resolution_prompt
434
434
  fi
435
435
  exit 1
436
436
  fi
437
437
 
438
- # Mostrar detalles adicionales si existen
438
+ # Show additional details if they exist
439
439
  DETAILS=$(echo "$JSON_RESPONSE" | jq -r '.details // null')
440
440
  if [ -n "$DETAILS" ] && [ "$DETAILS" != "null" ]; then
441
441
  echo
442
- echo "=== DETALLES ADICIONALES ==="
443
- # Si details es un string, imprimirlo directamente
442
+ echo "=== ADDITIONAL DETAILS ==="
443
+ # If details is a string, print it directly
444
444
  if echo "$DETAILS" | jq -e 'type == "string"' >/dev/null 2>&1; then
445
445
  echo "$DETAILS" | jq -r '.'
446
- # Si es un objeto o array, formatearlo
446
+ # If it's an object or array, format it
447
447
  else
448
448
  echo "$DETAILS" | jq '.'
449
449
  fi
450
450
  fi
451
451
 
452
- log "✅ Revisión completada. Commit aprobado (Score: $SCORE/10)"
452
+ log "✅ Review completed. Commit approved (Score: $SCORE/10)"
453
453
  fi
454
454
 
455
455
  else
456
- error "Error al ejecutar Claude CLI"
457
- error "Verifica que Claude CLI esté configurado correctamente"
456
+ error "Error executing Claude CLI"
457
+ error "Check that Claude CLI is configured correctly"
458
458
  cat "$RESPONSE_FILE"
459
459
  exit 1
460
460
  fi
@@ -1,23 +1,23 @@
1
1
  #!/bin/bash
2
2
 
3
- # Git Prepare-commit-msg Hook para generar mensajes automáticos con Claude
3
+ # Git Prepare-commit-msg Hook to generate automatic messages with Claude
4
4
  # Archivo: .git/hooks/prepare-commit-msg
5
5
 
6
6
  set -e
7
7
 
8
- # Configuración
8
+ # Configuration
9
9
  CLAUDE_CLI="claude"
10
10
  TEMP_DIR="/tmp/commit-msg-$$"
11
11
  MAX_FILE_SIZE=100000
12
12
  AUTO_COMMIT_ENABLED=true
13
13
 
14
- # Colores para output
14
+ # Colors for output
15
15
  RED='\033[0;31m'
16
16
  GREEN='\033[0;32m'
17
17
  YELLOW='\033[1;33m'
18
18
  NC='\033[0m'
19
19
 
20
- # Función para logging
20
+ # Function for logging
21
21
  log() {
22
22
  printf "${GREEN}[PREPARE-MSG]${NC} %s\n" "$1" >&2
23
23
  }
@@ -26,35 +26,35 @@ warning() {
26
26
  printf "${YELLOW}[WARNING]${NC} %s\n" "$1" >&2
27
27
  }
28
28
 
29
- # Función para limpiar archivos temporales
29
+ # Function to clean temporary files
30
30
  cleanup() {
31
31
  rm -rf "$TEMP_DIR"
32
32
  }
33
33
  trap cleanup EXIT
34
34
 
35
- # Argumentos del hook
35
+ # Hook arguments
36
36
  COMMIT_MSG_FILE="$1"
37
37
  COMMIT_SOURCE="$2"
38
38
 
39
- # Solo procesar si es un commit normal
39
+ # Only process if it's a normal commit
40
40
  if [ "$COMMIT_SOURCE" != "" ] && [ "$COMMIT_SOURCE" != "message" ]; then
41
41
  exit 0
42
42
  fi
43
43
 
44
- # Leer el mensaje actual
44
+ # Read the current message
45
45
  CURRENT_MSG=$(head -n 1 "$COMMIT_MSG_FILE" 2>/dev/null || echo "")
46
46
 
47
- # Verificar si necesitamos generar mensaje
47
+ # Check if we need to generate a message
48
48
  if [ "$CURRENT_MSG" = "auto" ]; then
49
- log "Intentando generar mensaje..."
49
+ log "Trying to generate message..."
50
50
  else
51
51
  exit 0
52
52
  fi
53
53
 
54
- # Verificar si Claude CLI está instalado
54
+ # Check if Claude CLI is installed
55
55
  if ! command -v "$CLAUDE_CLI" &> /dev/null; then
56
- warning "Claude CLI no está instalado"
57
- warning "Commit cancelado. Ejecuta nuevamente sin 'auto' para escribir mensaje manual"
56
+ warning "Claude CLI is not installed"
57
+ warning "Commit canceled. Run again without 'auto' to write manual message"
58
58
  exit 1
59
59
  fi
60
60
 
@@ -62,49 +62,49 @@ mkdir -p "$TEMP_DIR"
62
62
  PROMPT_FILE="$TEMP_DIR/commit_msg_prompt.txt"
63
63
 
64
64
  cat > "$PROMPT_FILE" << 'EOF'
65
- Analiza los siguientes cambios y genera un mensaje de commit siguiendo el formato Conventional Commits.
65
+ Analyze the following changes and generate a commit message following the Conventional Commits format.
66
66
 
67
- Responde SOLO con un JSON válido:
67
+ Respond ONLY with a valid JSON:
68
68
 
69
69
  {
70
70
  "type": "feat|fix|docs|style|refactor|test|chore|ci|perf",
71
- "scope": "alcance opcional (ej: api, frontend, db)",
72
- "title": "descripción corta en presente (max 50 chars)",
73
- "body": "descripción detallada opcional"
71
+ "scope": "optional scope (e.g.: api, frontend, db)",
72
+ "title": "short description in present tense (max 50 chars)",
73
+ "body": "optional detailed description"
74
74
  }
75
75
 
76
- CAMBIOS A ANALIZAR:
76
+ CHANGES TO ANALYZE:
77
77
  EOF
78
78
 
79
- # Obtener archivos staged
79
+ # Get staged files
80
80
  ALL_STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || echo "")
81
81
 
82
82
  if [ -z "$ALL_STAGED_FILES" ]; then
83
- warning "No hay archivos staged"
84
- warning "Commit cancelado. Ejecuta nuevamente sin 'auto' para escribir mensaje manual"
83
+ warning "No staged files"
84
+ warning "Commit canceled. Run again without 'auto' to write manual message"
85
85
  exit 1
86
86
  fi
87
87
 
88
- printf "\nArchivos modificados:\n" >> "$PROMPT_FILE"
88
+ printf "\nModified files:\n" >> "$PROMPT_FILE"
89
89
  echo "$ALL_STAGED_FILES" >> "$PROMPT_FILE"
90
90
 
91
- printf "\nResumen de cambios:\n" >> "$PROMPT_FILE"
92
- git diff --cached --stat >> "$PROMPT_FILE" 2>/dev/null || echo "No se pudo obtener estadísticas"
91
+ printf "\nSummary of changes:\n" >> "$PROMPT_FILE"
92
+ git diff --cached --stat >> "$PROMPT_FILE" 2>/dev/null || echo "Could not get statistics"
93
93
 
94
- # Mostrar diffs de archivos pequeños
94
+ # Show diffs of small files
95
95
  for FILE in $ALL_STAGED_FILES; do
96
96
  if [ -f "$FILE" ]; then
97
97
  FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE" 2>/dev/null || echo "0")
98
98
 
99
99
  if [ "$FILE_SIZE" -lt "$MAX_FILE_SIZE" ]; then
100
- printf "\n--- Diff de %s ---\n" "$FILE" >> "$PROMPT_FILE"
101
- git diff --cached "$FILE" >> "$PROMPT_FILE" 2>/dev/null || echo "No se pudo obtener diff"
100
+ printf "\n--- Diff of %s ---\n" "$FILE" >> "$PROMPT_FILE"
101
+ git diff --cached "$FILE" >> "$PROMPT_FILE" 2>/dev/null || echo "Could not get diff"
102
102
  fi
103
103
  fi
104
104
  done
105
105
 
106
106
  RESPONSE_FILE="$TEMP_DIR/commit_msg_response.txt"
107
- log "Generando mensaje de commit con Claude..."
107
+ log "Generating commit message with Claude..."
108
108
 
109
109
  if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
110
110
  JSON_MSG=$(sed -n '/^{/,/^}/p' "$RESPONSE_FILE" | head -n 1000)
@@ -127,12 +127,12 @@ if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
127
127
  fi
128
128
 
129
129
  printf "%s\n" "$FULL_MESSAGE" > "$COMMIT_MSG_FILE"
130
- log "📝 Mensaje generado: $(echo "$FULL_MESSAGE" | head -n 1)"
130
+ log "📝 Message generated: $(echo "$FULL_MESSAGE" | head -n 1)"
131
131
  exit 0
132
132
  fi
133
133
  fi
134
134
  fi
135
135
 
136
- warning "No se pudo generar el mensaje automáticamente con Claude"
137
- warning "Commit cancelado. Ejecuta nuevamente sin 'auto' para escribir mensaje manual"
136
+ warning "Could not generate message automatically with Claude"
137
+ warning "Commit canceled. Run again without 'auto' to write manual message"
138
138
  exit 1