claude-git-hooks 2.3.1 → 2.4.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,63 @@ 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
+ ## [2.4.0] - 2025-11-17
9
+
10
+ ### ⚠️ BREAKING CHANGES
11
+
12
+ - **Debug Mode** - Environment variable `DEBUG` no longer supported
13
+ - **What changed**: Removed `DEBUG` environment variable support from `lib/utils/logger.js`
14
+ - **Why**: Aligns with project philosophy "no environment variables" and provides better user experience
15
+ - **Migration**: Use `claude-hooks --debug true` instead of `DEBUG=1 git commit`
16
+ - **Alternative**: Set `"system": { "debug": true }` in `.claude/config.json`
17
+
18
+ ### 🔄 Changed
19
+
20
+ - **File Size Limit Increased** - Default `maxFileSize` increased from 100KB to 1MB
21
+ - **What changed**: `analysis.maxFileSize` now defaults to 1000000 (1MB) instead of 100000 (100KB)
22
+ - **Why**: Previous 100KB limit was too restrictive, rejected many legitimate source files
23
+ - **Files updated**:
24
+ - `lib/config.js:29` - Default configuration
25
+ - All preset configs in `templates/presets/*/config.json`
26
+ - `templates/config.example.json`
27
+ - **Impact**: More files will be analyzed without manual config adjustment
28
+ - **User action**: If you want stricter limits, set `"maxFileSize": 100000` in `.claude/config.json`
29
+
30
+ ### ✨ Added
31
+
32
+ - **Debug CLI Command** - New `--debug` flag for managing debug mode
33
+ - **Usage**: `claude-hooks --debug <true|false|status>`
34
+ - **Purpose**: Enables detailed logging for troubleshooting
35
+ - **Implementation**: Generic `updateConfig()` function in `bin/claude-hooks:1262`
36
+ - **Benefits**: Consistent with `--set-preset` pattern, no need to remember env var syntax
37
+
38
+ - **Generic Config Updater** - Reusable `updateConfig()` function
39
+ - **Purpose**: Centralized config update logic for all CLI commands
40
+ - **Location**: `bin/claude-hooks:1262`
41
+ - **Features**: Dot notation path support, custom validators, custom success messages
42
+ - **Extensibility**: Easy to add new config commands (`--set-max-files`, `--set-timeout`, etc.)
43
+
44
+ ### 🔄 Changed
45
+
46
+ - **setPreset() Refactored** - Now uses generic `updateConfig()` function
47
+ - **Effect**: Less code duplication, consistent error handling
48
+ - **Location**: `bin/claude-hooks:1349`
49
+
50
+ - **Debug Mode Activation** - Hooks now enable debug from config
51
+ - **Files**: `lib/hooks/pre-commit.js:185`, `lib/hooks/prepare-commit-msg.js:124`
52
+ - **Effect**: Debug logs appear when `config.system.debug` is true
53
+
54
+ ### 📚 Documentation
55
+
56
+ - **Help Text Updated** - Added `--debug` command documentation
57
+ - **Location**: `bin/claude-hooks:1170`
58
+ - **Includes**: Command description, examples, debug mode section
59
+
60
+ - **README.md Updated** - Debug command documented in multiple sections
61
+ - **Cheatsheet**: Added debug commands to "Comandos Frecuentes" (line 52-56)
62
+ - **Tips**: Updated tip #4 with CLI command (line 269)
63
+ - **Features**: Updated debug mode description (line 492)
64
+
8
65
  ## [2.3.1] - 2025-11-13
9
66
 
10
67
  ### 🔄 Changed
package/README.md CHANGED
@@ -48,6 +48,12 @@ claude-hooks --set-preset <name>
48
48
 
49
49
  # Mostrar preset actual
50
50
  claude-hooks preset current
51
+
52
+ # Activar modo debug
53
+ claude-hooks --debug true
54
+
55
+ # Ver estado de debug
56
+ claude-hooks --debug status
51
57
  ```
52
58
 
53
59
  ### 📦 Instalación y Gestión
@@ -127,7 +133,7 @@ cat > .claude/config.json << 'EOF'
127
133
  {
128
134
  "preset": "backend",
129
135
  "analysis": {
130
- "maxFileSize": 150000,
136
+ "maxFileSize": 1000000,
131
137
  "maxFiles": 12,
132
138
  "timeout": 150000
133
139
  },
@@ -260,9 +266,9 @@ git commit -m "fix: resolver issues"
260
266
  1. **Mensaje automático**: Usa `"auto"` como mensaje para que Claude lo genere
261
267
  2. **Skip auth**: Usa `--skip-auth` en CI/CD o desarrollo local
262
268
  3. **Force install**: Usa `--force` para reinstalar sin confirmación
263
- 4. **Debug**: Activa en `.claude/config.json`: `{"system": {"debug": true}}`
264
- 5. **Archivos grandes**: Se omiten automáticamente archivos > 100KB
265
- 6. **Límite de archivos**: Máximo 10 archivos por commit (configurable)
269
+ 4. **Debug**: Activa con `claude-hooks --debug true` o en `.claude/config.json`: `{"system": {"debug": true}}`
270
+ 5. **Archivos grandes**: Se omiten automáticamente archivos > 1MB
271
+ 6. **Límite de archivos**: Máximo 30 archivos por commit (configurable)
266
272
 
267
273
  ### 🚀 Parallel Analysis (v2.2.0+)
268
274
 
@@ -435,8 +441,8 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
435
441
  1. **Intercepta cada intento de commit**
436
442
  2. **Extrae y filtra archivos modificados**:
437
443
  - Solo analiza: Java, XML, properties, yml, yaml
438
- - Omite archivos mayores a 100KB
439
- - Límite de 10 archivos por commit
444
+ - Omite archivos mayores a 1MB
445
+ - Límite de 30 archivos por commit
440
446
  3. **Construye prompt inteligente**:
441
447
  - Usa template de prompt desde `.claude/CLAUDE_ANALYSIS_PROMPT*.md`
442
448
  - Lee las pautas desde `.claude/CLAUDE_PRE_COMMIT*.md`
@@ -462,7 +468,7 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
462
468
  - `"auto"`
463
469
  2. **Analiza los cambios del staging area**:
464
470
  - Lista archivos modificados con estadísticas
465
- - Incluye diffs completos para archivos < 100KB
471
+ - Incluye diffs completos para archivos < 1MB
466
472
  3. **Genera mensaje en formato Conventional Commits**:
467
473
  - Determina tipo: feat, fix, docs, style, refactor, test, chore
468
474
  - Crea título conciso y descriptivo
@@ -483,7 +489,7 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
483
489
  - 📝 Archivo `.claude-pr-analysis.json`
484
490
  - **Auto-actualización**: Verificación automática de versiones antes de cada commit con prompt interactivo para actualizar
485
491
  - **Comando update**: `claude-hooks update` para actualizar manualmente a la última versión
486
- - **Modo debug**: `DEBUG=1 git commit` guarda respuestas en `debug-claude-response.json`
492
+ - **Modo debug**: `claude-hooks --debug true` activa logging detallado para troubleshooting
487
493
  - **Análisis de PR**: Nuevo comando `analyze-diff` para generar información de Pull Requests
488
494
  - **Validación de dependencias**: Verifica que Claude CLI esté autenticado antes de ejecutar
489
495
  - **⚠️ Exclusión de código del análisis (EXPERIMENTAL/BROKEN)**: Los marcadores `// SKIP_ANALYSIS_LINE` y `// SKIP_ANALYSIS_BLOCK` no funcionan correctamente. El hook analiza git diff en lugar del archivo completo, por lo que marcadores agregados en commits anteriores no son detectados en cambios subsecuentes.
@@ -530,13 +536,13 @@ claude-hooks status
530
536
 
531
537
  En `lib/hooks/pre-commit.js`:
532
538
 
533
- - **`MAX_FILE_SIZE`**: Tamaño máximo de archivo a analizar (default: 100KB)
534
- - **`MAX_FILES`**: Número máximo de archivos por commit (default: 10)
539
+ - **`MAX_FILE_SIZE`**: Tamaño máximo de archivo a analizar (default: 1MB)
540
+ - **`MAX_FILES`**: Número máximo de archivos por commit (default: 30)
535
541
  - **`ALLOWED_EXTENSIONS`**: Extensiones permitidas (default: .java, .xml, .properties, .yml, .yaml)
536
542
 
537
543
  En `lib/hooks/prepare-commit-msg.js`:
538
544
 
539
- - **`MAX_FILE_SIZE`**: Tamaño máximo para incluir diff completo (default: 100KB)
545
+ - **`MAX_FILE_SIZE`**: Tamaño máximo para incluir diff completo (default: 1MB)
540
546
 
541
547
  ### Pautas de Evaluación
542
548
 
package/bin/claude-hooks CHANGED
@@ -468,6 +468,7 @@ async function install(args) {
468
468
  console.log(' 📝 Edit .claude/config.json to customize settings');
469
469
  console.log(' 🎯 Use presets: backend, frontend, fullstack, database, ai, default');
470
470
  console.log(' 🚀 Enable parallel analysis: set subagents.enabled = true');
471
+ console.log(' 🐛 Enable debug mode: claude-hooks --debug true');
471
472
  console.log('\n📖 Example config.json:');
472
473
  console.log(' {');
473
474
  console.log(' "preset": "backend",');
@@ -1167,6 +1168,7 @@ Commands:
1167
1168
  presets List all available presets
1168
1169
  --set-preset <name> Set the active preset
1169
1170
  preset current Show the current active preset
1171
+ --debug <value> Set debug mode (true, false, or status)
1170
1172
  --version, -v Show the current version
1171
1173
  help Show this help
1172
1174
 
@@ -1185,6 +1187,8 @@ Examples:
1185
1187
  claude-hooks presets # List available presets
1186
1188
  claude-hooks --set-preset backend # Set backend preset
1187
1189
  claude-hooks preset current # Show current preset
1190
+ claude-hooks --debug true # Enable debug mode
1191
+ claude-hooks --debug status # Check debug status
1188
1192
 
1189
1193
  Commit use cases:
1190
1194
  git commit -m "message" # Manual message + blocking analysis
@@ -1236,6 +1240,12 @@ Parallel Analysis (v2.2.0+):
1236
1240
  - batchSize: 4+ → Fewer API calls but slower
1237
1241
  - Speed improvement: up to 4x faster with batchSize: 1
1238
1242
 
1243
+ Debug Mode:
1244
+ Enable detailed logging for troubleshooting:
1245
+ - CLI: claude-hooks --debug true
1246
+ - Config: "system": { "debug": true } in .claude/config.json
1247
+ - Check status: claude-hooks --debug status
1248
+
1239
1249
  Customization:
1240
1250
  Override prompts by copying to .claude/:
1241
1251
  cp templates/COMMIT_MESSAGE.md .claude/
@@ -1247,6 +1257,68 @@ More information: https://github.com/pablorovito/claude-git-hooks
1247
1257
  `);
1248
1258
  }
1249
1259
 
1260
+ // Configuration Management Functions
1261
+
1262
+ /**
1263
+ * Updates a configuration value in .claude/config.json
1264
+ * Why: Centralized config update logic for all CLI commands
1265
+ *
1266
+ * @param {string} propertyPath - Dot notation path (e.g., 'preset', 'system.debug')
1267
+ * @param {any} value - Value to set
1268
+ * @param {Object} options - Optional settings
1269
+ * @param {Function} options.validator - Custom validation function, receives value, throws on invalid
1270
+ * @param {Function} options.successMessage - Function that receives value and returns success message
1271
+ */
1272
+ async function updateConfig(propertyPath, value, options = {}) {
1273
+ const { validator, successMessage } = options;
1274
+
1275
+ try {
1276
+ // Validate value if validator provided
1277
+ if (validator) {
1278
+ await validator(value);
1279
+ }
1280
+
1281
+ // Get repo root
1282
+ const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
1283
+ const configDir = path.join(repoRoot, '.claude');
1284
+ const configPath = path.join(configDir, 'config.json');
1285
+
1286
+ // Ensure .claude directory exists
1287
+ if (!fs.existsSync(configDir)) {
1288
+ fs.mkdirSync(configDir, { recursive: true });
1289
+ }
1290
+
1291
+ // Load existing config or create new
1292
+ let config = {};
1293
+ if (fs.existsSync(configPath)) {
1294
+ config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1295
+ }
1296
+
1297
+ // Set value at propertyPath (support dot notation like 'system.debug')
1298
+ const pathParts = propertyPath.split('.');
1299
+ let current = config;
1300
+ for (let i = 0; i < pathParts.length - 1; i++) {
1301
+ const part = pathParts[i];
1302
+ if (!current[part] || typeof current[part] !== 'object') {
1303
+ current[part] = {};
1304
+ }
1305
+ current = current[part];
1306
+ }
1307
+ current[pathParts[pathParts.length - 1]] = value;
1308
+
1309
+ // Save config
1310
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
1311
+
1312
+ // Show success message
1313
+ const message = successMessage ? successMessage(value) : 'Configuration updated';
1314
+ success(message);
1315
+ info(`Configuration saved to ${configPath}`);
1316
+ } catch (err) {
1317
+ error(`Failed to update configuration: ${err.message}`);
1318
+ process.exit(1);
1319
+ }
1320
+ }
1321
+
1250
1322
  // Preset Management Functions
1251
1323
 
1252
1324
  /**
@@ -1282,6 +1354,7 @@ async function showPresets() {
1282
1354
 
1283
1355
  /**
1284
1356
  * Sets the active preset
1357
+ * Why: Configures tech-stack specific analysis settings
1285
1358
  */
1286
1359
  async function setPreset(presetName) {
1287
1360
  if (!presetName) {
@@ -1289,45 +1362,24 @@ async function setPreset(presetName) {
1289
1362
  return;
1290
1363
  }
1291
1364
 
1292
- try {
1293
- // Verify preset exists
1294
- const presets = await listPresets();
1295
- const preset = presets.find(p => p.name === presetName);
1296
-
1297
- if (!preset) {
1298
- error(`Preset "${presetName}" not found`);
1299
- info('Available presets:');
1300
- presets.forEach(p => console.log(` - ${p.name}`));
1301
- process.exit(1);
1302
- }
1303
-
1304
- // Update .claude/config.json
1305
- const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
1306
- const configDir = path.join(repoRoot, '.claude');
1307
- const configPath = path.join(configDir, 'config.json');
1308
-
1309
- // Ensure .claude directory exists
1310
- if (!fs.existsSync(configDir)) {
1311
- fs.mkdirSync(configDir, { recursive: true });
1312
- }
1313
-
1314
- // Load existing config or create new
1315
- let config = {};
1316
- if (fs.existsSync(configPath)) {
1317
- config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1365
+ await updateConfig('preset', presetName, {
1366
+ validator: async (name) => {
1367
+ const presets = await listPresets();
1368
+ const preset = presets.find(p => p.name === name);
1369
+ if (!preset) {
1370
+ error(`Preset "${name}" not found`);
1371
+ info('Available presets:');
1372
+ presets.forEach(p => console.log(` - ${p.name}`));
1373
+ throw new Error(`Invalid preset: ${name}`);
1374
+ }
1375
+ return preset;
1376
+ },
1377
+ successMessage: async (name) => {
1378
+ const presets = await listPresets();
1379
+ const preset = presets.find(p => p.name === name);
1380
+ return `Preset '${preset.displayName}' activated`;
1318
1381
  }
1319
-
1320
- // Set preset
1321
- config.preset = presetName;
1322
-
1323
- // Save config
1324
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
1325
-
1326
- success(`Preset '${preset.displayName}' activated`);
1327
- info(`Configuration saved to ${configPath}`);
1328
- } catch (err) {
1329
- error(`Failed to set preset: ${err.message}`);
1330
- }
1382
+ });
1331
1383
  }
1332
1384
 
1333
1385
  /**
@@ -1354,6 +1406,45 @@ async function currentPreset() {
1354
1406
  }
1355
1407
  }
1356
1408
 
1409
+ /**
1410
+ * Sets debug mode
1411
+ * Why: Enables detailed logging for troubleshooting
1412
+ */
1413
+ async function setDebug(value) {
1414
+ if (!value) {
1415
+ error('Please specify a value: claude-hooks --debug <true|false|status>');
1416
+ return;
1417
+ }
1418
+
1419
+ const normalizedValue = value.toLowerCase();
1420
+
1421
+ // Handle status check
1422
+ if (normalizedValue === 'status') {
1423
+ try {
1424
+ const config = await getConfig();
1425
+ const isEnabled = config.system.debug || false;
1426
+ console.log('');
1427
+ info(`Debug mode: ${isEnabled ? colors.green + 'enabled' + colors.reset : colors.red + 'disabled' + colors.reset}`);
1428
+ console.log('');
1429
+ } catch (err) {
1430
+ error(`Failed to check debug status: ${err.message}`);
1431
+ }
1432
+ return;
1433
+ }
1434
+
1435
+ // Validate and convert to boolean
1436
+ if (normalizedValue !== 'true' && normalizedValue !== 'false') {
1437
+ error('Invalid value. Use: true, false, or status');
1438
+ return;
1439
+ }
1440
+
1441
+ const debugValue = normalizedValue === 'true';
1442
+
1443
+ await updateConfig('system.debug', debugValue, {
1444
+ successMessage: (val) => `Debug mode ${val ? 'enabled' : 'disabled'}`
1445
+ });
1446
+ }
1447
+
1357
1448
  // Main
1358
1449
  async function main() {
1359
1450
  const args = process.argv.slice(2);
@@ -1395,6 +1486,9 @@ async function main() {
1395
1486
  error(`Unknown preset subcommand: ${args[1]}`);
1396
1487
  }
1397
1488
  break;
1489
+ case '--debug':
1490
+ await setDebug(args[1]);
1491
+ break;
1398
1492
  case '--version':
1399
1493
  case '-v':
1400
1494
  case 'version':
package/lib/config.js CHANGED
@@ -26,9 +26,9 @@ const __dirname = path.dirname(__filename);
26
26
  const defaults = {
27
27
  // Analysis configuration
28
28
  analysis: {
29
- maxFileSize: 100000, // 100KB - max file size to analyze
30
- maxFiles: 10, // Max number of files per commit
31
- timeout: 120000, // 2 minutes - Claude analysis timeout
29
+ maxFileSize: 1000000, // 1MB - max file size to analyze
30
+ maxFiles: 20, // Max number of files per commit
31
+ timeout: 300000, // 3 minutes - Claude analysis timeout
32
32
  contextLines: 3, // Git diff context lines
33
33
  ignoreExtensions: [], // Extensions to exclude (e.g., ['.min.js', '.lock'])
34
34
  // NOTE: allowedExtensions comes from preset/template, not here
@@ -37,14 +37,14 @@ const defaults = {
37
37
  // Commit message generation
38
38
  commitMessage: {
39
39
  autoKeyword: 'auto', // Keyword to trigger auto-generation
40
- timeout: 180000,
40
+ timeout: 300000,
41
41
  },
42
42
 
43
43
  // Subagent configuration (parallel analysis)
44
44
  subagents: {
45
- enabled: true, // Enable parallel file analysis
45
+ enabled: false, // Enable parallel file analysis
46
46
  model: 'haiku', // haiku (fast), sonnet (balanced), opus (thorough)
47
- batchSize: 3, // Parallel subagents per batch
47
+ batchSize: 1, // Parallel subagents per batch
48
48
  },
49
49
 
50
50
  // Template paths
@@ -181,12 +181,38 @@ const main = async () => {
181
181
  // Load configuration
182
182
  const config = await getConfig();
183
183
 
184
+ // Enable debug mode from config
185
+ if (config.system.debug) {
186
+ logger.setDebugMode(true);
187
+ }
188
+
184
189
  // Display configuration info
185
190
  const version = await getVersion();
186
191
  console.log(`\n🤖 claude-git-hooks v${version}`);
187
192
 
188
193
  logger.info('Starting code quality analysis...');
189
194
 
195
+ // DEBUG: Log working directories
196
+ const repoRoot = await import('../utils/git-operations.js').then(m => m.getRepoRoot());
197
+ const { getRepoRoot } = await import('../utils/git-operations.js');
198
+
199
+ // Normalize paths for comparison (handle Windows backslash vs forward slash)
200
+ const normalizePath = (p) => p.replace(/\\/g, '/').toLowerCase();
201
+ const cwdNormalized = normalizePath(process.cwd());
202
+ const repoRootNormalized = normalizePath(repoRoot);
203
+
204
+ logger.debug(
205
+ 'pre-commit - main',
206
+ 'Working directory info',
207
+ {
208
+ 'process.cwd()': process.cwd(),
209
+ 'repo root': repoRoot,
210
+ 'cwd (normalized)': cwdNormalized,
211
+ 'repo root (normalized)': repoRootNormalized,
212
+ 'match': cwdNormalized === repoRootNormalized
213
+ }
214
+ );
215
+
190
216
  logger.debug(
191
217
  'pre-commit - main',
192
218
  'Configuration',
@@ -237,6 +263,14 @@ const main = async () => {
237
263
  });
238
264
 
239
265
  const validFiles = filteredFiles.filter(f => f.valid);
266
+ const invalidFiles = filteredFiles.filter(f => !f.valid);
267
+
268
+ // Show user-facing warnings for rejected files
269
+ if (invalidFiles.length > 0) {
270
+ invalidFiles.forEach(file => {
271
+ logger.warning(`Skipping ${file.path}: ${file.reason}`);
272
+ });
273
+ }
240
274
 
241
275
  if (validFiles.length === 0) {
242
276
  logger.warning('No valid files found to review');
@@ -120,6 +120,11 @@ const main = async () => {
120
120
  // Load configuration (includes preset + user overrides)
121
121
  const config = await getConfig();
122
122
 
123
+ // Enable debug mode from config
124
+ if (config.system.debug) {
125
+ logger.setDebugMode(true);
126
+ }
127
+
123
128
  try {
124
129
  // Get hook arguments
125
130
  const args = process.argv.slice(2);
@@ -250,13 +250,24 @@ const filterFiles = async (files, { maxSize = 100000, extensions = [] } = {}) =>
250
250
  logger.debug(
251
251
  'file-operations - filterFiles',
252
252
  'Filtering files',
253
- { fileCount: files.length, maxSize, extensions }
253
+ {
254
+ fileCount: files.length,
255
+ maxSize,
256
+ extensions,
257
+ 'process.cwd()': process.cwd(),
258
+ files: files
259
+ }
254
260
  );
255
261
 
256
262
  const results = await Promise.allSettled(
257
263
  files.map(async (filePath) => {
258
264
  // Check extension first (fast)
259
265
  if (!hasAllowedExtension(filePath, extensions)) {
266
+ logger.debug(
267
+ 'file-operations - filterFiles',
268
+ 'Extension rejected',
269
+ { filePath }
270
+ );
260
271
  return {
261
272
  path: filePath,
262
273
  size: 0,
@@ -267,6 +278,11 @@ const filterFiles = async (files, { maxSize = 100000, extensions = [] } = {}) =>
267
278
 
268
279
  // Check if file exists
269
280
  const exists = await fileExists(filePath);
281
+ logger.debug(
282
+ 'file-operations - filterFiles',
283
+ 'File exists check',
284
+ { filePath, exists }
285
+ );
270
286
  if (!exists) {
271
287
  return {
272
288
  path: filePath,
@@ -281,6 +297,11 @@ const filterFiles = async (files, { maxSize = 100000, extensions = [] } = {}) =>
281
297
  const size = await getFileSize(filePath);
282
298
 
283
299
  if (size > maxSize) {
300
+ logger.debug(
301
+ 'file-operations - filterFiles',
302
+ 'File too large',
303
+ { filePath, size, maxSize, 'size (KB)': Math.round(size / 1024), 'maxSize (KB)': Math.round(maxSize / 1024) }
304
+ );
284
305
  return {
285
306
  path: filePath,
286
307
  size,
@@ -289,6 +310,12 @@ const filterFiles = async (files, { maxSize = 100000, extensions = [] } = {}) =>
289
310
  };
290
311
  }
291
312
 
313
+ logger.debug(
314
+ 'file-operations - filterFiles',
315
+ 'File passed size check',
316
+ { filePath, size, maxSize, 'size (KB)': Math.round(size / 1024) }
317
+ );
318
+
292
319
  return {
293
320
  path: filePath,
294
321
  size,
@@ -297,6 +324,11 @@ const filterFiles = async (files, { maxSize = 100000, extensions = [] } = {}) =>
297
324
  };
298
325
 
299
326
  } catch (error) {
327
+ logger.debug(
328
+ 'file-operations - filterFiles',
329
+ 'Error reading file',
330
+ { filePath, error: error.message }
331
+ );
300
332
  return {
301
333
  path: filePath,
302
334
  size: 0,
@@ -312,15 +344,17 @@ const filterFiles = async (files, { maxSize = 100000, extensions = [] } = {}) =>
312
344
  .filter(r => r.status === 'fulfilled')
313
345
  .map(r => r.value);
314
346
 
315
- const validCount = fileMetadata.filter(f => f.valid).length;
347
+ const validFiles = fileMetadata.filter(f => f.valid);
348
+ const invalidFiles = fileMetadata.filter(f => !f.valid);
316
349
 
317
350
  logger.debug(
318
351
  'file-operations - filterFiles',
319
352
  'Filtering complete',
320
353
  {
321
354
  totalFiles: files.length,
322
- validFiles: validCount,
323
- invalidFiles: fileMetadata.length - validCount
355
+ validFiles: validFiles.length,
356
+ invalidFiles: invalidFiles.length,
357
+ rejectedFiles: invalidFiles.map(f => ({ path: f.path, reason: f.reason }))
324
358
  }
325
359
  );
326
360
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  class Logger {
18
18
  constructor({ debugMode = false } = {}) {
19
- this.debugMode = debugMode || process.env.DEBUG === 'true';
19
+ this.debugMode = debugMode;
20
20
  this.colors = {
21
21
  reset: '\x1b[0m',
22
22
  red: '\x1b[31m',
@@ -138,4 +138,4 @@ class Logger {
138
138
 
139
139
  // Export singleton instance
140
140
  // Why: Single logger instance ensures consistent debug mode across entire application
141
- export default new Logger({ debugMode: process.env.DEBUG === 'true' });
141
+ export default new Logger();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-git-hooks",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "description": "Git hooks with Claude CLI for code analysis and automatic commit messages",
5
5
  "type": "module",
6
6
  "bin": {
@@ -108,7 +108,7 @@ A preset is a **self-contained package** that customizes claude-hooks for a spec
108
108
  │ 3. CONFIGURATION MERGED │
109
109
  │ defaults < user config < preset config │
110
110
  │ - File extensions: ['.java', '.xml', '.yml'] │
111
- │ - Max file size: 100KB
111
+ │ - Max file size: 1MB
112
112
  │ - Parallel analysis: enabled │
113
113
  └────────────────────────┬────────────────────────────────────┘
114
114
 
@@ -282,7 +282,7 @@ cd python-django
282
282
  ```json
283
283
  {
284
284
  "analysis": {
285
- "maxFileSize": 150000,
285
+ "maxFileSize": 1000000,
286
286
  "maxFiles": 12,
287
287
  "timeout": 180000
288
288
  },
@@ -306,9 +306,9 @@ cd python-django
306
306
  ```javascript
307
307
  {
308
308
  analysis: {
309
- maxFileSize: 100000, // 100KB
310
- maxFiles: 10,
311
- timeout: 120000 // 2 minutes
309
+ maxFileSize: 1000000, // 1MB
310
+ maxFiles: 30,
311
+ timeout: 180000 // 3 minutes
312
312
  },
313
313
  subagents: {
314
314
  enabled: true,
@@ -1,41 +1,41 @@
1
1
  {
2
- "preset": null,
3
- "analysis": {
4
- "maxFileSize": 100000,
5
- "maxFiles": 10,
6
- "timeout": 120000,
7
- "contextLines": 3,
8
- "ignoreExtensions": []
9
- },
10
- "commitMessage": {
11
- "autoKeyword": "auto",
12
- "timeout": 180000
13
- },
14
- "subagents": {
15
- "enabled": true,
16
- "model": "haiku",
17
- "batchSize": 3
18
- },
19
- "templates": {
20
- "baseDir": ".claude",
21
- "analysis": "CLAUDE_ANALYSIS_PROMPT_SONAR.md",
22
- "guidelines": "CLAUDE_PRE_COMMIT_SONAR.md",
23
- "commitMessage": "COMMIT_MESSAGE.md",
24
- "analyzeDiff": "ANALYZE_DIFF.md",
25
- "resolution": "CLAUDE_RESOLUTION_PROMPT.md",
26
- "subagentInstruction": "SUBAGENT_INSTRUCTION.md"
27
- },
28
- "output": {
29
- "outputDir": ".claude/out",
30
- "debugFile": ".claude/out/debug-claude-response.json",
31
- "resolutionFile": ".claude/out/claude_resolution_prompt.md",
32
- "prAnalysisFile": ".claude/out/pr-analysis.json"
33
- },
34
- "system": {
35
- "debug": false,
36
- "wslCheckTimeout": 3000
37
- },
38
- "git": {
39
- "diffFilter": "ACM"
40
- }
2
+ "preset": "ai",
3
+ "analysis": {
4
+ "maxFileSize": 1000000,
5
+ "maxFiles": 30,
6
+ "timeout": 180000,
7
+ "contextLines": 3,
8
+ "ignoreExtensions": []
9
+ },
10
+ "commitMessage": {
11
+ "autoKeyword": "auto",
12
+ "timeout": 180000
13
+ },
14
+ "subagents": {
15
+ "enabled": false,
16
+ "model": "haiku",
17
+ "batchSize": 1
18
+ },
19
+ "templates": {
20
+ "baseDir": ".claude",
21
+ "analysis": "CLAUDE_ANALYSIS_PROMPT_SONAR.md",
22
+ "guidelines": "CLAUDE_PRE_COMMIT_SONAR.md",
23
+ "commitMessage": "COMMIT_MESSAGE.md",
24
+ "analyzeDiff": "ANALYZE_DIFF.md",
25
+ "resolution": "CLAUDE_RESOLUTION_PROMPT.md",
26
+ "subagentInstruction": "SUBAGENT_INSTRUCTION.md"
27
+ },
28
+ "output": {
29
+ "outputDir": ".claude/out",
30
+ "debugFile": ".claude/out/debug-claude-response.json",
31
+ "resolutionFile": ".claude/out/claude_resolution_prompt.md",
32
+ "prAnalysisFile": ".claude/out/pr-analysis.json"
33
+ },
34
+ "system": {
35
+ "debug": false,
36
+ "wslCheckTimeout": 3000
37
+ },
38
+ "git": {
39
+ "diffFilter": "ACM"
40
+ }
41
41
  }
@@ -1,12 +1,12 @@
1
1
  {
2
- "analysis": {
3
- "maxFileSize": 100000,
4
- "maxFiles": 10,
5
- "timeout": 120000
6
- },
7
- "subagents": {
8
- "enabled": false,
9
- "model": "sonnet",
10
- "batchSize": 3
11
- }
2
+ "analysis": {
3
+ "maxFileSize": 1000000,
4
+ "maxFiles": 10,
5
+ "timeout": 300000
6
+ },
7
+ "subagents": {
8
+ "enabled": true,
9
+ "model": "haiku",
10
+ "batchSize": 3
11
+ }
12
12
  }
@@ -1,12 +1,12 @@
1
1
  {
2
- "analysis": {
3
- "maxFileSize": 100000,
4
- "maxFiles": 10,
5
- "timeout": 120000
6
- },
7
- "subagents": {
8
- "enabled": true,
9
- "model": "sonnet",
10
- "batchSize": 3
11
- }
2
+ "analysis": {
3
+ "maxFileSize": 1000000,
4
+ "maxFiles": 10,
5
+ "timeout": 300000
6
+ },
7
+ "subagents": {
8
+ "enabled": true,
9
+ "model": "haiku",
10
+ "batchSize": 3
11
+ }
12
12
  }
@@ -1,12 +1,12 @@
1
1
  {
2
- "analysis": {
3
- "maxFileSize": 150000,
4
- "maxFiles": 8,
5
- "timeout": 120000
6
- },
7
- "subagents": {
8
- "enabled": false,
9
- "model": "sonnet",
10
- "batchSize": 2
11
- }
2
+ "analysis": {
3
+ "maxFileSize": 1000000,
4
+ "maxFiles": 8,
5
+ "timeout": 300000
6
+ },
7
+ "subagents": {
8
+ "enabled": true,
9
+ "model": "haiku",
10
+ "batchSize": 2
11
+ }
12
12
  }
@@ -1,12 +1,12 @@
1
1
  {
2
- "analysis": {
3
- "maxFileSize": 100000,
4
- "maxFiles": 10,
5
- "timeout": 120000
6
- },
7
- "subagents": {
8
- "enabled": false,
9
- "model": "sonnet",
10
- "batchSize": 3
11
- }
2
+ "analysis": {
3
+ "maxFileSize": 1000000,
4
+ "maxFiles": 10,
5
+ "timeout": 300000
6
+ },
7
+ "subagents": {
8
+ "enabled": true,
9
+ "model": "haiku",
10
+ "batchSize": 3
11
+ }
12
12
  }
@@ -1,12 +1,12 @@
1
1
  {
2
- "analysis": {
3
- "maxFileSize": 100000,
4
- "maxFiles": 10,
5
- "timeout": 120000
6
- },
7
- "subagents": {
8
- "enabled": true,
9
- "model": "sonnet",
10
- "batchSize": 3
11
- }
2
+ "analysis": {
3
+ "maxFileSize": 1000000,
4
+ "maxFiles": 10,
5
+ "timeout": 300000
6
+ },
7
+ "subagents": {
8
+ "enabled": true,
9
+ "model": "haiku",
10
+ "batchSize": 3
11
+ }
12
12
  }
@@ -1,12 +1,12 @@
1
1
  {
2
- "analysis": {
3
- "maxFileSize": 100000,
4
- "maxFiles": 15,
5
- "timeout": 180000
6
- },
7
- "subagents": {
8
- "enabled": true,
9
- "model": "sonnet",
10
- "batchSize": 4
11
- }
2
+ "analysis": {
3
+ "maxFileSize": 1000000,
4
+ "maxFiles": 15,
5
+ "timeout": 300000
6
+ },
7
+ "subagents": {
8
+ "enabled": true,
9
+ "model": "haiku",
10
+ "batchSize": 4
11
+ }
12
12
  }