claude-git-hooks 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +178 -0
- package/README.md +203 -79
- package/bin/claude-hooks +295 -119
- package/lib/config.js +163 -0
- package/lib/hooks/pre-commit.js +179 -67
- package/lib/hooks/prepare-commit-msg.js +47 -41
- package/lib/utils/claude-client.js +93 -11
- package/lib/utils/file-operations.js +1 -65
- package/lib/utils/file-utils.js +65 -0
- package/lib/utils/package-info.js +75 -0
- package/lib/utils/preset-loader.js +209 -0
- package/lib/utils/prompt-builder.js +83 -67
- package/lib/utils/resolution-prompt.js +12 -2
- package/package.json +49 -50
- package/templates/ANALYZE_DIFF.md +33 -0
- package/templates/COMMIT_MESSAGE.md +24 -0
- package/templates/SUBAGENT_INSTRUCTION.md +1 -0
- package/templates/config.example.json +41 -0
- package/templates/presets/ai/ANALYSIS_PROMPT.md +133 -0
- package/templates/presets/ai/PRE_COMMIT_GUIDELINES.md +176 -0
- package/templates/presets/ai/config.json +12 -0
- package/templates/presets/ai/preset.json +42 -0
- package/templates/presets/backend/ANALYSIS_PROMPT.md +85 -0
- package/templates/presets/backend/PRE_COMMIT_GUIDELINES.md +87 -0
- package/templates/presets/backend/config.json +12 -0
- package/templates/presets/backend/preset.json +49 -0
- package/templates/presets/database/ANALYSIS_PROMPT.md +114 -0
- package/templates/presets/database/PRE_COMMIT_GUIDELINES.md +143 -0
- package/templates/presets/database/config.json +12 -0
- package/templates/presets/database/preset.json +38 -0
- package/templates/presets/default/config.json +12 -0
- package/templates/presets/default/preset.json +53 -0
- package/templates/presets/frontend/ANALYSIS_PROMPT.md +99 -0
- package/templates/presets/frontend/PRE_COMMIT_GUIDELINES.md +95 -0
- package/templates/presets/frontend/config.json +12 -0
- package/templates/presets/frontend/preset.json +50 -0
- package/templates/presets/fullstack/ANALYSIS_PROMPT.md +107 -0
- package/templates/presets/fullstack/CONSISTENCY_CHECKS.md +147 -0
- package/templates/presets/fullstack/PRE_COMMIT_GUIDELINES.md +125 -0
- package/templates/presets/fullstack/config.json +12 -0
- package/templates/presets/fullstack/preset.json +55 -0
- package/templates/shared/ANALYSIS_PROMPT.md +103 -0
- package/templates/shared/ANALYZE_DIFF.md +33 -0
- package/templates/shared/COMMIT_MESSAGE.md +24 -0
- package/templates/shared/PRE_COMMIT_GUIDELINES.md +145 -0
- package/templates/shared/RESOLUTION_PROMPT.md +32 -0
- package/templates/check-version.sh +0 -266
|
@@ -38,14 +38,22 @@ class PromptBuilderError extends Error {
|
|
|
38
38
|
* Why absolute path: Ensures templates are found regardless of cwd (cross-platform)
|
|
39
39
|
*
|
|
40
40
|
* @param {string} templateName - Name of template file
|
|
41
|
-
* @param {string} baseDir - Base directory (default: .claude)
|
|
41
|
+
* @param {string} baseDir - Base directory (default: try .claude, fallback to templates)
|
|
42
42
|
* @returns {Promise<string>} Template content
|
|
43
43
|
* @throws {PromptBuilderError} If template not found
|
|
44
44
|
*/
|
|
45
45
|
const loadTemplate = async (templateName, baseDir = '.claude') => {
|
|
46
46
|
// Why: Use repo root for absolute path (works on Windows/PowerShell/Git Bash)
|
|
47
47
|
const repoRoot = getRepoRoot();
|
|
48
|
-
|
|
48
|
+
let templatePath = path.join(repoRoot, baseDir, templateName);
|
|
49
|
+
|
|
50
|
+
// Try .claude first, fallback to templates/ if not found
|
|
51
|
+
try {
|
|
52
|
+
await fs.access(templatePath);
|
|
53
|
+
} catch {
|
|
54
|
+
// Try templates/ directory as fallback
|
|
55
|
+
templatePath = path.join(repoRoot, 'templates', templateName);
|
|
56
|
+
}
|
|
49
57
|
|
|
50
58
|
logger.debug(
|
|
51
59
|
'prompt-builder - loadTemplate',
|
|
@@ -104,6 +112,57 @@ const replaceTemplate = (template, variables) => {
|
|
|
104
112
|
}, template);
|
|
105
113
|
};
|
|
106
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Loads a prompt template and replaces variables
|
|
117
|
+
* Why: High-level interface that combines loading and variable replacement
|
|
118
|
+
*
|
|
119
|
+
* @param {string} templateName - Name of template file
|
|
120
|
+
* @param {Object} variables - Variables to replace in template
|
|
121
|
+
* @param {string} baseDir - Base directory (default: .claude)
|
|
122
|
+
* @returns {Promise<string>} Prompt with replaced variables
|
|
123
|
+
* @throws {PromptBuilderError} If template not found
|
|
124
|
+
*
|
|
125
|
+
* Example:
|
|
126
|
+
* const prompt = await loadPrompt('COMMIT_MESSAGE.md', {
|
|
127
|
+
* FILE_LIST: 'file1.js\nfile2.js',
|
|
128
|
+
* FILE_COUNT: 2,
|
|
129
|
+
* INSERTIONS: 10,
|
|
130
|
+
* DELETIONS: 5
|
|
131
|
+
* });
|
|
132
|
+
*/
|
|
133
|
+
const loadPrompt = async (templateName, variables = {}, baseDir = '.claude') => {
|
|
134
|
+
logger.debug(
|
|
135
|
+
'prompt-builder - loadPrompt',
|
|
136
|
+
'Loading prompt with variables',
|
|
137
|
+
{ templateName, variableCount: Object.keys(variables).length }
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
// Load template
|
|
142
|
+
const template = await loadTemplate(templateName, baseDir);
|
|
143
|
+
|
|
144
|
+
// Replace variables
|
|
145
|
+
const prompt = replaceTemplate(template, variables);
|
|
146
|
+
|
|
147
|
+
logger.debug(
|
|
148
|
+
'prompt-builder - loadPrompt',
|
|
149
|
+
'Prompt loaded successfully',
|
|
150
|
+
{ templateName, promptLength: prompt.length }
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
return prompt;
|
|
154
|
+
|
|
155
|
+
} catch (error) {
|
|
156
|
+
logger.error(
|
|
157
|
+
'prompt-builder - loadPrompt',
|
|
158
|
+
`Failed to load prompt: ${templateName}`,
|
|
159
|
+
error
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
107
166
|
/**
|
|
108
167
|
* Formats file information for prompt
|
|
109
168
|
* Why: Structures file data in readable format for Claude
|
|
@@ -144,6 +203,7 @@ const formatFileSection = ({ path, diff, content, isNew }) => {
|
|
|
144
203
|
* @param {string} options.guidelinesName - Guidelines filename
|
|
145
204
|
* @param {Array<Object>} options.files - Array of file data objects
|
|
146
205
|
* @param {Object} options.metadata - Additional metadata (repo name, branch, etc.)
|
|
206
|
+
* @param {Object} options.subagentConfig - Subagent configuration (optional)
|
|
147
207
|
* @returns {Promise<string>} Complete analysis prompt
|
|
148
208
|
*
|
|
149
209
|
* File data object structure:
|
|
@@ -158,12 +218,13 @@ const buildAnalysisPrompt = async ({
|
|
|
158
218
|
templateName = 'CLAUDE_ANALYSIS_PROMPT_SONAR.md',
|
|
159
219
|
guidelinesName = 'CLAUDE_PRE_COMMIT_SONAR.md',
|
|
160
220
|
files = [],
|
|
161
|
-
metadata = {}
|
|
221
|
+
metadata = {},
|
|
222
|
+
subagentConfig = null
|
|
162
223
|
} = {}) => {
|
|
163
224
|
logger.debug(
|
|
164
225
|
'prompt-builder - buildAnalysisPrompt',
|
|
165
226
|
'Building analysis prompt',
|
|
166
|
-
{ templateName, guidelinesName, fileCount: files.length }
|
|
227
|
+
{ templateName, guidelinesName, fileCount: files.length, subagentsEnabled: subagentConfig?.enabled }
|
|
167
228
|
);
|
|
168
229
|
|
|
169
230
|
try {
|
|
@@ -176,6 +237,22 @@ const buildAnalysisPrompt = async ({
|
|
|
176
237
|
// Start with template
|
|
177
238
|
let prompt = template;
|
|
178
239
|
|
|
240
|
+
// Add subagent instruction if enabled and 3+ files
|
|
241
|
+
if (subagentConfig?.enabled && files.length >= 3) {
|
|
242
|
+
try {
|
|
243
|
+
const subagentInstruction = await loadTemplate('SUBAGENT_INSTRUCTION.md');
|
|
244
|
+
const subagentVariables = {
|
|
245
|
+
BATCH_SIZE: subagentConfig.batchSize || 3,
|
|
246
|
+
MODEL: subagentConfig.model || 'haiku'
|
|
247
|
+
};
|
|
248
|
+
prompt += '\n\n' + replaceTemplate(subagentInstruction, subagentVariables) + '\n';
|
|
249
|
+
|
|
250
|
+
logger.info(`🚀 Batch optimization enabled: ${files.length} files, ${subagentVariables.BATCH_SIZE} per batch, ${subagentVariables.MODEL} model`);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
logger.warning('Subagent instruction template not found, proceeding without parallel analysis');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
179
256
|
// Add guidelines section
|
|
180
257
|
prompt += '\n\n=== EVALUATION GUIDELINES ===\n';
|
|
181
258
|
prompt += guidelines;
|
|
@@ -212,72 +289,11 @@ const buildAnalysisPrompt = async ({
|
|
|
212
289
|
}
|
|
213
290
|
};
|
|
214
291
|
|
|
215
|
-
/**
|
|
216
|
-
* Builds commit message generation prompt
|
|
217
|
-
* Why: Used by prepare-commit-msg hook
|
|
218
|
-
*
|
|
219
|
-
* @param {Object} options - Build options
|
|
220
|
-
* @param {Array<Object>} options.files - Array of changed files with diffs
|
|
221
|
-
* @param {Object} options.stats - Staging statistics
|
|
222
|
-
* @returns {Promise<string>} Complete commit message prompt
|
|
223
|
-
*
|
|
224
|
-
* Stats object structure:
|
|
225
|
-
* {
|
|
226
|
-
* totalFiles: number,
|
|
227
|
-
* addedFiles: number,
|
|
228
|
-
* modifiedFiles: number,
|
|
229
|
-
* deletedFiles: number,
|
|
230
|
-
* insertions: number,
|
|
231
|
-
* deletions: number
|
|
232
|
-
* }
|
|
233
|
-
*/
|
|
234
|
-
const buildCommitMessagePrompt = async ({ files = [], stats = {} } = {}) => {
|
|
235
|
-
logger.debug(
|
|
236
|
-
'prompt-builder - buildCommitMessagePrompt',
|
|
237
|
-
'Building commit message prompt',
|
|
238
|
-
{ fileCount: files.length, stats }
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
let prompt = `Generate a conventional commit message for the following changes.\n\n`;
|
|
242
|
-
|
|
243
|
-
// Add statistics
|
|
244
|
-
prompt += `=== STATISTICS ===\n`;
|
|
245
|
-
prompt += `Files changed: ${stats.totalFiles || files.length}\n`;
|
|
246
|
-
prompt += `Added: ${stats.addedFiles || 0}, Modified: ${stats.modifiedFiles || 0}, Deleted: ${stats.deletedFiles || 0}\n`;
|
|
247
|
-
prompt += `Insertions: ${stats.insertions || 0}, Deletions: ${stats.deletions || 0}\n\n`;
|
|
248
|
-
|
|
249
|
-
// Add file changes
|
|
250
|
-
prompt += `=== CHANGED FILES ===\n`;
|
|
251
|
-
files.forEach(({ path, diff }) => {
|
|
252
|
-
prompt += `\n--- ${path} ---\n`;
|
|
253
|
-
if (diff) {
|
|
254
|
-
prompt += `${diff}\n`;
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// Add instructions
|
|
259
|
-
prompt += `\n\n=== INSTRUCTIONS ===\n`;
|
|
260
|
-
prompt += `Generate a concise commit message following Conventional Commits format:\n`;
|
|
261
|
-
prompt += `- type: feat, fix, docs, style, refactor, test, chore\n`;
|
|
262
|
-
prompt += `- Format: "type: description" or "type(scope): description"\n`;
|
|
263
|
-
prompt += `- Description: Clear, imperative mood, no period at end\n`;
|
|
264
|
-
prompt += `- Optional body: Detailed explanation if needed\n\n`;
|
|
265
|
-
prompt += `Respond with ONLY the commit message, no explanations.\n`;
|
|
266
|
-
|
|
267
|
-
logger.debug(
|
|
268
|
-
'prompt-builder - buildCommitMessagePrompt',
|
|
269
|
-
'Commit message prompt built',
|
|
270
|
-
{ promptLength: prompt.length }
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
return prompt;
|
|
274
|
-
};
|
|
275
|
-
|
|
276
292
|
export {
|
|
277
293
|
PromptBuilderError,
|
|
278
294
|
loadTemplate,
|
|
279
295
|
replaceTemplate,
|
|
296
|
+
loadPrompt,
|
|
280
297
|
formatFileSection,
|
|
281
|
-
buildAnalysisPrompt
|
|
282
|
-
buildCommitMessagePrompt
|
|
298
|
+
buildAnalysisPrompt
|
|
283
299
|
};
|
|
@@ -179,14 +179,20 @@ ${content}
|
|
|
179
179
|
const generateResolutionPrompt = async (
|
|
180
180
|
analysisResult,
|
|
181
181
|
{
|
|
182
|
-
outputPath =
|
|
182
|
+
outputPath = null,
|
|
183
183
|
templatePath = '.claude/CLAUDE_RESOLUTION_PROMPT.md',
|
|
184
184
|
fileCount = 0
|
|
185
185
|
} = {}
|
|
186
186
|
) => {
|
|
187
187
|
// Why: Use repo root for absolute paths (works on Windows/PowerShell/Git Bash)
|
|
188
188
|
const repoRoot = getRepoRoot();
|
|
189
|
-
|
|
189
|
+
|
|
190
|
+
// Load config to get default output path
|
|
191
|
+
const { getConfig } = await import('../config.js');
|
|
192
|
+
const config = await getConfig();
|
|
193
|
+
const finalOutputPath = outputPath || config.output.resolutionFile;
|
|
194
|
+
|
|
195
|
+
const absoluteOutputPath = path.join(repoRoot, finalOutputPath);
|
|
190
196
|
const absoluteTemplatePath = path.join(repoRoot, templatePath);
|
|
191
197
|
|
|
192
198
|
logger.debug(
|
|
@@ -226,6 +232,10 @@ const generateResolutionPrompt = async (
|
|
|
226
232
|
.replace(/{{BLOCKING_ISSUES}}/g, issuesFormatted)
|
|
227
233
|
.replace(/{{FILE_CONTENTS}}/g, fileContentsFormatted);
|
|
228
234
|
|
|
235
|
+
// Ensure output directory exists
|
|
236
|
+
const outputDir = path.dirname(absoluteOutputPath);
|
|
237
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
238
|
+
|
|
229
239
|
// Write resolution prompt file
|
|
230
240
|
await fs.writeFile(absoluteOutputPath, prompt, 'utf8');
|
|
231
241
|
|
package/package.json
CHANGED
|
@@ -1,52 +1,51 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
2
|
+
"name": "claude-git-hooks",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "Git hooks with Claude CLI for code analysis and automatic commit messages",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"claude-hooks": "./bin/claude-hooks"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
11
|
+
"test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
|
|
12
|
+
"test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
|
|
13
|
+
"lint": "eslint lib/ bin/",
|
|
14
|
+
"lint:fix": "eslint lib/ bin/ --fix",
|
|
15
|
+
"format": "prettier --write \"lib/**/*.js\" \"bin/**\""
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"git",
|
|
19
|
+
"hooks",
|
|
20
|
+
"claude",
|
|
21
|
+
"ai",
|
|
22
|
+
"code-review",
|
|
23
|
+
"commit-messages",
|
|
24
|
+
"pre-commit",
|
|
25
|
+
"automation"
|
|
26
|
+
],
|
|
27
|
+
"author": "Pablo Rovito",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/pablorovito/claude-git-hooks.git"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=16.9.0"
|
|
35
|
+
},
|
|
36
|
+
"preferGlobal": true,
|
|
37
|
+
"files": [
|
|
38
|
+
"bin/",
|
|
39
|
+
"lib/",
|
|
40
|
+
"templates/",
|
|
41
|
+
"README.md",
|
|
42
|
+
"CHANGELOG.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/jest": "^29.5.0",
|
|
47
|
+
"eslint": "^8.57.0",
|
|
48
|
+
"jest": "^29.7.0",
|
|
49
|
+
"prettier": "^3.2.0"
|
|
50
|
+
}
|
|
52
51
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Analyze the following changes. CONTEXT: {{CONTEXT_DESCRIPTION}}
|
|
2
|
+
{{SUBAGENT_INSTRUCTION}}
|
|
3
|
+
Please generate:
|
|
4
|
+
1. A concise and descriptive PR title (maximum 72 characters)
|
|
5
|
+
2. A detailed PR description that includes:
|
|
6
|
+
- Summary of changes
|
|
7
|
+
- Motivation/context
|
|
8
|
+
- Type of change (feature/fix/refactor/docs/etc)
|
|
9
|
+
- Recommended testing
|
|
10
|
+
3. A suggested branch name following the format: type/short-description (example: feature/add-user-auth, fix/memory-leak)
|
|
11
|
+
|
|
12
|
+
IMPORTANT: If these are local changes without push, the suggested branch name should be for creating a new branch from the current one.
|
|
13
|
+
|
|
14
|
+
Respond EXCLUSIVELY with a valid JSON with this structure:
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"prTitle": "Interesting PR title",
|
|
18
|
+
"prDescription": "detailed PR description with markdown",
|
|
19
|
+
"suggestedBranchName": "type/suggested-branch-name",
|
|
20
|
+
"changeType": "feature|fix|refactor|docs|test|chore",
|
|
21
|
+
"breakingChanges": false,
|
|
22
|
+
"testingNotes": "notes on necessary testing or 'None'"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## COMMITS
|
|
27
|
+
{{COMMITS}}
|
|
28
|
+
|
|
29
|
+
## CHANGED FILES
|
|
30
|
+
{{DIFF_FILES}}
|
|
31
|
+
|
|
32
|
+
## FULL DIFF
|
|
33
|
+
{{FULL_DIFF}}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Analyze the following changes and generate a commit message following the Conventional Commits format.
|
|
2
|
+
|
|
3
|
+
Respond ONLY with a valid JSON:
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"type": "feat|fix|docs|style|refactor|test|chore|ci|perf",
|
|
8
|
+
"scope": "optional scope (e.g.: api, frontend, db)",
|
|
9
|
+
"title": "short description in present tense (max 50 chars)",
|
|
10
|
+
"body": "optional detailed description"
|
|
11
|
+
}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## CHANGES TO ANALYZE
|
|
15
|
+
|
|
16
|
+
### Modified files:
|
|
17
|
+
{{FILE_LIST}}
|
|
18
|
+
|
|
19
|
+
### Summary of changes:
|
|
20
|
+
Files changed: {{FILE_COUNT}}
|
|
21
|
+
Insertions: {{INSERTIONS}}, Deletions: {{DELETIONS}}
|
|
22
|
+
|
|
23
|
+
### Detailed diffs:
|
|
24
|
+
{{FILE_DIFFS}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
IMPORTANT OPTIMIZATION: When analyzing multiple files (3+), mentally organize your analysis into focused batches of {{BATCH_SIZE}} files at a time. This helps maintain quality while processing efficiently. For each file, perform thorough analysis following all guidelines and OUTPUT_SCHEMA requirements. After analyzing all files, consolidate into SINGLE JSON response: (1) merge all blockingIssues arrays, (2) merge all details arrays, (3) sum issue counts across all files, (4) worst-case metrics (lowest rating found), (5) QUALITY_GATE=FAILED if ANY file has blockers/criticals, (6) approved=false if any file is disapproved. Your response must be a single consolidated JSON object, not separate results per file.
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
You are analyzing a **{{PRESET_NAME}}** project with the following technology stack:
|
|
2
|
+
|
|
3
|
+
**Tech Stack:** {{TECH_STACK}}
|
|
4
|
+
|
|
5
|
+
**Analyzing files matching:** {{FILE_EXTENSIONS}}
|
|
6
|
+
|
|
7
|
+
## Your Task
|
|
8
|
+
|
|
9
|
+
Perform a comprehensive code quality analysis focusing on these areas:
|
|
10
|
+
|
|
11
|
+
{{FOCUS_AREAS}}
|
|
12
|
+
|
|
13
|
+
## Analysis Guidelines
|
|
14
|
+
|
|
15
|
+
1. **Claude API Best Practices**:
|
|
16
|
+
- Proper use of Claude API endpoints
|
|
17
|
+
- Correct model selection (haiku/sonnet/opus)
|
|
18
|
+
- Token usage optimization
|
|
19
|
+
- Error handling for API failures
|
|
20
|
+
- Rate limiting considerations
|
|
21
|
+
- Timeout handling
|
|
22
|
+
|
|
23
|
+
2. **Prompt Engineering**:
|
|
24
|
+
- Clear and specific instructions
|
|
25
|
+
- Well-structured prompts
|
|
26
|
+
- Appropriate context inclusion
|
|
27
|
+
- Effective use of examples
|
|
28
|
+
- Proper output format specifications
|
|
29
|
+
- Token-efficient prompting
|
|
30
|
+
|
|
31
|
+
3. **CLI User Experience**:
|
|
32
|
+
- Clear, helpful error messages
|
|
33
|
+
- Appropriate use of colors/formatting
|
|
34
|
+
- Progress indicators for long operations
|
|
35
|
+
- Helpful usage instructions
|
|
36
|
+
- Graceful error recovery
|
|
37
|
+
- Cross-platform compatibility
|
|
38
|
+
|
|
39
|
+
4. **Git Operations**:
|
|
40
|
+
- Safe git command execution
|
|
41
|
+
- Proper error handling
|
|
42
|
+
- Repository state validation
|
|
43
|
+
- Avoiding destructive operations
|
|
44
|
+
- Cross-platform path handling
|
|
45
|
+
|
|
46
|
+
5. **Security**:
|
|
47
|
+
- API key protection (never log/expose)
|
|
48
|
+
- Secure credential storage
|
|
49
|
+
- Input validation
|
|
50
|
+
- Avoiding command injection
|
|
51
|
+
- Sensitive data handling in prompts
|
|
52
|
+
|
|
53
|
+
6. **Code Quality**:
|
|
54
|
+
- Proper error handling
|
|
55
|
+
- Comprehensive logging
|
|
56
|
+
- Modular, reusable functions
|
|
57
|
+
- Clear documentation
|
|
58
|
+
- Maintainable code structure
|
|
59
|
+
|
|
60
|
+
## Specific Checks
|
|
61
|
+
|
|
62
|
+
### Claude API Usage
|
|
63
|
+
✅ Using appropriate model for task (haiku for simple, sonnet for complex)
|
|
64
|
+
✅ Implementing proper error handling (network, API, rate limit)
|
|
65
|
+
✅ Token usage calculated and optimized
|
|
66
|
+
✅ Prompts are well-structured and clear
|
|
67
|
+
✅ Output parsing is robust
|
|
68
|
+
✅ API keys never logged or exposed
|
|
69
|
+
|
|
70
|
+
### Git Operations
|
|
71
|
+
✅ Using proper git commands
|
|
72
|
+
✅ Handling errors gracefully
|
|
73
|
+
✅ Cross-platform path compatibility
|
|
74
|
+
✅ Avoiding destructive operations without confirmation
|
|
75
|
+
✅ Proper handling of special characters in filenames
|
|
76
|
+
|
|
77
|
+
### Template Quality
|
|
78
|
+
✅ Clear instructions for Claude
|
|
79
|
+
✅ Well-defined output format
|
|
80
|
+
✅ Appropriate context provided
|
|
81
|
+
✅ Token-efficient design
|
|
82
|
+
✅ Placeholders used correctly
|
|
83
|
+
|
|
84
|
+
## Output Format
|
|
85
|
+
|
|
86
|
+
Respond with a valid JSON following the SonarQube format:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"QUALITY_GATE": "PASSED|FAILED",
|
|
91
|
+
"approved": true|false,
|
|
92
|
+
"metrics": {
|
|
93
|
+
"reliability": "A|B|C|D|E",
|
|
94
|
+
"security": "A|B|C|D|E",
|
|
95
|
+
"maintainability": "A|B|C|D|E",
|
|
96
|
+
"coverage": 0-100,
|
|
97
|
+
"duplications": 0-100,
|
|
98
|
+
"complexity": "number"
|
|
99
|
+
},
|
|
100
|
+
"issues": {
|
|
101
|
+
"blocker": 0,
|
|
102
|
+
"critical": 0,
|
|
103
|
+
"major": 0,
|
|
104
|
+
"minor": 0,
|
|
105
|
+
"info": 0
|
|
106
|
+
},
|
|
107
|
+
"details": [
|
|
108
|
+
{
|
|
109
|
+
"severity": "BLOCKER|CRITICAL|MAJOR|MINOR|INFO",
|
|
110
|
+
"type": "BUG|VULNERABILITY|CODE_SMELL|PROMPT_QUALITY",
|
|
111
|
+
"file": "path/to/file",
|
|
112
|
+
"line": 123,
|
|
113
|
+
"message": "Clear description of the issue"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"securityHotspots": 0,
|
|
117
|
+
"blockingIssues": ["List of critical issues that must be fixed"]
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Analysis Rules
|
|
122
|
+
|
|
123
|
+
- **Block commit** if:
|
|
124
|
+
- Exposed API keys or secrets
|
|
125
|
+
- Security vulnerabilities
|
|
126
|
+
- Critical bugs in git operations
|
|
127
|
+
- Destructive operations without safeguards
|
|
128
|
+
|
|
129
|
+
- **Pass** if: Only minor issues, suggestions, or no issues
|
|
130
|
+
|
|
131
|
+
- Be constructive about prompt quality - suggest improvements
|
|
132
|
+
- Focus on safety and user experience
|
|
133
|
+
- Provide actionable, specific feedback with line numbers
|