claude-git-hooks 2.35.2 → 2.43.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/README.md CHANGED
@@ -570,4 +570,117 @@ claude-hooks batch-info # Shows config + per-model avg speed from telemetry
570
570
 
571
571
  ---
572
572
 
573
+ ## Contributing
574
+
575
+ ### Branching Strategy
576
+
577
+ This repository follows **simplified GitHub Flow**:
578
+
579
+ - **Main branch**: `main` (protected)
580
+ - **Feature branches**: `feature/issue-description` or `feature/TASK-ID-description`
581
+ - **Fix branches**: `fix/issue-description`
582
+ - **Hotfix branches**: `hotfix/urgent-description`
583
+
584
+ **Rules:**
585
+
586
+ 1. All changes require PR to `main`
587
+ 2. No direct commits to `main`
588
+ 3. PRs require review (auto-merge NOT allowed)
589
+
590
+ ### Development Process
591
+
592
+ **1. Initial setup**
593
+
594
+ ```bash
595
+ git clone https://github.com/mscope-S-L/git-hooks.git
596
+ cd git-hooks
597
+ npm install
598
+ npm link # Install globally as symlink for development
599
+ ```
600
+
601
+ **2. Create feature branch**
602
+
603
+ ```bash
604
+ git checkout -b feature/new-functionality
605
+ # or with task-id: feature/IX-123-new-functionality
606
+ ```
607
+
608
+ **3. Develop and test**
609
+
610
+ ```bash
611
+ npm run lint # Check ESLint
612
+ npm run lint:fix # Auto-fix ESLint issues
613
+ npm run format # Format with Prettier
614
+ npm run test # Run all tests (Jest)
615
+ npm run test:watch # Tests in watch mode
616
+ npm run test:coverage # Coverage report
617
+ ```
618
+
619
+ **4. Local testing in a test repo**
620
+
621
+ ```bash
622
+ cd /path/to/test-repo
623
+ claude-hooks install --force --skip-auth # Reinstall from symlink
624
+ git commit -m "test" # Test hook (npm link is active, no reinstall needed)
625
+ ```
626
+
627
+ **5. Create PR**
628
+
629
+ ```bash
630
+ git push -u origin feature/new-functionality
631
+ claude-hooks analyze-diff main # Generate PR metadata
632
+ claude-hooks create-pr main # Or create PR directly on GitHub
633
+ ```
634
+
635
+ ### CI/CD
636
+
637
+ No automated CI/CD (GitHub Actions pending). Manual verifications before merge:
638
+
639
+ 1. `npm run lint` passes
640
+ 2. `npm run test` — all tests pass
641
+ 3. Manual testing in test repo
642
+ 4. Peer code review
643
+ 5. CHANGELOG.md updated
644
+
645
+ ### Versioning
646
+
647
+ Follows **Semantic Versioning** (MAJOR.MINOR.PATCH):
648
+
649
+ - **MAJOR**: Breaking changes (config format, CLI arguments)
650
+ - **MINOR**: New features without breaking changes
651
+ - **PATCH**: Bug fixes
652
+
653
+ ```bash
654
+ npm version patch # 2.6.1 → 2.6.2
655
+ npm version minor # 2.6.1 → 2.7.0
656
+ npm version major # 2.6.1 → 3.0.0
657
+ npm publish # Publish to NPM
658
+ ```
659
+
660
+ ### Conventional Commits
661
+
662
+ Format: `<type>(<scope>): <subject>`
663
+
664
+ | Type | Purpose |
665
+ |------|---------|
666
+ | `feat` | New functionality |
667
+ | `fix` | Bug fix |
668
+ | `docs` | Documentation only |
669
+ | `style` | Formatting (no logic change) |
670
+ | `refactor` | Refactoring without functional change |
671
+ | `test` | Add or modify tests |
672
+ | `chore` | Maintenance (deps, config) |
673
+ | `perf` | Performance improvements |
674
+
675
+ **Optional scopes:** `hooks`, `presets`, `github`, `cli`, `config`, `windows`
676
+
677
+ ```
678
+ feat(presets): add database preset for SQL analysis
679
+ fix(windows): resolve spawn ENOENT with .cmd files
680
+ docs: update CLAUDE.md with architecture details
681
+ chore(deps): upgrade @octokit/rest to v21
682
+ ```
683
+
684
+ ---
685
+
573
686
  More information: https://github.com/mscope-S-L/git-hooks
package/bin/claude-hooks CHANGED
@@ -8,7 +8,7 @@
8
8
  * All command implementations are in lib/commands/
9
9
  */
10
10
 
11
- import { error } from '../lib/commands/helpers.js';
11
+ import { error, fatal } from '../lib/commands/helpers.js';
12
12
  import { buildCommandMap } from '../lib/cli-metadata.js';
13
13
  import logger from '../lib/utils/logger.js';
14
14
  import { getConfig } from '../lib/config.js';
@@ -41,14 +41,12 @@ async function main() {
41
41
  }
42
42
 
43
43
  if (!entry) {
44
- error(`Unknown command: ${command}`);
45
- const { runShowHelp } = await import('../lib/commands/help.js');
46
- runShowHelp();
47
- return;
44
+ fatal(`Unknown command: ${command}`);
48
45
  }
49
46
 
50
47
  // --- Authorization guard for protected workflow commands ---
51
- {
48
+ const isHeadless = args.includes('--headless');
49
+ if (!isHeadless) {
52
50
  const { authorizeCommand, AuthorizationError, PERMISSIONS_SOURCE } = await import(
53
51
  '../lib/utils/authorization.js'
54
52
  );
@@ -128,6 +126,9 @@ async function main() {
128
126
  }
129
127
  process.exit(1);
130
128
  }
129
+ } else {
130
+ const { default: logger } = await import('../lib/utils/logger.js');
131
+ logger.debug('bin - main', 'Authorization guard bypassed (--headless)', { command: entry.name });
131
132
  }
132
133
 
133
134
  // --- Commands with special argument handling ---
@@ -135,10 +136,13 @@ async function main() {
135
136
  // analyze: translate flags to options object
136
137
  if (entry.name === 'analyze') {
137
138
  const handler = await entry.handler();
139
+ const fmtIdx = args.indexOf('--format');
138
140
  await handler({
139
141
  staged: !args.includes('--unstaged') && !args.includes('--all'),
140
142
  unstaged: args.includes('--unstaged'),
141
- all: args.includes('--all')
143
+ all: args.includes('--all'),
144
+ headless: args.includes('--headless'),
145
+ format: fmtIdx >= 0 ? args[fmtIdx + 1] : null
142
146
  });
143
147
  return;
144
148
  }
@@ -61,7 +61,9 @@ export const commands = [
61
61
  handler: async () => (await import('./commands/install.js')).runInstall,
62
62
  flags: {
63
63
  '--force': { description: 'Reinstall even if already exist' },
64
- '--skip-auth': { description: 'Skip Claude authentication check' }
64
+ '--skip-auth': { description: 'Deprecated: use --headless. Will be removed in a future version.' },
65
+ '--headless': { description: 'Skip all side effects (CI/container mode). Copies hooks only.' },
66
+ '--verify-sdk': { description: 'After install, ping the Anthropic SDK with 1 token to verify ANTHROPIC_API_KEY.' }
65
67
  }
66
68
  },
67
69
  {
@@ -104,6 +106,10 @@ export const commands = [
104
106
  args: {
105
107
  name: 'paths',
106
108
  completion: "find . -maxdepth 3 -type d -not -path '*/\\.*' -not -path '*/node_modules/*'"
109
+ },
110
+ flags: {
111
+ '--headless': { description: 'Skip interactive prompts (CI mode)' },
112
+ '--format': { description: 'Output format', takesValue: true, values: ['json'] }
107
113
  }
108
114
  },
109
115
  {
@@ -112,7 +118,9 @@ export const commands = [
112
118
  handler: async () => (await import('./commands/analyze.js')).runAnalyze,
113
119
  flags: {
114
120
  '--unstaged': { description: 'Analyze unstaged changes' },
115
- '--all': { description: 'Analyze all tracked files' }
121
+ '--all': { description: 'Analyze all tracked files' },
122
+ '--headless': { description: 'Skip interactive prompts (CI mode)' },
123
+ '--format': { description: 'Output format', takesValue: true, values: ['json'] }
116
124
  }
117
125
  },
118
126
  {
@@ -136,7 +144,9 @@ export const commands = [
136
144
  values: PRESET_NAMES
137
145
  },
138
146
  '--model': { description: 'Claude model override', takesValue: true },
139
- '--dry-run': { description: 'Analyze without posting comments' }
147
+ '--dry-run': { description: 'Analyze without posting comments' },
148
+ '--headless': { description: 'Skip interactive prompts (CI mode)' },
149
+ '--format': { description: 'Output format', takesValue: true, values: ['json'] }
140
150
  }
141
151
  },
142
152
  {
@@ -146,6 +156,10 @@ export const commands = [
146
156
  args: {
147
157
  name: 'base-branch',
148
158
  completion: "git branch --format='%(refname:short)'"
159
+ },
160
+ flags: {
161
+ '--headless': { description: 'Skip interactive prompts (CI mode)' },
162
+ '--format': { description: 'Output format', takesValue: true, values: ['json'] }
149
163
  }
150
164
  },
151
165
  {