claude-git-hooks 1.4.2 → 1.5.1

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,12 +5,47 @@ 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.5.1] - 2025-09-11
9
+
10
+ ### Added
11
+ - 📋 Sección CHEATSHEET en README
12
+
13
+ ### Fixed
14
+ - 🔧 SKIP_ANALYSIS_BLOCK funciona correctamente
15
+ - 📝 Estructura del proyecto en documentación
16
+
17
+ ## [1.5.0] - 2025-09-10
18
+
19
+ ### Added
20
+ - 🔍 Nuevo comando `claude-hooks analyze-diff [base]` para análisis de diferencias entre ramas
21
+ - Genera título de PR conciso (máx. 72 caracteres)
22
+ - Crea descripción detallada del PR con markdown
23
+ - Sugiere nombre de rama siguiendo formato tipo/descripcion
24
+ - Identifica tipo de cambio (feature/fix/refactor/docs/test/chore)
25
+ - Detecta breaking changes
26
+ - Proporciona notas de testing recomendado
27
+ - Guarda resultados en `.claude-pr-analysis.json`
28
+
29
+ ### Changed
30
+ - 🎯 Modo SonarQube ahora es el predeterminado (no hay selección interactiva)
31
+ - ⚡ Eliminada lógica de selección de modo del pre-commit hook
32
+ - 🗑️ Removidas referencias a guardado de preferencias `.claude-analysis-mode`
33
+
34
+ ### Fixed
35
+ - 🐛 Eliminado prompt interactivo incompatible con algunas consolas
36
+ - 🔧 Pre-commit ahora va directo al análisis sin solicitar input del usuario
37
+
38
+ ### Removed
39
+ - 🗑️ Eliminada selección interactiva de modo de análisis
40
+ - 🗑️ Removido comando `set-mode` (ya no es necesario)
41
+ - 🗑️ Eliminada variable de entorno `CLAUDE_ANALYSIS_MODE`
42
+
8
43
  ## [1.4.2] - 2025-09-08
9
44
 
10
45
  ### Added
11
46
  - 🚫 Comentario `// SKIP-ANALYSIS` para excluir código del análisis
12
47
  - Una línea: excluye la siguiente línea
13
- - Bloque: código entre dos comentarios `// SKIP-ANALYSIS` es excluido
48
+ - Bloque: código entre dos comentarios `// SKIP_ANALYSIS_BLOCK` es excluido
14
49
  - 📝 Excepciones para Spring Framework en criterios de evaluación
15
50
  - `@Autowired` no es considerado issue bloqueante (máximo severidad MAJOR)
16
51
  - Inyección de dependencias con field injection es aceptable
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -1,22 +1,129 @@
1
1
  # Pre-commit Hook con Claude CLI
2
2
 
3
3
  Este directorio contiene un pre-commit hook que utiliza Claude CLI para revisar automáticamente el código antes de cada commit.
4
+ Otras funciones de interés:
4
5
 
5
- ## 📁 Archivos en este Directorio
6
+ - Generación de mensaje de commit.
7
+ - Generación de información de PR y tests de validación de PR - Utiliza análisis de diferencias entre contenido local y origin.
6
8
 
7
- - **`README.md`** - Esta documentación
8
- - **`pre-commit`** - Hook principal para análisis de código (con auto-actualización)
9
- - **`prepare-commit-msg`** - Hook para generar mensajes de commit automáticos
10
- - **`.gitattributes`** - Configuración para mantener line endings correctos
11
- - **`.claude/CLAUDE_PRE_COMMIT.md`** - Pautas de evaluación formato estándar
12
- - **`.claude/CLAUDE_PRE_COMMIT_SONAR.md`** - Pautas de evaluación formato SonarQube
13
- - **`.claude/CLAUDE_ANALYSIS_PROMPT.md`** - Template de prompt para análisis estándar
14
- - **`.claude/CLAUDE_ANALYSIS_PROMPT_SONAR.md`** - Template de prompt para análisis SonarQube
15
- - **`.claude/CLAUDE_RESOLUTION_PROMPT.md`** - Template para generar prompt de resolución AI
9
+ ## 📋 CHEATSHEET
10
+
11
+ ### 🚀 Comandos Frecuentes
12
+
13
+ ```bash
14
+ # Commit rápido sin análisis + mensaje automático
15
+ git commit --no-verify -m "auto"
16
+
17
+ # Analizar diferencias con rama origin actual
18
+ claude-hooks analyze-diff
19
+
20
+ # Analizar diferencias para PR (comparar con develop)
21
+ claude-hooks analyze-diff develop
22
+
23
+ # Reinstalar durante desarrollo (después de npm link)
24
+ claude-hooks install --force --skip-auth
25
+ ```
26
+
27
+ ### 📦 Instalación y Gestión
28
+
29
+ ```bash
30
+ # Instalación inicial
31
+ claude-hooks install
32
+
33
+ # Actualizar a última versión
34
+ claude-hooks update
35
+
36
+ # Desinstalar hooks
37
+ claude-hooks uninstall
38
+
39
+ # Ver estado actual
40
+ claude-hooks status
41
+
42
+ # Desactivar temporalmente
43
+ claude-hooks disable
44
+
45
+ # Reactivar hooks
46
+ claude-hooks enable
47
+ ```
48
+
49
+ ### 💻 Flujos de Commit
50
+
51
+ ```bash
52
+ # Commit con análisis de código
53
+ git commit -m "feat: nueva funcionalidad"
54
+
55
+ # Generar mensaje de commit automático
56
+ git commit -m "auto"
57
+
58
+ # Saltar análisis (emergencias)
59
+ git commit --no-verify -m "hotfix: corrección urgente"
60
+
61
+ # Modificar último commit
62
+ git commit --amend
63
+ ```
64
+
65
+ ### 🚫 Exclusión de Código del Análisis
66
+
67
+ ```java
68
+ // SKIP-ANALYSIS
69
+ private String legacyCode = "no analizar siguiente línea";
70
+
71
+ // SKIP_ANALYSIS_BLOCK
72
+ public void methodToIgnore() {
73
+ // Todo este bloque será ignorado
74
+ String oldCode = "legacy";
75
+ }
76
+ // SKIP_ANALYSIS_BLOCK
77
+ ```
78
+
79
+ ### 🔧 Configuración Avanzada
80
+
81
+ ```bash
82
+ # Archivos de configuración
83
+ .claude/
84
+ ├── CLAUDE_PRE_COMMIT_SONAR.md # Personalizar criterios
85
+ ├── CLAUDE_ANALYSIS_PROMPT_SONAR.md # Modificar prompt
86
+ └── settings.local.json # Configuración local
87
+
88
+ # Variables de entorno
89
+ export CLAUDE_ANALYSIS_MODE=sonarqube # Modo de análisis
90
+ export CLAUDE_DEBUG=true # Debug detallado
91
+ ```
92
+
93
+ ### 🎯 Casos de Uso Específicos
94
+
95
+ ```bash
96
+ # Desarrollo local de claude-hooks
97
+ cd /path/to/claude-git-hooks
98
+ npm link
99
+ cd /path/to/your-project
100
+ claude-hooks install --force --skip-auth
101
+
102
+ # Preparar PR hacia develop
103
+ git checkout -b feature/nueva-funcionalidad
104
+ # ... hacer cambios ...
105
+ git add .
106
+ git commit -m "feat: implementar nueva funcionalidad"
107
+ claude-hooks analyze-diff develop # Genera título, descripción y tests
108
+
109
+ # Resolver issues bloqueantes
110
+ git commit -m "fix: resolver issues"
111
+ # Si falla, ver claude_resolution_prompt.md generado
112
+ # Copiar contenido y pegar en Claude para obtener solución
113
+ ```
114
+
115
+ ### ⚡ Tips y Trucos
116
+
117
+ 1. **Mensaje automático**: Usa `"auto"` como mensaje para que Claude lo genere
118
+ 2. **Skip auth**: Usa `--skip-auth` en CI/CD o desarrollo local
119
+ 3. **Force install**: Usa `--force` para reinstalar sin confirmación
120
+ 4. **Debug**: Activa `CLAUDE_DEBUG=true` para ver detalles completos
121
+ 5. **Archivos grandes**: Se omiten automáticamente archivos > 100KB
122
+ 6. **Límite de archivos**: Máximo 10 archivos por commit
16
123
 
17
124
  ## 🔧 Configuración Previa Importante
18
125
 
19
- ### 1. Armonización de Line Endings (EOL)
126
+ ### 1. Armonización de Line Endings (EOL) -- Automatizada
20
127
 
21
128
  Debido a que Claude CLI corre en WSL y el desarrollo puede hacerse en Windows, es crucial configurar correctamente los line endings para evitar que los archivos de hooks se corrompan:
22
129
 
@@ -53,8 +160,6 @@ git config --global credential.helper store
53
160
 
54
161
  ## 🚀 Instalación
55
162
 
56
- ### Paquete NPM Global (Recomendado)
57
-
58
163
  **IMPORTANTE**: Claude CLI corre en WSL, por lo que toda la instalación y uso de git debe hacerse desde la terminal WSL.
59
164
 
60
165
  ```bash
@@ -80,35 +185,6 @@ El comando `claude-hooks install` ahora incluye:
80
185
  - `--force`: Reinstala aunque los hooks ya existan
81
186
  - `--skip-auth`: Omite la verificación de autenticación de Claude (útil para CI/CD)
82
187
 
83
- #### Añadir como Dependencia de Desarrollo
84
-
85
- ```bash
86
- # Instalar como devDependency
87
- npm install --save-dev claude-git-hooks
88
- ```
89
-
90
- Luego añade esto a tu `package.json`:
91
-
92
- ```json
93
- {
94
- "scripts": {
95
- "postinstall": "claude-hooks install"
96
- },
97
- "devDependencies": {
98
- "claude-git-hooks": "^1.2.0"
99
- }
100
- }
101
- ```
102
-
103
- ## 🤖 Características
104
-
105
- **✨ Auto-actualización**: Verifica automáticamente si hay nuevas versiones disponibles antes de cada commit y ofrece actualizar con un simple prompt interactivo.
106
-
107
- **Hooks disponibles**:
108
-
109
- - `pre-commit`: Análisis de código con Claude (solo archivos Java/config) con verificación automática de versión
110
- - `prepare-commit-msg`: Generación automática de mensajes de commit
111
-
112
188
  ## 📁 Gestión de Archivos
113
189
 
114
190
  ### Archivos creados durante la instalación
@@ -119,12 +195,9 @@ El comando `claude-hooks install` crea los siguientes archivos y directorios:
119
195
  2. **`.git/hooks/prepare-commit-msg`** - Hook de generación de mensajes
120
196
  3. **`.git/hooks/check-version.sh`** - Script de verificación de versión
121
197
  4. **`.claude/`** - Directorio para archivos de configuración
122
- - `CLAUDE_PRE_COMMIT.md` - Pautas de evaluación estándar
123
198
  - `CLAUDE_PRE_COMMIT_SONAR.md` - Pautas de evaluación SonarQube
124
- - `CLAUDE_ANALYSIS_PROMPT.md` - Template de prompt para análisis estándar
125
199
  - `CLAUDE_ANALYSIS_PROMPT_SONAR.md` - Template de prompt para análisis SonarQube
126
200
  - `CLAUDE_RESOLUTION_PROMPT.md` - Template para prompt de resolución AI
127
- 5. **`.claude-analysis-mode`** - Archivo de preferencia de modo (creado al primer uso)
128
201
 
129
202
  ### Actualización automática de .gitignore
130
203
 
@@ -133,9 +206,9 @@ Durante la instalación, Claude Hooks actualiza automáticamente tu `.gitignore`
133
206
  ```gitignore
134
207
  # Claude Git Hooks
135
208
  .claude/
136
- .claude-analysis-mode
137
209
  debug-claude-response.json
138
210
  claude_resolution_prompt.md
211
+ .claude-pr-analysis.json
139
212
  ```
140
213
 
141
214
  Esto asegura que:
@@ -155,26 +228,19 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
155
228
  - Solo analiza: Java, XML, properties, yml, yaml
156
229
  - Omite archivos mayores a 100KB
157
230
  - Límite de 10 archivos por commit
158
- 3. **Modos de análisis disponibles**:
159
- - **Estándar**: Formato clásico con score y recomendaciones detalladas
160
- - **SonarQube**: Simula salida de SonarQube con Quality Gate, métricas y clasificación de issues
161
- 4. **Construye prompt inteligente**:
231
+ 3. **Construye prompt inteligente**:
162
232
  - Usa template de prompt desde `.claude/CLAUDE_ANALYSIS_PROMPT*.md`
163
233
  - Lee las pautas desde `.claude/CLAUDE_PRE_COMMIT*.md`
164
234
  - Incluye el diff completo para archivos nuevos
165
235
  - Muestra solo cambios para archivos existentes
166
- 5. **Envía a Claude CLI para revisión**
167
- 6. **Procesa respuesta JSON estructurada**:
236
+ 4. **Envía a Claude CLI para revisión**
237
+ 5. **Procesa respuesta JSON estructurada**:
168
238
  - blockingIssues siempre como objetos con localización precisa
169
- - En modo estándar: evalúa `approved`, `score`, `recommendations`
170
- - En modo SonarQube: verifica `QUALITY_GATE`, muestra métricas y issues por severidad
171
- 7. **Decisión final**:
239
+ - verifica `QUALITY_GATE`, muestra métricas y issues por severidad
240
+ 6. **Decisión final**:
172
241
  - Si hay problemas críticos → genera prompt AI de resolución y bloquea commit
173
242
  - Si todo está bien → commit procede
174
-
175
- #### 🤖 Generación de Prompt de Resolución AI
176
-
177
- Cuando se detectan problemas críticos:
243
+ 7. **Generación de Prompt de Resolución AI** (opcional): Cuando se detectan problemas críticos:
178
244
 
179
245
  - Se genera automáticamente un archivo `claude_resolution_prompt.md`
180
246
  - Contiene información estructurada y AI-friendly de todos los issues
@@ -198,42 +264,20 @@ Cuando se detectan problemas críticos:
198
264
 
199
265
  ### Características adicionales
200
266
 
267
+ - **Generación de información para Pull Requests**: `claude-hooks analyze-diffs {branch}` para comparar rama local con otra rama, propone nombre para rama actual, título y detalles para pull request, da tips para verificar trabajo. Este comando genera automáticamente:
268
+ - 📝 Título de PR conciso (máx. 72 caracteres)
269
+ - 📄 Descripción detallada con markdown
270
+ - 🌿 Nombre de rama sugerido (formato: tipo/descripcion)
271
+ - 📋 Tipo de cambio (feature/fix/refactor/docs/test/chore)
272
+ - ⚠️ Indicador de breaking changes
273
+ - 🧪 Notas de testing recomendado
274
+ - 📝 Archivo `.claude-pr-analysis.json`
201
275
  - **Auto-actualización**: Verificación automática de versiones antes de cada commit con prompt interactivo para actualizar
202
276
  - **Comando update**: `claude-hooks update` para actualizar manualmente a la última versión
203
277
  - **Modo debug**: `DEBUG=1 git commit` guarda respuestas en `debug-claude-response.json`
204
- - **Configuración persistente**: Guarda preferencias en `.claude-analysis-mode`
278
+ - **Análisis de PR**: Nuevo comando `analyze-diff` para generar información de Pull Requests
205
279
  - **Validación de dependencias**: Verifica que Claude CLI esté autenticado antes de ejecutar
206
-
207
- ## 🛠️ Uso
208
-
209
- **IMPORTANTE**: Todos los comandos git deben ejecutarse desde WSL.
210
-
211
- ### Casos de uso de commits
212
-
213
- ```bash
214
- # Desde WSL
215
- git add .
216
-
217
- # 1. Mensaje manual + análisis bloqueante
218
- git commit -m "feat: nueva funcionalidad"
219
-
220
- # 2. Mensaje automático + análisis bloqueante
221
- git commit -m "auto" # Claude generará el mensaje automáticamente
222
-
223
- # 3. Mensaje manual sin análisis
224
- git commit --no-verify -m "fix: corrección urgente"
225
-
226
- # 4. Mensaje automático sin análisis
227
- git commit --no-verify -m "auto"
228
- ```
229
-
230
- Claude analizará los cambios y generará un mensaje de commit siguiendo las convenciones (feat, fix, docs, etc.).
231
-
232
- **⚠️ Si la generación automática falla**: El commit se cancelará completamente. Simplemente ejecuta `git commit -m "tu mensaje"` manualmente.
233
-
234
- ### Excluir código del análisis con SKIP-ANALYSIS
235
-
236
- Puedes excluir código específico del análisis usando comentarios `// SKIP-ANALYSIS`:
280
+ - **Exclusión de código del análisis con SKIP-ANALYSIS**: Puedes excluir código específico del análisis usando comentarios `// SKIP-ANALYSIS`:
237
281
 
238
282
  ```java
239
283
  // Excluir una sola línea
@@ -241,180 +285,15 @@ Puedes excluir código específico del análisis usando comentarios `// SKIP-ANA
241
285
  @Autowired private LegacyService legacyService; // Esta línea no será analizada
242
286
 
243
287
  // Excluir un bloque de código
244
- // SKIP-ANALYSIS
288
+ // SKIP-ANALYSIS_BLOCK
245
289
  @Deprecated
246
290
  public void methodWithKnownIssues() {
247
291
  // Código legacy que no queremos que sea analizado
248
292
  System.out.println("Debug temporal");
249
293
  }
250
- // SKIP-ANALYSIS
294
+ // SKIP-ANALYSIS_BLOCK
251
295
  ```
252
296
 
253
- **Nota**: El código entre comentarios `SKIP-ANALYSIS` no será enviado a Claude para su análisis.
254
-
255
- ### Modos de análisis 📊
256
-
257
- Puedes elegir entre dos formatos de análisis:
258
-
259
- #### 🎯 Configurar Modo (Recomendado)
260
-
261
- ```bash
262
- # Cambiar a modo SonarQube (métricas y quality gate)
263
- claude-hooks set-mode sonar
264
-
265
- # Cambiar a modo estándar (score y recomendaciones)
266
- claude-hooks set-mode standard
267
-
268
- # Ver modo actual
269
- claude-hooks status
270
- ```
271
-
272
- #### 🔧 Variable de Entorno (Temporal)
273
-
274
- ```bash
275
- # Sobrescribir temporalmente el modo configurado
276
- export CLAUDE_ANALYSIS_MODE=sonar
277
- git commit -m "mensaje"
278
-
279
- # Volver al modo configurado
280
- unset CLAUDE_ANALYSIS_MODE
281
- ```
282
-
283
- #### 📋 Diferencias entre Modos
284
-
285
- **Modo Estándar**:
286
-
287
- - Análisis con puntuación del 1-10
288
- - Recomendaciones detalladas por categoría
289
- - Formato tradicional fácil de leer
290
-
291
- **Modo SonarQube**:
292
-
293
- - Quality Gate (PASSED/FAILED)
294
- - Métricas: Reliability, Security, Maintainability
295
- - Issues clasificados por severidad (Blocker, Critical, Major, Minor, Info)
296
- - Security hotspots
297
-
298
- #### 🔄 Cambio de Modo Interactivo
299
-
300
- ```bash
301
- # Sin parámetros muestra ayuda interactiva
302
- claude-hooks set-mode
303
- ```
304
-
305
- ### Modo debug
306
-
307
- ```bash
308
- # Desde WSL
309
- DEBUG=1 git commit -m "mensaje"
310
- ```
311
-
312
- ## 📊 Formato de Respuesta
313
-
314
- Claude responde con un JSON estructurado que incluye:
315
-
316
- - `approved`: Si el commit es aprobado (boolean)
317
- - `score`: Puntuación del 1-10 (integer)
318
- - `blockingIssues`: Array de objetos con problemas críticos:
319
- - `description`: Descripción del problema
320
- - `file`: Archivo afectado
321
- - `line`: Línea del problema
322
- - `method`: Método o clase afectada
323
- - `severity`: Severidad (critical, high, etc.)
324
- - `recommendations`: Array de strings con sugerencias no bloqueantes
325
- - `details`: Objeto con comentarios por categoría (security, performance, etc.)
326
-
327
- ### Ejemplos de Respuestas con Problemas Críticos
328
-
329
- #### Modo Estándar - Commit Bloqueado
330
-
331
- ```json
332
- {
333
- "approved": false,
334
- "score": 3,
335
- "blockingIssues": [
336
- {
337
- "description": "SQL Injection vulnerability: concatenación directa de strings en query",
338
- "file": "src/main/java/UserRepository.java",
339
- "line": 45,
340
- "method": "findUserByName",
341
- "severity": "critical"
342
- },
343
- {
344
- "description": "Posible NullPointerException: variable 'user' no validada",
345
- "file": "src/main/java/UserService.java",
346
- "line": 78,
347
- "method": "processUser",
348
- "severity": "high"
349
- }
350
- ],
351
- "recommendations": [
352
- "Usar PreparedStatement en lugar de concatenación de strings",
353
- "Agregar validación de null antes de acceder a propiedades"
354
- ]
355
- }
356
- ```
357
-
358
- #### Modo SonarQube - Quality Gate Failed
359
-
360
- ```json
361
- {
362
- "QUALITY_GATE": "FAILED",
363
- "approved": false,
364
- "score": 4,
365
- "metrics": {
366
- "reliability": "D",
367
- "security": "E",
368
- "maintainability": "C"
369
- },
370
- "issues": {
371
- "blocker": 1,
372
- "critical": 2,
373
- "major": 3,
374
- "minor": 1
375
- },
376
- "blockingIssues": [
377
- {
378
- "description": "Security Hotspot: Hardcoded credentials detected",
379
- "file": "src/main/resources/application.yml",
380
- "line": 23,
381
- "method": "datasource.password",
382
- "severity": "blocker"
383
- },
384
- {
385
- "description": "Resource leak: Connection not closed in finally block",
386
- "file": "src/main/java/DatabaseUtil.java",
387
- "line": 112,
388
- "method": "executeQuery",
389
- "severity": "critical"
390
- }
391
- ],
392
- "details": [
393
- {
394
- "severity": "BLOCKER",
395
- "type": "VULNERABILITY",
396
- "file": "src/main/resources/application.yml",
397
- "line": 23,
398
- "message": "Never store passwords in plain text",
399
- "rule": "java:S2068"
400
- }
401
- ]
402
- }
403
- ```
404
-
405
- Cuando se detectan estos problemas críticos, se genera automáticamente un archivo `claude_resolution_prompt.md` con toda la información necesaria para que otra instancia de Claude pueda resolver los issues de forma eficiente.
406
-
407
- ## 🔄 Actualización y Gestión
408
-
409
- ### Actualizar a la última versión
410
-
411
- ```bash
412
- # Actualizar manualmente a la última versión
413
- claude-hooks update
414
- ```
415
-
416
- 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.
417
-
418
297
  ### Desactivar/Activar hooks
419
298
 
420
299
  ```bash
@@ -438,103 +317,26 @@ claude-hooks status
438
317
 
439
318
  ## ⚙️ Configuración
440
319
 
441
- ### Variables de entorno disponibles
442
-
443
- - **`CLAUDE_ANALYSIS_MODE`**: Selecciona el modo de análisis
444
-
445
- - Valores: `"standard"` o `"sonar"`
446
- - Ejemplo: `CLAUDE_ANALYSIS_MODE=sonar git commit -m "mensaje"`
447
- - Sobrescribe la preferencia guardada en `.claude-analysis-mode`
448
-
449
- - **`DEBUG`**: Activa el modo debug
450
- - Valores: `1` para activar
451
- - Ejemplo: `DEBUG=1 git commit -m "mensaje"`
452
- - Guarda las respuestas de Claude en `debug-claude-response.json`
453
-
454
- ### Variables modificables en los archivos de hooks
320
+ ### Scripts
455
321
 
456
322
  En el archivo `pre-commit`:
457
323
 
458
324
  - **`MAX_FILE_SIZE`**: Tamaño máximo de archivo a analizar (default: 100KB)
459
325
  - **`MAX_FILES`**: Número máximo de archivos por commit (default: 10)
460
326
  - **`CLAUDE_CLI`**: Comando de Claude CLI (default: "claude")
461
- - **`GUIDELINES_FILE`**: Archivo de pautas para modo estándar (default: ".claude/CLAUDE_PRE_COMMIT.md")
462
- - **`GUIDELINES_FILE_SONAR`**: Archivo de pautas para modo SonarQube (default: ".claude/CLAUDE_PRE_COMMIT_SONAR.md")
327
+ - **`GUIDELINES_FILE`**: Archivo de pautas (default: ".claude/CLAUDE_PRE_COMMIT_SONAR.md")
463
328
 
464
329
  En el archivo `prepare-commit-msg`:
465
330
 
466
331
  - **`MAX_FILE_SIZE`**: Tamaño máximo para incluir diff completo (default: 100KB)
467
332
  - **`CLAUDE_CLI`**: Comando de Claude CLI (default: "claude")
468
333
 
469
- ## 🐛 Troubleshooting
470
-
471
- ### "Claude CLI no está instalado"
472
-
473
- ```bash
474
- # Desde WSL
475
- npm install -g @anthropic-ai/claude-cli
476
- claude auth login
477
- ```
478
-
479
- ### "No se recibió respuesta JSON válida"
480
-
481
- - Verifica que Claude CLI esté autenticado en WSL
482
- - Ejecuta en modo DEBUG para ver la respuesta completa
483
- - Revisa que el archivo de pautas esté bien formateado
484
-
485
- ### El hook no se ejecuta
486
-
487
- - Verifica que estés ejecutando git desde WSL
488
- - Verifica permisos: `ls -la .git/hooks/pre-commit`
489
- - Debe mostrar permisos de ejecución (-rwxr-xr-x)
334
+ ### Pautas de Evaluación
490
335
 
491
- ### Problemas con line endings
492
-
493
- - Si ves errores de "^M" o caracteres extraños:
494
- ```bash
495
- # En WSL
496
- git config core.autocrlf input
497
- ```
498
-
499
- ### Los hooks se vacían o corrompen
500
-
501
- Este problema suele ocurrir por conflictos de configuración de line endings:
502
-
503
- 1. **Verifica configuraciones**:
504
-
505
- ```bash
506
- git config --local core.autocrlf # Debe ser 'input'
507
- git config --global core.autocrlf # Debe ser 'input'
508
- ```
509
-
510
- 2. **Si están diferentes, corrige**:
511
-
512
- ```bash
513
- git config --local core.autocrlf input
514
- ```
515
-
516
- 3. **Restaura los hooks**:
517
- ```bash
518
- ./git-hooks/setup-wsl.sh --sync
519
- ```
520
-
521
- ### Credenciales no funcionan en WSL
522
-
523
- - Las credenciales de Windows no se comparten automáticamente con WSL
524
- - Reconfigura tus credenciales git en WSL
525
-
526
- ## 📝 Personalización
527
-
528
- ### Archivos de Configuración en `.claude/`
529
-
530
- #### Pautas de Evaluación
531
-
532
- - **`CLAUDE_PRE_COMMIT.md`** - Criterios de evaluación para modo estándar
533
336
  - **`CLAUDE_PRE_COMMIT_SONAR.md`** - Criterios para modo SonarQube
534
337
 
535
- #### Templates de Prompts
338
+ ### Templates de Prompts
536
339
 
537
- - **`CLAUDE_ANALYSIS_PROMPT.md`** - Estructura del prompt de análisis estándar
538
340
  - **`CLAUDE_ANALYSIS_PROMPT_SONAR.md`** - Estructura del prompt SonarQube
539
341
  - **`CLAUDE_RESOLUTION_PROMPT.md`** - Template para generar prompts de resolución
540
342
 
@@ -544,33 +346,9 @@ Todos estos archivos son personalizables y específicos de tu proyecto. Puedes:
544
346
  - Ajustar la estructura de los prompts para obtener respuestas más precisas
545
347
  - Personalizar el formato de salida del prompt de resolución
546
348
 
547
- ## 🔄 Arquitectura del Sistema
548
-
549
- ```
550
- WSL Terminal
551
-
552
- ├─→ git add/commit
553
-
554
- └─→ .git/hooks/pre-commit
555
-
556
- ├─→ Lee archivos modificados
557
- ├─→ Lee CLAUDE_PRE_COMMIT.md
558
- ├─→ Construye prompt
559
-
560
- └─→ Claude CLI
561
-
562
- └─→ Respuesta JSON
563
-
564
- ├─→ ✅ Approved → Commit procede
565
- └─→ ❌ Rejected → Commit bloqueado
566
- ```
567
-
568
- ## 📌 Notas Importantes
349
+ ## 🐛 Troubleshooting
569
350
 
570
- 1. **Todo en WSL**: Claude CLI solo funciona en WSL, por lo que todos los comandos git deben ejecutarse desde ahí
571
- 2. **Line Endings**: La configuración de `core.autocrlf` es crítica para evitar problemas entre Windows y Linux
572
- 3. **Credenciales**: Necesitarás reconfigurar tus credenciales git en WSL
573
- 4. **Performance**: La revisión puede tardar unos segundos dependiendo del tamaño de los cambios
351
+ No hay... esto es la perfección hecha código.
574
352
 
575
353
  ## 🔧 Desarrollo y Contribución
576
354
 
@@ -579,19 +357,25 @@ WSL Terminal
579
357
  ```
580
358
  claude-git-hooks/
581
359
  ├── bin/
582
- │ └── claude-hooks # CLI principal con verificación completa
360
+ │ └── claude-hooks # CLI principal con verificación completa
583
361
  ├── templates/
584
- │ ├── pre-commit # Hook de análisis de código
585
- │ ├── prepare-commit-msg # Hook de generación de mensajes
586
- │ ├── CLAUDE_PRE_COMMIT.md # Pautas estándar
587
- └── CLAUDE_PRE_COMMIT_SONAR.md # Pautas SonarQube
588
- ├── .claude/ # Directorio creado en el repo del usuario
589
- ├── CLAUDE_PRE_COMMIT.md # Pautas copiadas aquí durante la instalación
590
- │ └── CLAUDE_PRE_COMMIT_SONAR.md
591
- ├── package.json # Configuración NPM
592
- ├── README.md # Este archivo
593
- ├── CHANGELOG.md # Historial de versiones
594
- └── PUBLISH.md # Guía de publicación
362
+ │ ├── pre-commit # Hook de análisis de código
363
+ │ ├── prepare-commit-msg # Hook de generación de mensajes
364
+ │ ├── check-version.sh # Script de verificación de versión
365
+ ├── CLAUDE_PRE_COMMIT_SONAR.md # Pautas SonarQube para pre commit
366
+ ├── CLAUDE_ANALYSIS_PROMPT_SONAR.md # Template de prompt para análisis
367
+ └── CLAUDE_RESOLUTION_PROMPT.md # Template para resolución de issues
368
+ ├── .claude/ # Directorio de configuración local (gitignore)
369
+ │ └── settings.local.json # Configuración local del usuario
370
+ ├── package.json # Configuración NPM
371
+ ├── package-lock.json # Lock file de NPM
372
+ ├── README.md # Este archivo
373
+ ├── README-NPM.md # Documentación para publicación NPM
374
+ ├── CHANGELOG.md # Historial de versiones
375
+ ├── PUBLISH.md # Guía de publicación
376
+ ├── CLAUDE_PRE_COMMIT_SONAR.md # Pautas de evaluación (legacy)
377
+ ├── pre-commit # Hook principal (legacy)
378
+ └── .gitignore # Archivos ignorados por git
595
379
  ```
596
380
 
597
381
  ### Configuración del Entorno de Desarrollo
@@ -624,23 +408,18 @@ Los hooks están en `templates/`:
624
408
  #### 2. Probar Localmente
625
409
 
626
410
  ```bash
627
- # Después de modificar archivos
411
+ # Después de modificar archivos, repo de claude-hooks
628
412
  npm link
629
413
 
630
414
  # En un repo de prueba
631
- claude-hooks install --force # Fuerza reinstalación
632
-
633
- # Probar funcionalidad
634
- git add .
635
- git commit -m "auto" # Probar generación automática
636
- git commit -m "test" # Probar análisis
415
+ claude-hooks install --force # Fuerza reinstalación, luego probar lo que se desee
637
416
  ```
638
417
 
639
418
  #### 3. Actualizar Documentación
640
419
 
641
420
  - `README.md` - Documentación principal
421
+ - `CHANGELOG.md` - Documentación principal
642
422
  - `README-NPM.md` - Para usuarios de NPM
643
- - `templates/CLAUDE_PRE_COMMIT*.md` - Pautas de evaluación
644
423
 
645
424
  #### 4. Versioning y Publicación
646
425
 
@@ -652,68 +431,4 @@ npm version major # 1.0.0 -> 2.0.0
652
431
 
653
432
  # Publicar nueva versión
654
433
  npm publish
655
-
656
- # Tag en git
657
- git push --tags
658
434
  ```
659
-
660
- ### Debugging
661
-
662
- #### Modo Debug
663
-
664
- ```bash
665
- # Activar debug en hooks
666
- DEBUG=1 git commit -m "test"
667
-
668
- # Ver logs del CLI
669
- claude-hooks install --debug
670
- ```
671
-
672
- #### Logs Útiles
673
-
674
- - `debug-claude-response.json` - Respuestas de Claude en modo debug
675
- - `~/.npm/_logs/` - Logs de npm install
676
- - `.git/hooks/` - Verificar que hooks están instalados
677
-
678
- ### Testing
679
-
680
- #### Test Manual
681
-
682
- ```bash
683
- # 1. Crear repo de prueba
684
- mkdir test-repo && cd test-repo
685
- git init
686
-
687
- # 2. Instalar hooks
688
- claude-hooks install
689
-
690
- # 3. Crear archivos de prueba
691
- echo 'public class Test {}' > Test.java
692
- git add .
693
-
694
- # 4. Probar análisis
695
- git commit -m "test: nueva clase"
696
-
697
- # 5. Probar generación automática
698
- echo 'public void newMethod() {}' >> Test.java
699
- git add .
700
- git commit -m "auto"
701
- ```
702
-
703
- #### Casos de Prueba
704
-
705
- - ✅ Análisis de código Java
706
- - ✅ Generación automática de mensajes
707
- - ✅ Modo SonarQube
708
- - ✅ Archivos grandes (>100KB)
709
- - ✅ Commits sin archivos Java
710
- - ✅ Enable/disable hooks
711
- - ✅ Modo debug
712
-
713
- ### Contribuir
714
-
715
- 1. **Fork** el repositorio
716
- 2. **Crear branch** para tu feature: `git checkout -b feature/nueva-funcionalidad`
717
- 3. **Commit** tus cambios: `git commit -m "feat: nueva funcionalidad"`
718
- 4. **Push** al branch: `git push origin feature/nueva-funcionalidad`
719
- 5. **Abrir Pull Request**
package/bin/claude-hooks CHANGED
@@ -447,9 +447,9 @@ async function install(args) {
447
447
  console.log(' git commit --no-verify # Omite el análisis completamente');
448
448
  console.log('\nExcluir código del análisis:');
449
449
  console.log(' // SKIP-ANALYSIS # Excluye la siguiente línea');
450
- console.log(' // SKIP-ANALYSIS # Entre dos comentarios excluye el bloque');
450
+ console.log(' // SKIP_ANALYSIS_BLOCK # Excluye bloque hasta encontrar otro igual');
451
451
  console.log(' ...código excluido...');
452
- console.log(' // SKIP-ANALYSIS');
452
+ console.log(' // SKIP_ANALYSIS_BLOCK');
453
453
  console.log('\nPara más opciones: claude-hooks --help');
454
454
  }
455
455
 
@@ -638,9 +638,9 @@ function updateGitignore() {
638
638
  const claudeEntries = [
639
639
  '# Claude Git Hooks',
640
640
  '.claude/',
641
- '.claude-analysis-mode',
642
641
  'debug-claude-response.json',
643
- 'claude_resolution_prompt.md'
642
+ 'claude_resolution_prompt.md',
643
+ '.claude-pr-analysis.json',
644
644
  ];
645
645
 
646
646
  let gitignoreContent = '';
@@ -794,6 +794,258 @@ function disable(hookName) {
794
794
  });
795
795
  }
796
796
 
797
+ // Comando analyze-diff
798
+ function analyzeDiff(args) {
799
+ if (!checkGitRepo()) {
800
+ error('No estás en un repositorio Git.');
801
+ return;
802
+ }
803
+
804
+ const currentBranch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
805
+
806
+ if (!currentBranch) {
807
+ error('No estás en una rama válida.');
808
+ return;
809
+ }
810
+
811
+ let baseBranch, compareWith, contextDescription;
812
+
813
+ if (args[0]) {
814
+ // Caso con argumento: comparar rama actual vs rama especificada
815
+ baseBranch = args[0];
816
+ compareWith = `${baseBranch}...HEAD`;
817
+ contextDescription = `${currentBranch} vs ${baseBranch}`;
818
+
819
+ // Verificar que la rama base existe
820
+ try {
821
+ execSync(`git rev-parse --verify ${baseBranch}`, { stdio: 'ignore' });
822
+ } catch (e) {
823
+ error(`La rama ${baseBranch} no existe.`);
824
+ return;
825
+ }
826
+ } else {
827
+ // Caso sin argumento: comparar local vs remoto
828
+ try {
829
+ // Obtener la rama remota tracked
830
+ const remoteBranch = execSync(`git rev-parse --abbrev-ref ${currentBranch}@{upstream}`, { encoding: 'utf8' }).trim();
831
+
832
+ // Actualizar referencias remotas
833
+ execSync('git fetch', { stdio: 'ignore' });
834
+
835
+ baseBranch = remoteBranch;
836
+ compareWith = `HEAD..${remoteBranch}`;
837
+ contextDescription = `cambios locales sin pushear en ${currentBranch}`;
838
+
839
+ info(`Comparando cambios locales vs remoto: ${remoteBranch}`);
840
+ } catch (e) {
841
+ // Si no hay rama remota, usar develop como fallback
842
+ baseBranch = 'develop';
843
+ compareWith = `${baseBranch}...HEAD`;
844
+ contextDescription = `${currentBranch} vs ${baseBranch} (sin rama remota)`;
845
+
846
+ try {
847
+ execSync(`git rev-parse --verify ${baseBranch}`, { stdio: 'ignore' });
848
+ warning(`No hay rama remota configurada. Comparando con ${baseBranch}.`);
849
+ } catch (e2) {
850
+ baseBranch = 'main';
851
+ compareWith = `${baseBranch}...HEAD`;
852
+ contextDescription = `${currentBranch} vs ${baseBranch} (fallback)`;
853
+
854
+ try {
855
+ execSync(`git rev-parse --verify ${baseBranch}`, { stdio: 'ignore' });
856
+ warning(`No hay develop ni rama remota. Comparando con main.`);
857
+ } catch (e3) {
858
+ error('No se pudo encontrar una rama de comparación válida.');
859
+ return;
860
+ }
861
+ }
862
+ }
863
+ }
864
+
865
+ info(`Analizando: ${contextDescription}...`);
866
+
867
+ // Obtener los archivos modificados
868
+ let diffFiles;
869
+ try {
870
+ // Para cambios locales sin pushear, invertir la comparación
871
+ if (!args[0] && compareWith.includes('HEAD..')) {
872
+ diffFiles = execSync(`git diff ${compareWith} --name-only`, { encoding: 'utf8' }).trim();
873
+ } else {
874
+ diffFiles = execSync(`git diff ${compareWith} --name-only`, { encoding: 'utf8' }).trim();
875
+ }
876
+
877
+ if (!diffFiles) {
878
+ // Verificar si hay cambios staged o unstaged
879
+ const stagedFiles = execSync('git diff --cached --name-only', { encoding: 'utf8' }).trim();
880
+ const unstagedFiles = execSync('git diff --name-only', { encoding: 'utf8' }).trim();
881
+
882
+ if (stagedFiles || unstagedFiles) {
883
+ warning('No hay diferencias con el remoto, pero tienes cambios locales sin commitear.');
884
+ console.log('Cambios staged:', stagedFiles || 'ninguno');
885
+ console.log('Cambios unstaged:', unstagedFiles || 'ninguno');
886
+ } else {
887
+ success('✅ No hay diferencias. Tu rama está sincronizada.');
888
+ }
889
+ return;
890
+ }
891
+ } catch (e) {
892
+ error('Error al obtener las diferencias: ' + e.message);
893
+ return;
894
+ }
895
+
896
+ // Obtener el diff completo
897
+ let fullDiff, commits;
898
+ try {
899
+ if (!args[0] && compareWith.includes('HEAD..')) {
900
+ fullDiff = execSync(`git diff ${compareWith}`, { encoding: 'utf8' });
901
+ commits = execSync(`git log ${baseBranch}..HEAD --oneline`, { encoding: 'utf8' }).trim();
902
+ } else {
903
+ fullDiff = execSync(`git diff ${compareWith}`, { encoding: 'utf8' });
904
+ commits = execSync(`git log ${baseBranch}..HEAD --oneline`, { encoding: 'utf8' }).trim();
905
+ }
906
+ } catch (e) {
907
+ error('Error al obtener diff o commits: ' + e.message);
908
+ return;
909
+ }
910
+
911
+ // Crear el prompt para Claude
912
+ const tempDir = `/tmp/claude-analyze-${Date.now()}`;
913
+ fs.mkdirSync(tempDir, { recursive: true });
914
+
915
+ const promptFile = path.join(tempDir, 'prompt.txt');
916
+ const prompt = `Analiza los siguientes cambios. CONTEXTO: ${contextDescription}
917
+
918
+ Por favor genera:
919
+ 1. Un título de PR conciso y descriptivo (máximo 72 caracteres)
920
+ 2. Una descripción detallada del PR que incluya:
921
+ - Resumen de los cambios
922
+ - Motivación/contexto
923
+ - Tipo de cambio (feature/fix/refactor/docs/etc)
924
+ - Testing recomendado
925
+ 3. Un nombre de rama sugerido siguiendo el formato: tipo/descripcion-corta (ejemplo: feature/add-user-auth, fix/memory-leak)
926
+
927
+ IMPORTANTE: Si estos son cambios locales sin pushear, el nombre de rama sugerido debe ser para crear una nueva rama desde la actual.
928
+
929
+ Responde EXCLUSIVAMENTE con un JSON válido con esta estructura:
930
+ {
931
+ "prTitle": "título del PR",
932
+ "prDescription": "descripción detallada del PR con markdown",
933
+ "suggestedBranchName": "tipo/nombre-rama-sugerido",
934
+ "changeType": "feature|fix|refactor|docs|test|chore",
935
+ "breakingChanges": false,
936
+ "testingNotes": "notas sobre testing necesario"
937
+ }
938
+
939
+ === COMMITS ===
940
+ ${commits}
941
+
942
+ === ARCHIVOS MODIFICADOS ===
943
+ ${diffFiles}
944
+
945
+ === DIFF COMPLETO ===
946
+ ${fullDiff.substring(0, 50000)} ${fullDiff.length > 50000 ? '\n... (diff truncado)' : ''}`;
947
+
948
+ fs.writeFileSync(promptFile, prompt);
949
+
950
+ info('Enviando a Claude para análisis...');
951
+
952
+ try {
953
+ const response = execSync(`claude < "${promptFile}"`, { encoding: 'utf8', maxBuffer: 1024 * 1024 * 10 });
954
+
955
+ // Extraer el JSON de la respuesta
956
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
957
+ if (!jsonMatch) {
958
+ error('No se recibió una respuesta JSON válida de Claude.');
959
+ console.log('Respuesta completa:', response);
960
+ return;
961
+ }
962
+
963
+ let result;
964
+ try {
965
+ result = JSON.parse(jsonMatch[0]);
966
+ } catch (e) {
967
+ error('Error al parsear la respuesta JSON: ' + e.message);
968
+ console.log('JSON recibido:', jsonMatch[0]);
969
+ return;
970
+ }
971
+
972
+ // Mostrar los resultados
973
+ console.log('');
974
+ console.log('═══════════════════════════════════════════════════════════════');
975
+ console.log(' ANÁLISIS DE DIFERENCIAS ');
976
+ console.log('═══════════════════════════════════════════════════════════════');
977
+ console.log('');
978
+
979
+ console.log(`🔍 ${colors.blue}Contexto:${colors.reset} ${contextDescription}`);
980
+ console.log(`📊 ${colors.blue}Archivos modificados:${colors.reset} ${diffFiles.split('\n').length}`);
981
+ console.log('');
982
+
983
+ console.log(`📝 ${colors.green}Título del PR:${colors.reset}`);
984
+ console.log(` ${result.prTitle}`);
985
+ console.log('');
986
+
987
+ console.log(`🌿 ${colors.green}Nombre de rama sugerido:${colors.reset}`);
988
+ console.log(` ${result.suggestedBranchName}`);
989
+ console.log('');
990
+
991
+ console.log(`📋 ${colors.green}Tipo de cambio:${colors.reset} ${result.changeType}`);
992
+
993
+ if (result.breakingChanges) {
994
+ console.log(`⚠️ ${colors.yellow}Breaking Changes: SÍ${colors.reset}`);
995
+ }
996
+
997
+ console.log('');
998
+ console.log(`📄 ${colors.green}Descripción del PR:${colors.reset}`);
999
+ console.log('───────────────────────────────────────────────────────────────');
1000
+ console.log(result.prDescription);
1001
+ console.log('───────────────────────────────────────────────────────────────');
1002
+
1003
+ if (result.testingNotes) {
1004
+ console.log('');
1005
+ console.log(`🧪 ${colors.green}Notas de Testing:${colors.reset}`);
1006
+ console.log(result.testingNotes);
1007
+ }
1008
+
1009
+ // Guardar los resultados en un archivo con contexto
1010
+ const outputData = {
1011
+ ...result,
1012
+ context: {
1013
+ currentBranch,
1014
+ baseBranch,
1015
+ contextDescription,
1016
+ filesChanged: diffFiles.split('\n').length,
1017
+ timestamp: new Date().toISOString()
1018
+ }
1019
+ };
1020
+
1021
+ const outputFile = '.claude-pr-analysis.json';
1022
+ fs.writeFileSync(outputFile, JSON.stringify(outputData, null, 2));
1023
+ console.log('');
1024
+ info(`Resultados guardados en ${outputFile}`);
1025
+
1026
+ // Sugerencias contextuales
1027
+ console.log('');
1028
+ if (!args[0] && contextDescription.includes('cambios locales sin pushear')) {
1029
+ // Caso de cambios locales sin pushear
1030
+ console.log(`💡 ${colors.yellow}Para crear nueva rama con estos cambios:${colors.reset}`);
1031
+ console.log(` git checkout -b ${result.suggestedBranchName}`);
1032
+ console.log(` git push -u origin ${result.suggestedBranchName}`);
1033
+ } else if (currentBranch !== result.suggestedBranchName) {
1034
+ // Caso normal de comparación entre ramas
1035
+ console.log(`💡 ${colors.yellow}Para renombrar tu rama actual:${colors.reset}`);
1036
+ console.log(` git branch -m ${result.suggestedBranchName}`);
1037
+ }
1038
+
1039
+ console.log(`💡 ${colors.yellow}Tip:${colors.reset} Usa esta información para crear tu PR en GitHub.`);
1040
+
1041
+ } catch (e) {
1042
+ error('Error al ejecutar Claude: ' + e.message);
1043
+ } finally {
1044
+ // Limpiar archivos temporales
1045
+ fs.rmSync(tempDir, { recursive: true, force: true });
1046
+ }
1047
+ }
1048
+
797
1049
  // Comando status
798
1050
  function status() {
799
1051
  if (!checkGitRepo()) {
@@ -816,21 +1068,9 @@ function status() {
816
1068
  }
817
1069
  });
818
1070
 
819
- // Verificar modo de análisis actual
820
- console.log('\nModo de análisis:');
821
- const analysisMode = fs.existsSync('.claude-analysis-mode')
822
- ? fs.readFileSync('.claude-analysis-mode', 'utf8').trim()
823
- : 'standard (por defecto)';
824
-
825
- if (analysisMode === 'sonar') {
826
- info(`Modo actual: SonarQube`);
827
- } else {
828
- info(`Modo actual: Estándar`);
829
- }
830
-
831
1071
  // Verificar archivos de pautas
832
1072
  console.log('\nArchivos de pautas:');
833
- const guidelines = ['CLAUDE_PRE_COMMIT.md', 'CLAUDE_PRE_COMMIT_SONAR.md'];
1073
+ const guidelines = ['CLAUDE_PRE_COMMIT_SONAR.md'];
834
1074
  guidelines.forEach(guideline => {
835
1075
  const claudePath = path.join('.claude', guideline);
836
1076
  if (fs.existsSync(claudePath)) {
@@ -847,7 +1087,7 @@ function status() {
847
1087
  const gitignorePath = '.gitignore';
848
1088
  if (fs.existsSync(gitignorePath)) {
849
1089
  const gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
850
- const claudeIgnores = ['.claude/', '.claude-analysis-mode', 'debug-claude-response.json'];
1090
+ const claudeIgnores = ['.claude/', 'debug-claude-response.json', '.claude-pr-analysis.json'];
851
1091
  let allPresent = true;
852
1092
 
853
1093
  claudeIgnores.forEach(entry => {
@@ -873,28 +1113,6 @@ function setMode(mode) {
873
1113
  if (!checkGitRepo()) {
874
1114
  error('No estás en un repositorio Git.');
875
1115
  }
876
-
877
- const validModes = ['sonar'];
878
-
879
- if (!mode) {
880
- // Modo interactivo
881
- console.log('\nModo de análisis configurado:');
882
- console.log('SonarQube - Formato con métricas y quality gate');
883
- console.log('\nEjemplo de uso: claude-hooks set-mode sonar');
884
- return;
885
- }
886
-
887
- if (!validModes.includes(mode)) {
888
- error(`Modo inválido: ${mode}. Usa 'sonar'`);
889
- }
890
-
891
- // Guardar el modo
892
- fs.writeFileSync('.claude-analysis-mode', mode);
893
-
894
- if (mode === 'sonar') {
895
- success('Modo configurado: SonarQube');
896
- info('Los commits usarán formato SonarQube con métricas y quality gate');
897
- }
898
1116
  }
899
1117
 
900
1118
  // Función para comparar versiones usando el script compartido
@@ -993,8 +1211,8 @@ Comandos:
993
1211
  uninstall Desinstala los hooks del repositorio
994
1212
  enable [hook] Habilita hooks (todos o uno específico)
995
1213
  disable [hook] Deshabilita hooks (todos o uno específico)
996
- set-mode [standard|sonar] Cambia el modo de análisis
997
1214
  status Muestra el estado de los hooks
1215
+ analyze-diff [base] Analiza diferencias entre ramas y genera PR info
998
1216
  help Muestra esta ayuda
999
1217
 
1000
1218
  Hooks disponibles:
@@ -1005,11 +1223,10 @@ Ejemplos:
1005
1223
  claude-hooks install # Instala todos los hooks
1006
1224
  claude-hooks install --skip-auth # Instala sin verificar autenticación
1007
1225
  claude-hooks update # Actualiza a la última versión
1008
- claude-hooks set-mode sonar # Cambiar a modo SonarQube
1009
- claude-hooks set-mode standard # Cambiar a modo estándar
1010
1226
  claude-hooks disable pre-commit # Deshabilita solo pre-commit
1011
1227
  claude-hooks enable # Habilita todos los hooks
1012
1228
  claude-hooks status # Ver estado actual
1229
+ claude-hooks analyze-diff main # Analiza diferencias con main
1013
1230
 
1014
1231
  Casos de uso de commits:
1015
1232
  git commit -m "mensaje" # Mensaje manual + análisis bloqueante
@@ -1017,11 +1234,17 @@ Casos de uso de commits:
1017
1234
  git commit --no-verify -m "auto" # Mensaje automático sin análisis
1018
1235
  git commit --no-verify -m "msg" # Mensaje manual sin análisis
1019
1236
 
1237
+ Caso de uso analyze-diff:
1238
+ claude-hooks analyze-diff main # Analiza cambios vs main y genera:
1239
+ → Título PR: "feat: add user authentication module"
1240
+ → Descripción PR: "## Summary\n- Added JWT authentication..."
1241
+ → Rama sugerida: "feature/user-authentication"
1242
+
1020
1243
  Excluir código del análisis:
1021
1244
  // SKIP-ANALYSIS # Excluye la siguiente línea del análisis
1022
- // SKIP-ANALYSIS # Entre dos comentarios excluye el bloque
1245
+ // SKIP_ANALYSIS_BLOCK # Excluye bloque hasta encontrar otro igual
1023
1246
  ...código excluido...
1024
- // SKIP-ANALYSIS
1247
+ // SKIP_ANALYSIS_BLOCK
1025
1248
 
1026
1249
  Más información: https://github.com/pablorovito/claude-git-hooks
1027
1250
  `);
@@ -1048,12 +1271,12 @@ async function main() {
1048
1271
  case 'disable':
1049
1272
  disable(args[1]);
1050
1273
  break;
1051
- case 'set-mode':
1052
- setMode(args[1]);
1053
- break;
1054
1274
  case 'status':
1055
1275
  status();
1056
1276
  break;
1277
+ case 'analyze-diff':
1278
+ analyzeDiff(args.slice(1));
1279
+ break;
1057
1280
  case 'help':
1058
1281
  case '--help':
1059
1282
  case '-h':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-git-hooks",
3
- "version": "1.4.2",
3
+ "version": "1.5.1",
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": {
File without changes
File without changes
File without changes
File without changes
@@ -109,7 +109,6 @@ generate_resolution_prompt() {
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
- sed -i "s|{{ANALYSIS_MODE}}|sonar|g" "$RESOLUTION_FILE"
113
112
 
114
113
  # Crear archivo temporal para issues formateados
115
114
  local TEMP_ISSUES_FILE=$(mktemp)
@@ -149,18 +148,10 @@ generate_resolution_prompt() {
149
148
  echo
150
149
  }
151
150
 
152
- # Usar siempre modo SonarQube
153
- ANALYSIS_MODE="sonar"
154
-
155
151
  # Configurar archivos para modo SonarQube
156
152
  GUIDELINES_FILE=".claude/CLAUDE_PRE_COMMIT_SONAR.md"
157
153
  PROMPT_TEMPLATE=".claude/CLAUDE_ANALYSIS_PROMPT_SONAR.md"
158
- log "Usando modo de análisis: SonarQube"
159
154
 
160
- # Guardar preferencia si no existe
161
- if [ ! -f ".claude-analysis-mode" ]; then
162
- echo "sonar" > .claude-analysis-mode
163
- fi
164
155
 
165
156
  # Verificar que el template de prompt existe
166
157
  if [ ! -f "$PROMPT_TEMPLATE" ]; then
@@ -214,15 +205,20 @@ filter_skip_analysis() {
214
205
  local inside_skip_block=false
215
206
 
216
207
  while IFS= read -r line; do
217
- # Detectar inicio de bloque SKIP-ANALYSIS
208
+ # Detectar SKIP-ANALYSIS para línea única
218
209
  if echo "$line" | grep -q "// SKIP-ANALYSIS"; then
210
+ skip_next_line=true
211
+ continue
212
+ fi
213
+
214
+ # Detectar inicio/fin de bloque SKIP_ANALYSIS_BLOCK
215
+ if echo "$line" | grep -q "// SKIP_ANALYSIS_BLOCK"; then
219
216
  if [ "$inside_skip_block" = true ]; then
220
217
  # Fin del bloque
221
218
  inside_skip_block=false
222
219
  else
223
- # Inicio del bloque o línea única
220
+ # Inicio del bloque
224
221
  inside_skip_block=true
225
- skip_next_line=true
226
222
  fi
227
223
  continue
228
224
  fi
@@ -235,7 +231,6 @@ filter_skip_analysis() {
235
231
  # Si debemos saltar la siguiente línea (comentario único)
236
232
  if [ "$skip_next_line" = true ]; then
237
233
  skip_next_line=false
238
- inside_skip_block=false
239
234
  continue
240
235
  fi
241
236
 
@@ -337,10 +332,9 @@ if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
337
332
  BLOCKING_ISSUES=$(echo "$JSON_RESPONSE" | jq -r '.blockingIssues[].description' 2>/dev/null | sed '/^$/d')
338
333
  fi
339
334
 
340
- # Verificar si estamos en modo SonarQube
341
335
  QUALITY_GATE=$(echo "$JSON_RESPONSE" | jq -r '.QUALITY_GATE // ""' 2>/dev/null)
342
336
 
343
- if [ "$ANALYSIS_MODE" = "sonar" ] && [ -n "$QUALITY_GATE" ] && [ "$QUALITY_GATE" != "null" ]; then
337
+ if [ -n "$QUALITY_GATE" ] && [ "$QUALITY_GATE" != "null" ]; then
344
338
  # Mostrar resultados estilo SonarQube
345
339
  echo
346
340
  echo "╔════════════════════════════════════════════════════════════════════╗"
File without changes