commic 1.0.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.
Files changed (50) hide show
  1. package/.husky/pre-commit +2 -0
  2. package/README.md +306 -0
  3. package/biome.json +50 -0
  4. package/dist/ai/AIService.d.ts +51 -0
  5. package/dist/ai/AIService.d.ts.map +1 -0
  6. package/dist/ai/AIService.js +351 -0
  7. package/dist/ai/AIService.js.map +1 -0
  8. package/dist/config/ConfigManager.d.ts +49 -0
  9. package/dist/config/ConfigManager.d.ts.map +1 -0
  10. package/dist/config/ConfigManager.js +124 -0
  11. package/dist/config/ConfigManager.js.map +1 -0
  12. package/dist/errors/CustomErrors.d.ts +54 -0
  13. package/dist/errors/CustomErrors.d.ts.map +1 -0
  14. package/dist/errors/CustomErrors.js +99 -0
  15. package/dist/errors/CustomErrors.js.map +1 -0
  16. package/dist/git/GitService.d.ts +77 -0
  17. package/dist/git/GitService.d.ts.map +1 -0
  18. package/dist/git/GitService.js +219 -0
  19. package/dist/git/GitService.js.map +1 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +48 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/orchestrator/MainOrchestrator.d.ts +63 -0
  25. package/dist/orchestrator/MainOrchestrator.d.ts.map +1 -0
  26. package/dist/orchestrator/MainOrchestrator.js +225 -0
  27. package/dist/orchestrator/MainOrchestrator.js.map +1 -0
  28. package/dist/types/index.d.ts +55 -0
  29. package/dist/types/index.d.ts.map +1 -0
  30. package/dist/types/index.js +2 -0
  31. package/dist/types/index.js.map +1 -0
  32. package/dist/ui/UIManager.d.ts +118 -0
  33. package/dist/ui/UIManager.d.ts.map +1 -0
  34. package/dist/ui/UIManager.js +369 -0
  35. package/dist/ui/UIManager.js.map +1 -0
  36. package/dist/validation/ConventionalCommitsValidator.d.ts +33 -0
  37. package/dist/validation/ConventionalCommitsValidator.d.ts.map +1 -0
  38. package/dist/validation/ConventionalCommitsValidator.js +114 -0
  39. package/dist/validation/ConventionalCommitsValidator.js.map +1 -0
  40. package/package.json +49 -0
  41. package/src/ai/AIService.ts +413 -0
  42. package/src/config/ConfigManager.ts +141 -0
  43. package/src/errors/CustomErrors.ts +176 -0
  44. package/src/git/GitService.ts +246 -0
  45. package/src/index.ts +55 -0
  46. package/src/orchestrator/MainOrchestrator.ts +263 -0
  47. package/src/types/index.ts +60 -0
  48. package/src/ui/UIManager.ts +420 -0
  49. package/src/validation/ConventionalCommitsValidator.ts +139 -0
  50. package/tsconfig.json +24 -0
@@ -0,0 +1,369 @@
1
+ import boxen from 'boxen';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import ora from 'ora';
5
+ /**
6
+ * Manages terminal UI rendering and visual feedback
7
+ * Provides consistent, colorful interface with emojis and loading indicators
8
+ */
9
+ export class UIManager {
10
+ colors = {
11
+ primary: chalk.cyan,
12
+ success: chalk.green,
13
+ error: chalk.red,
14
+ warning: chalk.yellow,
15
+ info: chalk.blue,
16
+ muted: chalk.gray,
17
+ };
18
+ /**
19
+ * Display welcome message with branding
20
+ */
21
+ showWelcome() {
22
+ const welcomeText = chalk.bold.cyan('Commic') +
23
+ '\n' +
24
+ chalk.gray('AI-powered commit messages with Conventional Commits') +
25
+ '\n\n' +
26
+ this.colors.muted('✨ Features:') +
27
+ '\n' +
28
+ ' • ' +
29
+ this.colors.primary('Automated commit message generation') +
30
+ '\n' +
31
+ ' • ' +
32
+ this.colors.primary('Conventional Commits specification') +
33
+ '\n' +
34
+ ' • ' +
35
+ this.colors.primary('Multiple AI-generated suggestions') +
36
+ '\n' +
37
+ ' • ' +
38
+ this.colors.primary('Smart diff analysis') +
39
+ '\n\n' +
40
+ this.colors.muted('📋 How it works:') +
41
+ '\n' +
42
+ ' 1. Analyzes your Git changes' +
43
+ '\n' +
44
+ ' 2. Generates commit message suggestions' +
45
+ '\n' +
46
+ ' 3. Lets you choose the best one' +
47
+ '\n' +
48
+ ' 4. Creates the commit automatically';
49
+ console.log('\n' +
50
+ boxen(welcomeText, {
51
+ padding: 1,
52
+ margin: 1,
53
+ borderStyle: 'round',
54
+ borderColor: 'cyan',
55
+ }) +
56
+ '\n');
57
+ }
58
+ /**
59
+ * Display success message with checkmark emoji
60
+ * @param message Success message to display
61
+ */
62
+ showSuccess(message) {
63
+ console.log(`\n${this.colors.success(`✨ ${message}`)}\n\n`);
64
+ }
65
+ /**
66
+ * Display error message with cross emoji
67
+ * @param message Error message to display
68
+ * @param details Optional detailed error information
69
+ */
70
+ showError(message, details) {
71
+ console.log(`\n${this.colors.error(`❌ Error: ${message}`)}`);
72
+ if (details) {
73
+ console.log(this.colors.muted(` ${details}`));
74
+ }
75
+ console.log('\n');
76
+ }
77
+ /**
78
+ * Display error with suggestion
79
+ * @param message Error message
80
+ * @param suggestion Actionable suggestion for user
81
+ */
82
+ showErrorWithSuggestion(message, suggestion) {
83
+ console.log(`\n${this.colors.error(`❌ Error: ${message}`)}`);
84
+ console.log(`${this.colors.info(`💡 Suggestion: ${suggestion}`)}\n\n`);
85
+ }
86
+ /**
87
+ * Display informational message with bulb emoji
88
+ * @param message Info message to display
89
+ */
90
+ showInfo(message) {
91
+ console.log(`\n${this.colors.info(`💡 ${message}`)}\n\n`);
92
+ }
93
+ /**
94
+ * Display warning message
95
+ * @param message Warning message to display
96
+ */
97
+ showWarning(message) {
98
+ console.log(`\n${this.colors.warning(`⚠️ ${message}`)}\n\n`);
99
+ }
100
+ /**
101
+ * Apply muted (gray) color to text
102
+ * @param text Text to color
103
+ * @returns Colored text string
104
+ */
105
+ muted(text) {
106
+ return this.colors.muted(text);
107
+ }
108
+ /**
109
+ * Create and start a loading spinner
110
+ * @param message Loading message to display
111
+ * @returns Ora spinner instance
112
+ */
113
+ showLoading(message) {
114
+ return ora({
115
+ text: message,
116
+ color: 'cyan',
117
+ spinner: 'dots',
118
+ }).start();
119
+ }
120
+ /**
121
+ * Display a section header
122
+ * @param title Section title
123
+ */
124
+ showSectionHeader(title) {
125
+ console.log(`\n${this.colors.primary.bold(title)}`);
126
+ console.log(this.colors.muted('─'.repeat(Math.max(title.length, 50))));
127
+ console.log();
128
+ }
129
+ /**
130
+ * Display formatted commit message preview
131
+ * @param message Commit message to preview
132
+ * @param index Optional index number
133
+ */
134
+ showCommitPreview(message, index) {
135
+ const prefix = index !== undefined ? `${index + 1}. ` : ' ';
136
+ const lines = message.split('\n');
137
+ console.log(this.colors.muted(prefix) + this.colors.primary(lines[0]));
138
+ if (lines.length > 1) {
139
+ lines.slice(1).forEach((line) => {
140
+ if (line.trim()) {
141
+ console.log(this.colors.muted(` ${line}`));
142
+ }
143
+ });
144
+ }
145
+ console.log();
146
+ }
147
+ /**
148
+ * Clear the console
149
+ */
150
+ clear() {
151
+ console.clear();
152
+ }
153
+ /**
154
+ * Display a blank line
155
+ */
156
+ newLine() {
157
+ console.log();
158
+ }
159
+ /**
160
+ * Display repository information banner
161
+ * @param repoName Repository name
162
+ * @param branch Current branch
163
+ * @param repoPath Repository path
164
+ * @param remoteUrl Optional remote repository URL
165
+ */
166
+ showRepositoryInfo(repoName, branch, repoPath, remoteUrl) {
167
+ console.log();
168
+ console.log(this.colors.primary.bold('📦 Repository Information'));
169
+ console.log(this.colors.muted('─'.repeat(50)));
170
+ console.log();
171
+ console.log(` ${this.colors.primary('📁 Repository: ')}${chalk.bold.white(repoName)}`);
172
+ console.log(` ${this.colors.primary('🌿 Branch: ')}${chalk.bold.green(branch)}`);
173
+ if (remoteUrl) {
174
+ console.log(` ${this.colors.primary('🔗 Remote: ')}${this.colors.muted(remoteUrl)}`);
175
+ }
176
+ console.log(` ${this.colors.muted('📍 Path: ')}${this.colors.muted(repoPath)}`);
177
+ console.log();
178
+ console.log(this.colors.muted('─'.repeat(50)));
179
+ console.log();
180
+ }
181
+ /**
182
+ * Display change statistics
183
+ * @param stats Statistics object with files, insertions, deletions
184
+ */
185
+ showChangeStats(stats) {
186
+ const { filesChanged, insertions, deletions } = stats;
187
+ console.log();
188
+ console.log(this.colors.primary.bold('📊 Changes Summary'));
189
+ console.log(this.colors.muted('─'.repeat(50)));
190
+ console.log();
191
+ const fileText = filesChanged === 1 ? 'file' : 'files';
192
+ console.log(` ${chalk.bold.white(filesChanged)} ${fileText} changed`);
193
+ if (insertions > 0) {
194
+ console.log(` ${chalk.bold.green(`+${insertions}`)} insertions`);
195
+ }
196
+ if (deletions > 0) {
197
+ console.log(` ${chalk.bold.red(`-${deletions}`)} deletions`);
198
+ }
199
+ const totalChanges = insertions + deletions;
200
+ if (totalChanges > 0) {
201
+ console.log(` ${chalk.bold.cyan(`Total: ${totalChanges} lines`)} changed`);
202
+ }
203
+ console.log();
204
+ console.log(this.colors.muted('─'.repeat(50)));
205
+ console.log();
206
+ }
207
+ /**
208
+ * Display AI generation info
209
+ * @param model Model name being used
210
+ * @param suggestionCount Number of suggestions generated
211
+ */
212
+ showAIGenerationInfo(model, suggestionCount) {
213
+ console.log(this.colors.muted(` 🤖 Model: ${chalk.cyan.bold(model)}`));
214
+ console.log(this.colors.muted(` 📝 Generating ${chalk.cyan.bold(suggestionCount)} commit message suggestions...`));
215
+ console.log();
216
+ }
217
+ /**
218
+ * Prompt user for API key
219
+ * @returns Entered API key
220
+ */
221
+ async promptForApiKey() {
222
+ const answer = await inquirer.prompt([
223
+ {
224
+ type: 'password',
225
+ name: 'apiKey',
226
+ message: 'Enter your Gemini API key:',
227
+ mask: '*',
228
+ validate: (input) => {
229
+ if (!input || input.trim().length === 0) {
230
+ return 'API key cannot be empty';
231
+ }
232
+ if (input.length < 20) {
233
+ return 'API key seems too short. Please check and try again.';
234
+ }
235
+ return true;
236
+ },
237
+ },
238
+ ]);
239
+ return answer.apiKey.trim();
240
+ }
241
+ /**
242
+ * Prompt user to select a Gemini model
243
+ * @param models Available model options
244
+ * @returns Selected model
245
+ */
246
+ async promptForModel(models) {
247
+ const answer = await inquirer.prompt([
248
+ {
249
+ type: 'list',
250
+ name: 'model',
251
+ message: 'Select Gemini model:',
252
+ choices: models.map((model) => {
253
+ if (model === 'gemini-2.5-flash') {
254
+ return {
255
+ name: `${model} ${chalk.gray('(stable)')}`,
256
+ value: model,
257
+ };
258
+ }
259
+ else if (model === 'gemini-flash-latest') {
260
+ return {
261
+ name: `${model} ${chalk.gray('(always latest, recommended)')}`,
262
+ value: model,
263
+ };
264
+ }
265
+ return {
266
+ name: model,
267
+ value: model,
268
+ };
269
+ }),
270
+ default: 'gemini-flash-latest',
271
+ },
272
+ ]);
273
+ return answer.model;
274
+ }
275
+ /**
276
+ * Prompt user to select a commit message from suggestions
277
+ * @param suggestions Array of commit message suggestions
278
+ * @returns Index of selected suggestion, or -1 if cancelled
279
+ */
280
+ async promptForCommitSelection(suggestions) {
281
+ this.showSectionHeader('📝 Select a commit message');
282
+ this.newLine();
283
+ // Show all suggestions with more detail
284
+ console.log(this.colors.muted('Available suggestions:'));
285
+ console.log();
286
+ suggestions.forEach((suggestion, index) => {
287
+ const lines = suggestion.message.split('\n');
288
+ const firstLine = lines[0];
289
+ const hasBody = lines.length > 1;
290
+ console.log(` ${this.colors.primary.bold(`${index + 1}.`)} ${this.colors.primary(firstLine)}`);
291
+ if (hasBody) {
292
+ lines.slice(1).forEach((line) => {
293
+ if (line.trim()) {
294
+ console.log(this.colors.muted(` ${line}`));
295
+ }
296
+ });
297
+ console.log();
298
+ }
299
+ else {
300
+ console.log();
301
+ }
302
+ });
303
+ console.log();
304
+ const choices = suggestions.map((suggestion, index) => {
305
+ const lines = suggestion.message.split('\n');
306
+ const firstLine = lines[0];
307
+ const hasBody = lines.length > 1;
308
+ return {
309
+ name: hasBody ? `${firstLine} ${chalk.gray('(multi-line)')}` : firstLine,
310
+ value: index,
311
+ short: firstLine,
312
+ };
313
+ });
314
+ // Add cancel option
315
+ choices.push({
316
+ name: chalk.red("✖ Cancel (don't commit)"),
317
+ value: -1,
318
+ short: 'Cancelled',
319
+ });
320
+ const answer = await inquirer.prompt([
321
+ {
322
+ type: 'list',
323
+ name: 'selection',
324
+ message: 'Choose a commit message:',
325
+ choices,
326
+ pageSize: 10,
327
+ loop: false,
328
+ },
329
+ ]);
330
+ // Show preview of selected message if not cancelled
331
+ if (answer.selection !== -1) {
332
+ this.newLine();
333
+ this.showSectionHeader('✅ Selected commit message');
334
+ console.log();
335
+ console.log(this.colors.muted('─'.repeat(50)));
336
+ console.log();
337
+ const messageLines = suggestions[answer.selection].message.split('\n');
338
+ messageLines.forEach((line) => {
339
+ if (line.trim()) {
340
+ console.log(` ${this.colors.primary(line)}`);
341
+ }
342
+ else {
343
+ console.log();
344
+ }
345
+ });
346
+ console.log();
347
+ console.log(this.colors.muted('─'.repeat(50)));
348
+ console.log();
349
+ }
350
+ return answer.selection;
351
+ }
352
+ /**
353
+ * Prompt for confirmation
354
+ * @param message Confirmation message
355
+ * @returns true if confirmed, false otherwise
356
+ */
357
+ async promptForConfirmation(message) {
358
+ const answer = await inquirer.prompt([
359
+ {
360
+ type: 'confirm',
361
+ name: 'confirmed',
362
+ message,
363
+ default: true,
364
+ },
365
+ ]);
366
+ return answer.confirmed;
367
+ }
368
+ }
369
+ //# sourceMappingURL=UIManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UIManager.js","sourceRoot":"","sources":["../../src/ui/UIManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { ParsedCommitMessage, ValidationResult } from '../types/index.js';
2
+ /**
3
+ * Validates commit messages against the Conventional Commits specification
4
+ * https://www.conventionalcommits.org/en/v1.0.0/
5
+ */
6
+ export declare class ConventionalCommitsValidator {
7
+ private static readonly VALID_TYPES;
8
+ private static readonly COMMIT_PATTERN;
9
+ /**
10
+ * Get list of valid commit types
11
+ * @returns Array of valid type strings
12
+ */
13
+ static getValidTypes(): string[];
14
+ /**
15
+ * Validate a commit message against Conventional Commits spec
16
+ * @param message Commit message to validate
17
+ * @returns ValidationResult with valid flag and any errors
18
+ */
19
+ static validate(message: string): ValidationResult;
20
+ /**
21
+ * Parse a commit message into its components
22
+ * @param message Commit message to parse
23
+ * @returns Parsed commit message structure
24
+ */
25
+ static parseCommitMessage(message: string): ParsedCommitMessage | null;
26
+ /**
27
+ * Check if a message is single-line (no body)
28
+ * @param message Commit message to check
29
+ * @returns true if single-line, false if multi-line
30
+ */
31
+ static isSingleLine(message: string): boolean;
32
+ }
33
+ //# sourceMappingURL=ConventionalCommitsValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConventionalCommitsValidator.d.ts","sourceRoot":"","sources":["../../src/validation/ConventionalCommitsValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE/E;;;GAGG;AACH,qBAAa,4BAA4B;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAWjC;IAIF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAyC;IAE/E;;;OAGG;IACH,MAAM,CAAC,aAAa,IAAI,MAAM,EAAE;IAIhC;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB;IA6DlD;;;;OAIG;IACH,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IA0BtE;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAI9C"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Validates commit messages against the Conventional Commits specification
3
+ * https://www.conventionalcommits.org/en/v1.0.0/
4
+ */
5
+ export class ConventionalCommitsValidator {
6
+ static VALID_TYPES = [
7
+ 'feat',
8
+ 'fix',
9
+ 'docs',
10
+ 'style',
11
+ 'refactor',
12
+ 'test',
13
+ 'chore',
14
+ 'perf',
15
+ 'ci',
16
+ 'build',
17
+ ];
18
+ // Regex pattern for Conventional Commits format
19
+ // Matches: type(scope)?: description or type(scope)?!: description
20
+ static COMMIT_PATTERN = /^(\w+)(\([a-z0-9-]+\))?(!)?:\s(.+)$/;
21
+ /**
22
+ * Get list of valid commit types
23
+ * @returns Array of valid type strings
24
+ */
25
+ static getValidTypes() {
26
+ return [...ConventionalCommitsValidator.VALID_TYPES];
27
+ }
28
+ /**
29
+ * Validate a commit message against Conventional Commits spec
30
+ * @param message Commit message to validate
31
+ * @returns ValidationResult with valid flag and any errors
32
+ */
33
+ static validate(message) {
34
+ const errors = [];
35
+ if (!message || message.trim().length === 0) {
36
+ errors.push('Commit message cannot be empty');
37
+ return { valid: false, errors };
38
+ }
39
+ // Split into lines to check subject and body separately
40
+ const lines = message.split('\n');
41
+ const subject = lines[0];
42
+ // Validate subject line format
43
+ const match = subject.match(ConventionalCommitsValidator.COMMIT_PATTERN);
44
+ if (!match) {
45
+ errors.push('Subject line must follow format: type(scope)?: description');
46
+ return { valid: false, errors };
47
+ }
48
+ const [, type, , breaking, description] = match;
49
+ // Validate type
50
+ if (!ConventionalCommitsValidator.VALID_TYPES.includes(type)) {
51
+ errors.push(`Invalid type "${type}". Must be one of: ${ConventionalCommitsValidator.VALID_TYPES.join(', ')}`);
52
+ }
53
+ // Validate description
54
+ if (!description || description.trim().length === 0) {
55
+ errors.push('Description cannot be empty');
56
+ }
57
+ // Check description starts with lowercase (Conventional Commits convention)
58
+ if (description && /^[A-Z]/.test(description)) {
59
+ errors.push('Description should start with lowercase letter');
60
+ }
61
+ // Validate subject line length (recommended max 72 characters)
62
+ if (subject.length > 72) {
63
+ errors.push('Subject line should be 72 characters or less');
64
+ }
65
+ // If multi-line, validate blank line between subject and body
66
+ if (lines.length > 1 && lines[1].trim() !== '') {
67
+ errors.push('There should be a blank line between subject and body');
68
+ }
69
+ // Check for breaking change notation
70
+ if (breaking === '!' || message.includes('BREAKING CHANGE:')) {
71
+ // This is valid - breaking changes are properly marked
72
+ // No error to add
73
+ }
74
+ return {
75
+ valid: errors.length === 0,
76
+ errors,
77
+ };
78
+ }
79
+ /**
80
+ * Parse a commit message into its components
81
+ * @param message Commit message to parse
82
+ * @returns Parsed commit message structure
83
+ */
84
+ static parseCommitMessage(message) {
85
+ const lines = message.split('\n');
86
+ const subject = lines[0];
87
+ const match = subject.match(ConventionalCommitsValidator.COMMIT_PATTERN);
88
+ if (!match) {
89
+ return null;
90
+ }
91
+ const [, type, scopeWithParens, breaking, description] = match;
92
+ // Extract scope without parentheses
93
+ const scope = scopeWithParens ? scopeWithParens.slice(1, -1) : undefined;
94
+ // Extract body (everything after the blank line)
95
+ const body = lines.length > 2 ? lines.slice(2).join('\n').trim() : undefined;
96
+ return {
97
+ type,
98
+ scope,
99
+ breaking: breaking === '!' || message.includes('BREAKING CHANGE:'),
100
+ description,
101
+ body,
102
+ };
103
+ }
104
+ /**
105
+ * Check if a message is single-line (no body)
106
+ * @param message Commit message to check
107
+ * @returns true if single-line, false if multi-line
108
+ */
109
+ static isSingleLine(message) {
110
+ const lines = message.split('\n').filter((line) => line.trim().length > 0);
111
+ return lines.length === 1;
112
+ }
113
+ }
114
+ //# sourceMappingURL=ConventionalCommitsValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConventionalCommitsValidator.js","sourceRoot":"","sources":["../../src/validation/ConventionalCommitsValidator.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "commic",
3
+ "version": "1.0.0",
4
+ "description": "AI-powered Git commit message generator with Conventional Commits support",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "commic": "./dist/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "npm run build && node dist/index.js",
13
+ "dev": "tsx src/index.ts",
14
+ "prepare": "husky",
15
+ "lint": "biome check .",
16
+ "lint:fix": "biome check --write --unsafe .",
17
+ "format": "biome format --write ."
18
+ },
19
+ "keywords": [
20
+ "git",
21
+ "commit",
22
+ "ai",
23
+ "gemini",
24
+ "conventional-commits",
25
+ "cli"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@google/generative-ai": "^0.21.0",
31
+ "boxen": "^8.0.1",
32
+ "chalk": "^5.4.1",
33
+ "commander": "^12.1.0",
34
+ "inquirer": "^12.2.0",
35
+ "ora": "^8.1.1",
36
+ "simple-git": "^3.27.0"
37
+ },
38
+ "devDependencies": {
39
+ "@biomejs/biome": "^2.3.11",
40
+ "@types/inquirer": "^9.0.7",
41
+ "@types/node": "^22.10.5",
42
+ "husky": "^9.1.7",
43
+ "tsx": "^4.19.2",
44
+ "typescript": "^5.7.3"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ }
49
+ }