korekt-cli 0.12.0 → 0.13.2
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 +34 -75
- package/package.json +1 -1
- package/src/config.js +0 -10
- package/src/index.js +30 -0
- package/src/index.test.js +115 -1
package/README.md
CHANGED
|
@@ -4,17 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/korekt-cli)
|
|
5
5
|
[](https://www.npmjs.com/package/korekt-cli)
|
|
6
6
|
|
|
7
|
-
AI-powered code review
|
|
8
|
-
|
|
9
|
-
`kk` integrates seamlessly with your local Git workflow to provide intelligent code reviews powered by AI.
|
|
10
|
-
|
|
11
|
-
## Features
|
|
12
|
-
|
|
13
|
-
* **AI-Powered Analysis**: Get instant, intelligent code reviews with severity levels, categories, and actionable suggestions
|
|
14
|
-
* **Local Git Integration**: Works with committed changes, staged changes, and unstaged modifications
|
|
15
|
-
* **Ticket Context Enrichment**: Server-side ticket extraction from branch names and commit messages (Jira & Azure DevOps)
|
|
16
|
-
* **Beautiful Output**: Color-coded issues with severity indicators, file locations, and suggested fixes
|
|
17
|
-
* **Ultra-Fast**: Short command syntax (`kk`) for maximum developer efficiency
|
|
7
|
+
AI-powered code review from your terminal.
|
|
18
8
|
|
|
19
9
|
## Installation
|
|
20
10
|
|
|
@@ -22,112 +12,81 @@ AI-powered code review CLI - Keep your kode korekt
|
|
|
22
12
|
npm install -g korekt-cli
|
|
23
13
|
```
|
|
24
14
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
Configure the CLI with your API credentials:
|
|
15
|
+
## Setup
|
|
28
16
|
|
|
29
17
|
```bash
|
|
30
18
|
kk config --key YOUR_API_KEY
|
|
31
|
-
kk config --endpoint https://api.korekt.ai/api/review
|
|
32
19
|
```
|
|
33
20
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Review committed changes against a target branch
|
|
38
|
-
kk review main
|
|
39
|
-
|
|
40
|
-
# Review only staged changes
|
|
41
|
-
kk stg
|
|
42
|
-
|
|
43
|
-
# Review only unstaged changes
|
|
44
|
-
kk diff
|
|
21
|
+
## Local Workflow
|
|
45
22
|
|
|
23
|
+
### Review Your Changes
|
|
46
24
|
|
|
25
|
+
```bash
|
|
26
|
+
kk review main # Review commits against main
|
|
27
|
+
kk stg # Review staged changes
|
|
28
|
+
kk diff # Review unstaged changes
|
|
47
29
|
```
|
|
48
30
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
### Configuration
|
|
31
|
+
### Choose AI Model
|
|
52
32
|
|
|
53
33
|
```bash
|
|
54
|
-
#
|
|
55
|
-
kk
|
|
56
|
-
|
|
57
|
-
# Set API endpoint
|
|
58
|
-
kk config --endpoint https://api.korekt.ai/api/review
|
|
59
|
-
|
|
60
|
-
# Show current configuration
|
|
61
|
-
kk config --show
|
|
34
|
+
kk review -m # Interactive model picker
|
|
35
|
+
kk review -m gemini-3-flash-preview # Direct selection
|
|
62
36
|
```
|
|
63
37
|
|
|
64
|
-
|
|
38
|
+
Available models (ranked by recommendation):
|
|
65
39
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
40
|
+
1. **gemini-3-flash-preview** - Most efficient, recommended for daily use
|
|
41
|
+
2. **gemini-3-pro-preview** - Best quality for complex reviews
|
|
42
|
+
3. **gemini-2.5-pro** - High quality alternative
|
|
43
|
+
4. **gemini-2.5-flash** - Legacy, avoid
|
|
69
44
|
|
|
70
|
-
|
|
71
|
-
kk review main
|
|
45
|
+
### Ignore Files
|
|
72
46
|
|
|
73
|
-
|
|
47
|
+
```bash
|
|
74
48
|
kk review main --ignore "*.lock" "dist/*"
|
|
49
|
+
```
|
|
75
50
|
|
|
76
|
-
|
|
77
|
-
kk review main --dry-run
|
|
51
|
+
## CI/CD Integration
|
|
78
52
|
|
|
79
|
-
|
|
80
|
-
kk review main --json
|
|
53
|
+
### Post to Pull Request
|
|
81
54
|
|
|
82
|
-
|
|
83
|
-
kk
|
|
84
|
-
|
|
55
|
+
```bash
|
|
56
|
+
kk review --comment # Auto-posts findings to PR
|
|
57
|
+
```
|
|
85
58
|
|
|
86
|
-
|
|
87
|
-
kk diff
|
|
59
|
+
Works with GitHub Actions, Azure Pipelines, and Bitbucket Pipelines.
|
|
88
60
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
61
|
+
### Post to Ticket
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
kk review --post-ticket # Posts findings to linked Jira/Azure ticket
|
|
92
65
|
```
|
|
93
66
|
|
|
94
|
-
|
|
67
|
+
Ticket IDs are automatically extracted from branch names and commit messages.
|
|
95
68
|
|
|
96
|
-
|
|
69
|
+
### JSON Output
|
|
97
70
|
|
|
98
71
|
```bash
|
|
99
|
-
|
|
72
|
+
kk review main --json # Machine-readable output
|
|
100
73
|
```
|
|
101
74
|
|
|
102
75
|
## Environment Variables
|
|
103
76
|
|
|
104
|
-
You can also configure using environment variables:
|
|
105
|
-
|
|
106
77
|
```bash
|
|
107
78
|
export KOREKT_API_KEY="your-api-key"
|
|
108
|
-
export KOREKT_API_ENDPOINT="https://api.korekt.ai/api/review"
|
|
109
79
|
```
|
|
110
80
|
|
|
111
|
-
|
|
81
|
+
Alternative to `kk config --key`. Config file takes precedence.
|
|
112
82
|
|
|
113
83
|
## Help
|
|
114
84
|
|
|
115
|
-
For more options and detailed help:
|
|
116
|
-
|
|
117
85
|
```bash
|
|
118
86
|
kk --help
|
|
119
87
|
kk review --help
|
|
120
88
|
```
|
|
121
89
|
|
|
122
|
-
## Development
|
|
123
|
-
|
|
124
|
-
To run tests:
|
|
125
|
-
```bash
|
|
126
|
-
npm test
|
|
127
|
-
```
|
|
128
|
-
|
|
129
90
|
## License
|
|
130
91
|
|
|
131
|
-
MIT
|
|
132
|
-
|
|
133
|
-
See [LICENSE](./LICENSE) for details.
|
|
92
|
+
MIT - See [LICENSE](./LICENSE) for details.
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -44,13 +44,3 @@ export function getApiEndpoint() {
|
|
|
44
44
|
export function setApiEndpoint(endpoint) {
|
|
45
45
|
config.set('apiEndpoint', endpoint);
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get all configuration
|
|
50
|
-
*/
|
|
51
|
-
export function getConfig() {
|
|
52
|
-
return {
|
|
53
|
-
apiKey: getApiKey(),
|
|
54
|
-
apiEndpoint: getApiEndpoint(),
|
|
55
|
-
};
|
|
56
|
-
}
|
package/src/index.js
CHANGED
|
@@ -72,6 +72,24 @@ async function confirmAction(message) {
|
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Handle skipped response from API (when integration mode prevents CLI review)
|
|
77
|
+
* @param {Object} response - Axios response object
|
|
78
|
+
* @param {Object} options - Command options (json flag, etc.)
|
|
79
|
+
* @param {Object} spinner - Ora spinner instance
|
|
80
|
+
* @returns {boolean} - True if response was skipped, false otherwise
|
|
81
|
+
*/
|
|
82
|
+
export function handleSkippedResponse(response, options, spinner) {
|
|
83
|
+
if (response.data.skipped) {
|
|
84
|
+
spinner.info(response.data.message || 'Review skipped.');
|
|
85
|
+
if (options.json) {
|
|
86
|
+
output(JSON.stringify(response.data, null, 2));
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
75
93
|
/**
|
|
76
94
|
* Available Gemini models for code review
|
|
77
95
|
*/
|
|
@@ -339,6 +357,12 @@ program
|
|
|
339
357
|
|
|
340
358
|
clearInterval(timer);
|
|
341
359
|
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
360
|
+
|
|
361
|
+
// Handle skipped response (integration mode prevents CLI review)
|
|
362
|
+
if (handleSkippedResponse(response, options, spinner)) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
342
366
|
spinner.succeed(`Review completed in ${elapsed}s!`);
|
|
343
367
|
|
|
344
368
|
// Handle --comment flag: post results to PR
|
|
@@ -523,6 +547,12 @@ async function reviewUncommitted(mode, options) {
|
|
|
523
547
|
|
|
524
548
|
clearInterval(timer);
|
|
525
549
|
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
550
|
+
|
|
551
|
+
// Handle skipped response (integration mode prevents CLI review)
|
|
552
|
+
if (handleSkippedResponse(response, options, spinner)) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
526
556
|
spinner.succeed(`Review completed in ${elapsed}s!`);
|
|
527
557
|
|
|
528
558
|
// Output results to stdout
|
package/src/index.test.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
truncateFileData,
|
|
4
|
+
formatErrorOutput,
|
|
5
|
+
detectCIProvider,
|
|
6
|
+
getPrUrl,
|
|
7
|
+
handleSkippedResponse,
|
|
8
|
+
} from './index.js';
|
|
3
9
|
|
|
4
10
|
describe('CLI JSON output mode', () => {
|
|
5
11
|
let stdoutSpy;
|
|
@@ -549,6 +555,114 @@ describe('--model flag behavior', () => {
|
|
|
549
555
|
});
|
|
550
556
|
});
|
|
551
557
|
|
|
558
|
+
describe('skipped response handling', () => {
|
|
559
|
+
let stdoutSpy;
|
|
560
|
+
|
|
561
|
+
beforeEach(() => {
|
|
562
|
+
stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
afterEach(() => {
|
|
566
|
+
vi.restoreAllMocks();
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('should return true and call spinner.info when response is skipped', () => {
|
|
570
|
+
const response = {
|
|
571
|
+
data: {
|
|
572
|
+
skipped: true,
|
|
573
|
+
reason: 'webhook_mode_active',
|
|
574
|
+
message: 'Review skipped due to webhook mode.',
|
|
575
|
+
},
|
|
576
|
+
};
|
|
577
|
+
const options = { json: false };
|
|
578
|
+
const spinner = { info: vi.fn() };
|
|
579
|
+
|
|
580
|
+
const result = handleSkippedResponse(response, options, spinner);
|
|
581
|
+
|
|
582
|
+
expect(result).toBe(true);
|
|
583
|
+
expect(spinner.info).toHaveBeenCalledWith('Review skipped due to webhook mode.');
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
it('should return false when response is not skipped', () => {
|
|
587
|
+
const response = {
|
|
588
|
+
data: {
|
|
589
|
+
review: { issues: [], praises: [] },
|
|
590
|
+
summary: { total_issues: 0 },
|
|
591
|
+
},
|
|
592
|
+
};
|
|
593
|
+
const options = { json: false };
|
|
594
|
+
const spinner = { info: vi.fn() };
|
|
595
|
+
|
|
596
|
+
const result = handleSkippedResponse(response, options, spinner);
|
|
597
|
+
|
|
598
|
+
expect(result).toBe(false);
|
|
599
|
+
expect(spinner.info).not.toHaveBeenCalled();
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
it('should output JSON to stdout when json option is true and response is skipped', () => {
|
|
603
|
+
const response = {
|
|
604
|
+
data: {
|
|
605
|
+
skipped: true,
|
|
606
|
+
reason: 'local_reviews_disabled',
|
|
607
|
+
message: 'Local reviews disabled.',
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
const options = { json: true };
|
|
611
|
+
const spinner = { info: vi.fn() };
|
|
612
|
+
|
|
613
|
+
handleSkippedResponse(response, options, spinner);
|
|
614
|
+
|
|
615
|
+
expect(stdoutSpy).toHaveBeenCalledWith(JSON.stringify(response.data, null, 2) + '\n');
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
it('should not output JSON when json option is false', () => {
|
|
619
|
+
const response = {
|
|
620
|
+
data: {
|
|
621
|
+
skipped: true,
|
|
622
|
+
reason: 'reviews_disabled',
|
|
623
|
+
message: 'Reviews disabled.',
|
|
624
|
+
},
|
|
625
|
+
};
|
|
626
|
+
const options = { json: false };
|
|
627
|
+
const spinner = { info: vi.fn() };
|
|
628
|
+
|
|
629
|
+
handleSkippedResponse(response, options, spinner);
|
|
630
|
+
|
|
631
|
+
expect(stdoutSpy).not.toHaveBeenCalled();
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
it('should use default message when response message is empty', () => {
|
|
635
|
+
const response = {
|
|
636
|
+
data: {
|
|
637
|
+
skipped: true,
|
|
638
|
+
reason: 'webhook_mode_active',
|
|
639
|
+
},
|
|
640
|
+
};
|
|
641
|
+
const options = { json: false };
|
|
642
|
+
const spinner = { info: vi.fn() };
|
|
643
|
+
|
|
644
|
+
handleSkippedResponse(response, options, spinner);
|
|
645
|
+
|
|
646
|
+
expect(spinner.info).toHaveBeenCalledWith('Review skipped.');
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
it('should handle all skip reason types', () => {
|
|
650
|
+
const reasons = ['webhook_mode_active', 'reviews_disabled', 'local_reviews_disabled'];
|
|
651
|
+
const spinner = { info: vi.fn() };
|
|
652
|
+
|
|
653
|
+
reasons.forEach((reason) => {
|
|
654
|
+
const response = {
|
|
655
|
+
data: { skipped: true, reason, message: `Skipped: ${reason}` },
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
const result = handleSkippedResponse(response, { json: false }, spinner);
|
|
659
|
+
expect(result).toBe(true);
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
expect(spinner.info).toHaveBeenCalledTimes(3);
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
|
|
552
666
|
describe('getPrUrl', () => {
|
|
553
667
|
const originalEnv = process.env;
|
|
554
668
|
|