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/CHANGELOG.md +150 -0
- package/CLAUDE.md +24 -1384
- package/README.md +113 -0
- package/bin/claude-hooks +11 -7
- package/lib/cli-metadata.js +17 -3
- package/lib/commands/analyze-pr.js +270 -145
- package/lib/commands/analyze.js +151 -3
- package/lib/commands/create-pr.js +345 -134
- package/lib/commands/helpers.js +9 -4
- package/lib/commands/hooks.js +5 -5
- package/lib/commands/install.js +77 -28
- package/lib/commands/lint.js +120 -4
- package/lib/config.js +4 -1
- package/lib/hooks/pre-commit.js +26 -5
- package/lib/hooks/prepare-commit-msg.js +78 -4
- package/lib/utils/analysis-engine.js +12 -6
- package/lib/utils/claude-client.js +222 -12
- package/lib/utils/claude-diagnostics.js +5 -4
- package/lib/utils/cost-tracker.js +128 -0
- package/lib/utils/diff-analysis-orchestrator.js +2 -1
- package/lib/utils/git-operations.js +105 -2
- package/lib/utils/hooks-verified-marker.js +121 -0
- package/lib/utils/interactive-ui.js +4 -4
- package/lib/utils/judge.js +4 -3
- package/lib/utils/langfuse-tracer.js +156 -0
- package/lib/utils/linter-runner.js +29 -4
- package/lib/utils/logger.js +30 -5
- package/lib/utils/pr-metadata-engine.js +4 -2
- package/lib/utils/tool-runner.js +4 -3
- package/package.json +4 -2
- package/templates/CUSTOMIZATION_GUIDE.md +2 -2
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
|
-
|
|
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
|
}
|
package/lib/cli-metadata.js
CHANGED
|
@@ -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: '
|
|
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
|
{
|