claude-git-hooks 1.2.4 → 1.3.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,31 @@ Todos los cambios notables en este proyecto se documentarán en este archivo.
5
5
  El formato está basado en [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.0] - 2025-08-28
9
+
10
+ ### Added
11
+ - 🚀 Nuevo comando `claude-hooks update` para actualizar a la última versión disponible
12
+ - 🔄 Verificación automática de versión antes de cada commit con prompt interactivo
13
+ - 📜 Script compartido `check-version.sh` para evitar duplicación de código
14
+ - ✨ Prompt interactivo compatible con todas las consolas para aceptar actualizaciones
15
+ - 📊 Mensajes informativos detallados durante el proceso de verificación y actualización
16
+
17
+ ### Changed
18
+ - 🎯 El hook `pre-commit` ahora verifica automáticamente si hay actualizaciones disponibles
19
+ - 📦 La instalación ahora incluye el script `check-version.sh` en `.git/hooks/`
20
+ - 🔧 Mejorada la UX con mensajes claros sobre el estado de la versión
21
+
22
+ ### Fixed
23
+ - 🐛 Corregido el parsing de versión desde NPM API (usaba endpoint incorrecto)
24
+ - 🔧 Mejorada la compatibilidad del prompt interactivo para consolas IntelliJ/WSL
25
+ - 📝 Múltiples métodos de fallback para leer input del usuario
26
+
27
+ ### Technical
28
+ - 🏗️ Función `getLatestVersion()` ahora usa `dist-tags.latest` de NPM API
29
+ - 🔄 Función `checkVersionAndPromptUpdate()` reutilizable para verificación
30
+ - 📁 Script compartido para evitar duplicación de lógica de verificación
31
+ - 🎯 Fallback a `npm view` si la API de NPM falla
32
+
8
33
  ## [1.2.4] - 2025-08-22
9
34
 
10
35
  ### Fixed
package/README.md CHANGED
@@ -93,11 +93,11 @@ Luego añade esto a tu `package.json`:
93
93
 
94
94
  ## 🤖 Características
95
95
 
96
- **✨ Auto-actualización incorporada**: Los hooks se actualizan automáticamente en cada commit.
96
+ **✨ Auto-actualización**: Verifica automáticamente si hay nuevas versiones disponibles antes de cada commit y ofrece actualizar con un simple prompt interactivo.
97
97
 
98
98
  **Hooks disponibles**:
99
99
 
100
- - `pre-commit`: Análisis de código con Claude (solo archivos Java/config)
100
+ - `pre-commit`: Análisis de código con Claude (solo archivos Java/config) con verificación automática de versión
101
101
  - `prepare-commit-msg`: Generación automática de mensajes de commit
102
102
 
103
103
  ## 📁 Gestión de Archivos
@@ -172,7 +172,8 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
172
172
 
173
173
  ### Características adicionales
174
174
 
175
- - **Auto-actualización**: Los hooks se sincronizan automáticamente con las versiones en `git-hooks/`
175
+ - **Auto-actualización**: Verificación automática de versiones antes de cada commit con prompt interactivo para actualizar
176
+ - **Comando update**: `claude-hooks update` para actualizar manualmente a la última versión
176
177
  - **Modo debug**: `DEBUG=1 git commit` guarda respuestas en `debug-claude-response.json`
177
178
  - **Configuración persistente**: Guarda preferencias en `.claude-analysis-mode`
178
179
  - **Validación de dependencias**: Verifica que Claude CLI esté autenticado antes de ejecutar
@@ -273,7 +274,18 @@ Claude responde con un JSON que incluye:
273
274
  - `recommendations`: Recomendaciones de mejora
274
275
  - `blockingIssues`: Problemas que bloquean el commit
275
276
 
276
- ## 🔄 Desactivar/Activar
277
+ ## 🔄 Actualización y Gestión
278
+
279
+ ### Actualizar a la última versión
280
+
281
+ ```bash
282
+ # Actualizar manualmente a la última versión
283
+ claude-hooks update
284
+ ```
285
+
286
+ El comando `update` descarga e instala automáticamente la última versión disponible desde NPM, y luego reinstala los hooks con las nuevas características.
287
+
288
+ ### Desactivar/Activar hooks
277
289
 
278
290
  ```bash
279
291
  # Desactivar todos los hooks
package/bin/claude-hooks CHANGED
@@ -7,6 +7,86 @@ const os = require('os');
7
7
  const readline = require('readline');
8
8
  const https = require('https');
9
9
 
10
+ // Función para obtener la última versión desde NPM
11
+ function getLatestVersion(packageName) {
12
+ return new Promise((resolve, reject) => {
13
+ // Usar la API principal de NPM, no /latest
14
+ https.get(`https://registry.npmjs.org/${packageName}`, (res) => {
15
+ let data = '';
16
+ res.on('data', chunk => data += chunk);
17
+ res.on('end', () => {
18
+ try {
19
+ const json = JSON.parse(data);
20
+ // Obtener la versión del tag 'latest'
21
+ if (json['dist-tags'] && json['dist-tags'].latest) {
22
+ resolve(json['dist-tags'].latest);
23
+ } else {
24
+ reject(new Error('No se pudo obtener la versión'));
25
+ }
26
+ } catch (e) {
27
+ // Si falla, intentar con npm view
28
+ try {
29
+ const version = execSync(`npm view ${packageName} version`, { encoding: 'utf8' }).trim();
30
+ resolve(version);
31
+ } catch (npmError) {
32
+ reject(e);
33
+ }
34
+ }
35
+ });
36
+ }).on('error', reject);
37
+ });
38
+ }
39
+
40
+ // Función para verificar versión (usada por los hooks)
41
+ async function checkVersionAndPromptUpdate() {
42
+ try {
43
+ const currentVersion = require('../package.json').version;
44
+ const latestVersion = await getLatestVersion('claude-git-hooks');
45
+
46
+ if (currentVersion === latestVersion) {
47
+ return true; // Ya actualizado
48
+ }
49
+
50
+ console.log('');
51
+ warning(`Nueva versión disponible: ${latestVersion} (actual: ${currentVersion})`);
52
+
53
+ // Prompt interactivo compatible con todas las consolas
54
+ const rl = readline.createInterface({
55
+ input: process.stdin,
56
+ output: process.stdout
57
+ });
58
+
59
+ return new Promise((resolve) => {
60
+ rl.question('¿Deseas actualizar ahora? (s/n): ', (answer) => {
61
+ rl.close();
62
+
63
+ if (answer.toLowerCase() === 's' || answer.toLowerCase() === 'si' || answer.toLowerCase() === 'sí' || answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {
64
+ info('Actualizando claude-git-hooks...');
65
+ try {
66
+ execSync('npm install -g claude-git-hooks@latest', { stdio: 'inherit' });
67
+ success('Actualización completada. Por favor, vuelve a ejecutar tu comando.');
68
+ process.exit(0); // Salir para que el usuario reinicie el proceso
69
+ } catch (e) {
70
+ error('Error al actualizar: ' + e.message);
71
+ resolve(false);
72
+ }
73
+ } else {
74
+ info('Actualización pospuesta. Puedes actualizar más tarde con: claude-hooks update');
75
+ resolve(true); // Continuar sin actualizar
76
+ }
77
+ });
78
+ });
79
+ } catch (e) {
80
+ // Si hay error verificando la versión, continuar sin bloquear
81
+ return true;
82
+ }
83
+ }
84
+
85
+ // Exportar para uso en hooks
86
+ if (typeof module !== 'undefined' && module.exports) {
87
+ module.exports = { checkVersionAndPromptUpdate };
88
+ }
89
+
10
90
  // Colores para output
11
91
  const colors = {
12
92
  reset: '\x1b[0m',
@@ -258,7 +338,13 @@ async function install(args) {
258
338
  error('No estás en un repositorio Git. Por favor, ejecuta este comando desde la raíz de un repositorio.');
259
339
  }
260
340
 
261
- info('Instalando Claude Git Hooks...');
341
+ const isForce = args.includes('--force');
342
+
343
+ if (isForce) {
344
+ info('Instalando Claude Git Hooks (modo force)...');
345
+ } else {
346
+ info('Instalando Claude Git Hooks...');
347
+ }
262
348
 
263
349
  // Solicitar contraseña sudo al inicio si es necesario
264
350
  let sudoPassword = null;
@@ -308,6 +394,16 @@ async function install(args) {
308
394
  success(`${hook} instalado`);
309
395
  });
310
396
 
397
+ // Copiar script de verificación de versión
398
+ const checkVersionSource = path.join(templatesPath, 'check-version.sh');
399
+ const checkVersionDest = path.join(hooksPath, 'check-version.sh');
400
+
401
+ if (fs.existsSync(checkVersionSource)) {
402
+ fs.copyFileSync(checkVersionSource, checkVersionDest);
403
+ fs.chmodSync(checkVersionDest, '755');
404
+ success('Script de verificación de versión instalado');
405
+ }
406
+
311
407
  // Crear directorio .claude si no existe
312
408
  const claudeDir = '.claude';
313
409
  if (!fs.existsSync(claudeDir)) {
@@ -420,7 +516,7 @@ async function checkAndInstallDependencies(sudoPassword = null) {
420
516
  if (missingTools.length === 0) {
421
517
  success('Herramientas Unix estándar verificadas');
422
518
  } else {
423
- error(`Faltan herramientas Unix estándar: ${missingTools.join(', ')}`);
519
+ error(`Faltan herramientas Unix estándar: ${missingTools.join(', ')}. Reintenta instalación en una consola Ubuntu`);
424
520
  }
425
521
 
426
522
  // Verificar e instalar Claude CLI
@@ -785,6 +881,87 @@ function setMode(mode) {
785
881
  }
786
882
  }
787
883
 
884
+ // Función para comparar versiones usando el script compartido
885
+ function compareVersions(v1, v2) {
886
+ try {
887
+ // Usar el script compartido para mantener consistencia
888
+ const result = execSync(`bash -c 'source "${getTemplatesPath()}/check-version.sh" && compare_versions "${v1}" "${v2}"; echo $?'`, { encoding: 'utf8' }).trim();
889
+ const exitCode = parseInt(result);
890
+
891
+ // Convertir los códigos de retorno del script bash a valores JS
892
+ if (exitCode === 0) return 0; // iguales
893
+ if (exitCode === 1) return 1; // v1 > v2
894
+ if (exitCode === 2) return -1; // v1 < v2
895
+
896
+ // Fallback: comparación simple si el script falla
897
+ if (v1 === v2) return 0;
898
+ const sorted = [v1, v2].sort((a, b) => {
899
+ const aParts = a.split('.').map(Number);
900
+ const bParts = b.split('.').map(Number);
901
+ for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
902
+ const aPart = aParts[i] || 0;
903
+ const bPart = bParts[i] || 0;
904
+ if (aPart !== bPart) return aPart - bPart;
905
+ }
906
+ return 0;
907
+ });
908
+ return v1 === sorted[1] ? 1 : -1;
909
+ } catch (e) {
910
+ // Si falla todo, usar comparación simple
911
+ if (v1 === v2) return 0;
912
+ return v1 > v2 ? 1 : -1;
913
+ }
914
+ }
915
+
916
+ // Comando update - actualizar a la última versión
917
+ async function update() {
918
+ info('Verificando última versión disponible...');
919
+
920
+ try {
921
+ const currentVersion = require('../package.json').version;
922
+ const latestVersion = await getLatestVersion('claude-git-hooks');
923
+
924
+ const comparison = compareVersions(currentVersion, latestVersion);
925
+
926
+ if (comparison === 0) {
927
+ success(`Ya tienes la última versión instalada (${currentVersion})`);
928
+ return;
929
+ } else if (comparison > 0) {
930
+ info(`Estás usando una versión de desarrollo (${currentVersion})`);
931
+ info(`Última versión publicada: ${latestVersion}`);
932
+ success(`Ya tienes la última versión instalada (${currentVersion})`);
933
+ return;
934
+ }
935
+
936
+ info(`Versión actual: ${currentVersion}`);
937
+ info(`Versión disponible: ${latestVersion}`);
938
+
939
+ // Actualizar el paquete
940
+ info('Actualizando claude-git-hooks...');
941
+ try {
942
+ execSync('npm install -g claude-git-hooks@latest', { stdio: 'inherit' });
943
+ success(`Actualizado exitosamente a la versión ${latestVersion}`);
944
+
945
+ // Reinstalar hooks con la nueva versión
946
+ info('Reinstalando hooks con la nueva versión...');
947
+ await install(['--force']);
948
+
949
+ } catch (updateError) {
950
+ error('Error al actualizar. Intenta ejecutar: npm install -g claude-git-hooks@latest');
951
+ }
952
+ } catch (e) {
953
+ warning('No se pudo verificar la última versión disponible');
954
+ warning('Intentando actualizar de todas formas...');
955
+ try {
956
+ execSync('npm install -g claude-git-hooks@latest', { stdio: 'inherit' });
957
+ success('Actualización completada');
958
+ await install(['--force']);
959
+ } catch (updateError) {
960
+ error('Error al actualizar: ' + updateError.message);
961
+ }
962
+ }
963
+ }
964
+
788
965
  // Comando help
789
966
  function showHelp() {
790
967
  console.log(`
@@ -794,6 +971,7 @@ Uso: claude-hooks <comando> [opciones]
794
971
 
795
972
  Comandos:
796
973
  install Instala los hooks en el repositorio actual
974
+ update Actualiza a la última versión disponible
797
975
  uninstall Desinstala los hooks del repositorio
798
976
  enable [hook] Habilita hooks (todos o uno específico)
799
977
  disable [hook] Deshabilita hooks (todos o uno específico)
@@ -807,6 +985,7 @@ Hooks disponibles:
807
985
 
808
986
  Ejemplos:
809
987
  claude-hooks install # Instala todos los hooks
988
+ claude-hooks update # Actualiza a la última versión
810
989
  claude-hooks set-mode sonar # Cambiar a modo SonarQube
811
990
  claude-hooks set-mode standard # Cambiar a modo estándar
812
991
  claude-hooks disable pre-commit # Deshabilita solo pre-commit
@@ -826,6 +1005,9 @@ async function main() {
826
1005
  case 'install':
827
1006
  await install(args.slice(1));
828
1007
  break;
1008
+ case 'update':
1009
+ await update();
1010
+ break;
829
1011
  case 'uninstall':
830
1012
  uninstall();
831
1013
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-git-hooks",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
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": {
@@ -0,0 +1,266 @@
1
+ #!/bin/bash
2
+
3
+ # Script compartido para verificar versión de claude-git-hooks
4
+ # Este script puede ser invocado desde cualquier hook
5
+
6
+ # Colores para output
7
+ RED='\033[0;31m'
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ BLUE='\033[0;34m'
11
+ NC='\033[0m' # No Color
12
+
13
+ # Función para logging
14
+ log() {
15
+ echo -e "${GREEN}[VERSION-CHECK]${NC} $1"
16
+ }
17
+
18
+ error() {
19
+ echo -e "${RED}[ERROR]${NC} $1"
20
+ }
21
+
22
+ warning() {
23
+ echo -e "${YELLOW}[WARNING]${NC} $1"
24
+ }
25
+
26
+ info() {
27
+ echo -e "${BLUE}[INFO]${NC} $1"
28
+ }
29
+
30
+ # Función compartida para comparar versiones semánticas
31
+ # Retorna: 1 si v1 > v2, 2 si v1 < v2, 0 si son iguales
32
+ compare_versions() {
33
+ local v1="$1"
34
+ local v2="$2"
35
+
36
+ if [ -n "$DEBUG_VERSION" ]; then
37
+ echo "[DEBUG] compare_versions: comparando '$v1' con '$v2'"
38
+ fi
39
+
40
+ # Si son exactamente iguales
41
+ if [ "$v1" = "$v2" ]; then
42
+ if [ -n "$DEBUG_VERSION" ]; then
43
+ echo "[DEBUG] compare_versions: versiones iguales, retornando 0"
44
+ fi
45
+ return 0
46
+ fi
47
+
48
+ # Usar sort -V que entiende versiones semánticas correctamente
49
+ local sorted=$(printf "%s\n%s" "$v1" "$v2" | sort -V)
50
+ local smaller=$(echo "$sorted" | head -1)
51
+ local larger=$(echo "$sorted" | tail -1)
52
+
53
+ if [ -n "$DEBUG_VERSION" ]; then
54
+ echo "[DEBUG] compare_versions: sorted='$sorted', smaller='$smaller', larger='$larger'"
55
+ fi
56
+
57
+ if [ "$v1" = "$larger" ]; then
58
+ if [ -n "$DEBUG_VERSION" ]; then
59
+ echo "[DEBUG] compare_versions: v1 es mayor, retornando 1"
60
+ fi
61
+ return 1 # v1 es mayor que v2
62
+ else
63
+ if [ -n "$DEBUG_VERSION" ]; then
64
+ echo "[DEBUG] compare_versions: v1 es menor, retornando 2"
65
+ fi
66
+ return 2 # v1 es menor que v2 (cambié de 255 a 2 para evitar problemas con set -e)
67
+ fi
68
+ }
69
+
70
+ # Función principal de verificación
71
+ check_version() {
72
+ # Debug mode si está activado
73
+ if [ -n "$DEBUG_VERSION" ]; then
74
+ echo "[DEBUG] Iniciando verificación de versión..."
75
+ fi
76
+
77
+ info "Verificando versión instalada..."
78
+
79
+ # Intentar obtener versión actual desde package.json global
80
+ CURRENT_VERSION=""
81
+ NPM_PREFIX=$(npm prefix -g 2>/dev/null || echo "/usr/local")
82
+ PACKAGE_JSON_PATHS=(
83
+ "$NPM_PREFIX/lib/node_modules/claude-git-hooks/package.json"
84
+ "/usr/lib/node_modules/claude-git-hooks/package.json"
85
+ "/usr/local/lib/node_modules/claude-git-hooks/package.json"
86
+ "$HOME/.npm-global/lib/node_modules/claude-git-hooks/package.json"
87
+ )
88
+
89
+ for path in "${PACKAGE_JSON_PATHS[@]}"; do
90
+ if [ -f "$path" ]; then
91
+ CURRENT_VERSION=$(grep '"version"' "$path" 2>/dev/null | sed 's/.*"version".*"\(.*\)".*/\1/')
92
+ break
93
+ fi
94
+ done
95
+
96
+ if [ -z "$CURRENT_VERSION" ]; then
97
+ warning "No se pudo determinar la versión actual"
98
+ return 0 # Continuar sin bloquear
99
+ fi
100
+
101
+ if [ -n "$DEBUG_VERSION" ]; then
102
+ echo "[DEBUG] Versión actual encontrada: $CURRENT_VERSION"
103
+ fi
104
+
105
+ # Obtener última versión desde NPM (usando npm view que es más confiable)
106
+ info "Verificando última versión disponible..."
107
+
108
+ # Método principal: usar npm view que es más confiable
109
+ if [ -n "$DEBUG_VERSION" ]; then
110
+ echo "[DEBUG] Ejecutando: npm view claude-git-hooks version"
111
+ fi
112
+
113
+ LATEST_VERSION=$(npm view claude-git-hooks version 2>/dev/null || echo "")
114
+
115
+ if [ -n "$DEBUG_VERSION" ]; then
116
+ echo "[DEBUG] npm view retornó: '$LATEST_VERSION'"
117
+ echo "[DEBUG] Longitud de LATEST_VERSION: ${#LATEST_VERSION}"
118
+ fi
119
+
120
+ # Si npm view falla, intentar con la API de NPM
121
+ if [ -z "$LATEST_VERSION" ]; then
122
+ # Obtener el JSON completo y extraer dist-tags.latest con jq si está disponible
123
+ if command -v jq &> /dev/null; then
124
+ LATEST_VERSION=$(curl -s https://registry.npmjs.org/claude-git-hooks 2>/dev/null | jq -r '."dist-tags".latest' 2>/dev/null || echo "")
125
+ if [ -n "$DEBUG_VERSION" ]; then
126
+ echo "[DEBUG] jq parsing retornó: '$LATEST_VERSION'"
127
+ fi
128
+ else
129
+ # Sin jq, usar método más robusto con sed
130
+ LATEST_VERSION=$(curl -s https://registry.npmjs.org/claude-git-hooks 2>/dev/null | sed -n 's/.*"dist-tags":{[^}]*"latest":"\([^"]*\)".*/\1/p' | head -1)
131
+ if [ -n "$DEBUG_VERSION" ]; then
132
+ echo "[DEBUG] sed parsing retornó: '$LATEST_VERSION'"
133
+ fi
134
+ fi
135
+ fi
136
+
137
+ # Validar que lo obtenido parece una versión (formato X.Y.Z)
138
+ if [ -n "$DEBUG_VERSION" ]; then
139
+ echo "[DEBUG] Validando versión: '$LATEST_VERSION'"
140
+ fi
141
+
142
+ if ! echo "$LATEST_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+' ; then
143
+ if [ -n "$DEBUG_VERSION" ]; then
144
+ echo "[DEBUG] Versión obtenida no es válida: '$LATEST_VERSION'"
145
+ fi
146
+ warning "No se pudo obtener una versión válida del registro NPM"
147
+ return 0
148
+ fi
149
+
150
+ if [ -n "$DEBUG_VERSION" ]; then
151
+ echo "[DEBUG] Versión válida confirmada: '$LATEST_VERSION'"
152
+ fi
153
+
154
+ if [ -z "$LATEST_VERSION" ]; then
155
+ # Si no se puede obtener la versión, continuar sin bloquear
156
+ return 0
157
+ fi
158
+
159
+ if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
160
+ log "Versión actual ($CURRENT_VERSION) está actualizada ✓"
161
+ return 0
162
+ fi
163
+
164
+ # Comparar versiones usando la función compartida
165
+ if [ -n "$DEBUG_VERSION" ]; then
166
+ echo "[DEBUG] Comparando versiones: '$CURRENT_VERSION' vs '$LATEST_VERSION'"
167
+ fi
168
+
169
+ # Deshabilitar set -e temporalmente para capturar el código de retorno
170
+ set +e
171
+ compare_versions "$CURRENT_VERSION" "$LATEST_VERSION"
172
+ comparison_result=$?
173
+ set -e
174
+
175
+ if [ -n "$DEBUG_VERSION" ]; then
176
+ echo "[DEBUG] Resultado de comparación: $comparison_result"
177
+ fi
178
+
179
+ if [ $comparison_result -eq 0 ]; then
180
+ # Las versiones son iguales
181
+ if [ -n "$DEBUG_VERSION" ]; then
182
+ echo "[DEBUG] Las versiones son iguales"
183
+ fi
184
+ log "Versión actual ($CURRENT_VERSION) está actualizada ✓"
185
+ return 0
186
+ elif [ $comparison_result -eq 1 ]; then
187
+ # La versión actual es mayor que la publicada (desarrollo local)
188
+ if [ -n "$DEBUG_VERSION" ]; then
189
+ echo "[DEBUG] Versión local ($CURRENT_VERSION) es más nueva que la publicada ($LATEST_VERSION)"
190
+ fi
191
+ log "Versión de desarrollo ($CURRENT_VERSION) > versión publicada ($LATEST_VERSION) ✓"
192
+ return 0
193
+ elif [ $comparison_result -eq 2 ]; then
194
+ # La versión publicada es mayor, continuar con prompt de actualización
195
+ if [ -n "$DEBUG_VERSION" ]; then
196
+ echo "[DEBUG] La versión publicada ($LATEST_VERSION) es más nueva que la local ($CURRENT_VERSION)"
197
+ fi
198
+ # Continuar con el prompt de actualización (no return aquí)
199
+ fi
200
+
201
+ if [ -n "$DEBUG_VERSION" ]; then
202
+ echo "[DEBUG] La versión publicada es más nueva, procediendo con prompt de actualización"
203
+ fi
204
+
205
+ # Solo mostrar actualización si la versión publicada es realmente más nueva
206
+ echo
207
+ warning "Nueva versión disponible: $LATEST_VERSION (actual: $CURRENT_VERSION)"
208
+ echo -e "${YELLOW}╭─────────────────────────────────────────────╮${NC}"
209
+ echo -e "${YELLOW}│${NC} Una nueva versión de claude-git-hooks está ${YELLOW}│${NC}"
210
+ echo -e "${YELLOW}│${NC} disponible con mejoras y correcciones ${YELLOW}│${NC}"
211
+ echo -e "${YELLOW}╰─────────────────────────────────────────────╯${NC}"
212
+ echo
213
+
214
+ # Leer respuesta del usuario de forma compatible con todas las consolas
215
+ echo -n "¿Deseas actualizar ahora? (s/n): "
216
+
217
+ # Intentar varios métodos de lectura para máxima compatibilidad
218
+ REPLY=""
219
+
220
+ # Método 1: Leer desde /dev/tty si existe
221
+ if [ -c /dev/tty ]; then
222
+ read -r REPLY </dev/tty 2>/dev/null || REPLY=""
223
+ fi
224
+
225
+ # Método 2: Si falla, intentar leer desde stdin estándar
226
+ if [ -z "$REPLY" ]; then
227
+ read -r REPLY 2>/dev/null || REPLY=""
228
+ fi
229
+
230
+ # Método 3: Si aún no tenemos respuesta, usar bash -c
231
+ if [ -z "$REPLY" ]; then
232
+ REPLY=$(bash -c 'read -r reply && echo "$reply"' 2>/dev/null || echo "")
233
+ fi
234
+
235
+ # Si ningún método funcionó, informar y continuar
236
+ if [ -z "$REPLY" ]; then
237
+ echo
238
+ info "No se pudo leer la respuesta. Continuando sin actualizar."
239
+ info "Para actualizar manualmente, ejecuta: claude-hooks update"
240
+ return 0
241
+ fi
242
+
243
+ if [ "$REPLY" = "s" ] || [ "$REPLY" = "S" ] || [ "$REPLY" = "si" ] || [ "$REPLY" = "SI" ] || [ "$REPLY" = "sí" ] || [ "$REPLY" = "SÍ" ] || [ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ] || [ "$REPLY" = "yes" ] || [ "$REPLY" = "YES" ]; then
244
+ echo
245
+ info "Actualizando claude-git-hooks..."
246
+
247
+ if npm install -g claude-git-hooks@latest; then
248
+ echo
249
+ log "✅ Actualización completada exitosamente"
250
+ info "Por favor, vuelve a ejecutar tu comando git commit"
251
+ exit 0 # Salir para que el usuario reinicie con la nueva versión
252
+ else
253
+ error "Error al actualizar. Intenta manualmente con: npm install -g claude-git-hooks@latest"
254
+ return 1
255
+ fi
256
+ else
257
+ info "Actualización pospuesta. Puedes actualizar más tarde con: claude-hooks update"
258
+ echo
259
+ return 0
260
+ fi
261
+ }
262
+
263
+ # Si se ejecuta directamente (no como source), ejecutar la verificación
264
+ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
265
+ check_version
266
+ fi
@@ -14,6 +14,7 @@ MAX_FILE_SIZE=100000 # 100KB máximo por archivo
14
14
  RED='\033[0;31m'
15
15
  GREEN='\033[0;32m'
16
16
  YELLOW='\033[1;33m'
17
+ BLUE='\033[0;34m'
17
18
  NC='\033[0m' # No Color
18
19
 
19
20
  # Función para logging
@@ -29,6 +30,32 @@ warning() {
29
30
  echo -e "${YELLOW}[WARNING]${NC} $1"
30
31
  }
31
32
 
33
+ # Verificar versión al inicio (antes de cualquier análisis)
34
+ # Intentar encontrar el script check-version.sh
35
+ CHECK_VERSION_SCRIPT=""
36
+ # Buscar en múltiples ubicaciones posibles
37
+ SCRIPT_PATHS=(
38
+ "$(dirname "$0")/check-version.sh"
39
+ "/usr/local/lib/node_modules/claude-git-hooks/templates/check-version.sh"
40
+ "/usr/lib/node_modules/claude-git-hooks/templates/check-version.sh"
41
+ "$HOME/.npm-global/lib/node_modules/claude-git-hooks/templates/check-version.sh"
42
+ "$(npm prefix -g 2>/dev/null)/lib/node_modules/claude-git-hooks/templates/check-version.sh"
43
+ )
44
+
45
+ for path in "${SCRIPT_PATHS[@]}"; do
46
+ if [ -f "$path" ]; then
47
+ CHECK_VERSION_SCRIPT="$path"
48
+ break
49
+ fi
50
+ done
51
+
52
+ # Si encontramos el script, ejecutarlo
53
+ if [ -n "$CHECK_VERSION_SCRIPT" ]; then
54
+ # Source el script para tener acceso a la función
55
+ source "$CHECK_VERSION_SCRIPT"
56
+ check_version
57
+ fi
58
+
32
59
  # Detectar qué archivo de pautas usar
33
60
  # Prioridad: variable de entorno > archivo > pregunta interactiva
34
61
  if [ -n "$CLAUDE_ANALYSIS_MODE" ]; then