@codecora/cli 0.0.3 → 0.0.5
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 +113 -62
- package/bin/cora.js +8 -0
- package/dist/commands/auth.js +5 -4
- package/dist/commands/review.js +4 -0
- package/dist/config/storage.js +3 -1
- package/dist/git/diff.js +63 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
# CORA CLI
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Catch bugs & security issues BEFORE you commit. Save 2+ hours/week on code reviews.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
All CLI features have been tested and verified working:
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|---------|--------|-------------|
|
|
13
|
-
| Authentication | ✅ | `cora auth status` shows user info, session validity, expiration |
|
|
14
|
-
| Code Review | ✅ | Reviews staged/unstaged changes with token usage tracking |
|
|
15
|
-
| Output Formats | ✅ | Pretty (default), JSON, Compact formats |
|
|
16
|
-
| Git Hooks | ✅ | Automatic pre-commit review on every commit |
|
|
17
|
-
| Mock Mode | ✅ | Testing without using API credits |
|
|
18
|
-
| Error Handling | ✅ | Graceful handling of network errors and invalid input |
|
|
9
|
+
**Website:** [https://codecora.dev](https://codecora.dev) | **Docs:** [https://codecora.dev/docs/cli](https://codecora.dev/docs/cli)
|
|
19
10
|
|
|
20
|
-
|
|
21
|
-
- Issues with severity (critical, major, minor, info)
|
|
22
|
-
- Token breakdown (input/output/execution time)
|
|
23
|
-
- Quota information
|
|
24
|
-
- AI-generated summaries and suggested fixes
|
|
11
|
+
CORA CLI brings AI code review to your local development workflow. Get instant feedback on your code changes before they leave your machine.
|
|
25
12
|
|
|
26
13
|
## Features
|
|
27
14
|
|
|
@@ -31,49 +18,87 @@ All CLI features have been tested and verified working:
|
|
|
31
18
|
- **Git Hooks** - Automatic review on every commit
|
|
32
19
|
- **Cross-platform** - Works on macOS, Linux, and Windows
|
|
33
20
|
|
|
21
|
+
## Benefits
|
|
22
|
+
|
|
23
|
+
- **Save Time** - Reduce code review time by 2+ hours per week
|
|
24
|
+
- **Catch Bugs Early** - Find issues before they reach production
|
|
25
|
+
- **Security First** - Detect vulnerabilities and security risks
|
|
26
|
+
- **Learn Best Practices** - Get AI-powered suggestions for code improvement
|
|
27
|
+
- **Zero Friction** - Works with your existing Git workflow
|
|
28
|
+
|
|
34
29
|
## Installation
|
|
35
30
|
|
|
36
|
-
###
|
|
31
|
+
### Using npm/bun (Requires Node.js 20+)
|
|
37
32
|
|
|
38
33
|
```bash
|
|
39
34
|
# Using npm
|
|
40
35
|
npm install -g @codecora/cli
|
|
41
36
|
|
|
42
37
|
# Using bun
|
|
43
|
-
bun install -g @
|
|
38
|
+
bun install -g @codecora/cli
|
|
44
39
|
```
|
|
45
40
|
|
|
46
|
-
|
|
41
|
+
## Quick Start
|
|
47
42
|
|
|
48
|
-
|
|
43
|
+
```bash
|
|
44
|
+
# 1. Install CORA CLI
|
|
45
|
+
npm install -g @codecora/cli
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| macOS (Intel) | `cora-macos-x64` |
|
|
53
|
-
| macOS (Apple Silicon) | `cora-macos-arm64` |
|
|
54
|
-
| Linux (x64) | `cora-linux-x64` |
|
|
55
|
-
| Windows (x64) | `cora-win-x64.exe` |
|
|
47
|
+
# 2. Login to CORA
|
|
48
|
+
cora auth login
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
curl -L https://github.com/ajianaz/cora/releases/latest/download/cora-macos-arm64 -o cora
|
|
60
|
-
chmod +x cora
|
|
61
|
-
sudo mv cora /usr/local/bin/
|
|
50
|
+
# 3. Review staged changes
|
|
51
|
+
cora review
|
|
62
52
|
```
|
|
63
53
|
|
|
64
|
-
|
|
54
|
+
**Example Output:**
|
|
65
55
|
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
cora auth login
|
|
56
|
+
```
|
|
57
|
+
✅ Review complete
|
|
69
58
|
|
|
70
|
-
|
|
71
|
-
cora review
|
|
59
|
+
Found 2 issues:
|
|
72
60
|
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
🔴 Critical: SQL injection risk
|
|
62
|
+
File: src/auth.ts:45
|
|
63
|
+
User input not sanitized before query
|
|
64
|
+
|
|
65
|
+
🟡 Major: Missing error handling
|
|
66
|
+
File: src/api.ts:12
|
|
67
|
+
API call lacks try-catch block
|
|
68
|
+
|
|
69
|
+
💡 Suggestions available. Run with --include-walkthrough for details.
|
|
75
70
|
```
|
|
76
71
|
|
|
72
|
+
## Use Cases
|
|
73
|
+
|
|
74
|
+
CORA CLI is perfect for:
|
|
75
|
+
|
|
76
|
+
- **Pre-commit Hooks** - Automatically review code before every commit
|
|
77
|
+
- **CI/CD Pipelines** - Integrate into GitHub Actions, GitLab CI, Jenkins
|
|
78
|
+
- **Legacy Code Audit** - Review entire codebases with `--base` flag
|
|
79
|
+
- **Pull Request Reviews** - Check feature branches before merging
|
|
80
|
+
- **Learning Projects** - Get AI feedback on code quality and best practices
|
|
81
|
+
|
|
82
|
+
## Why CORA vs Others?
|
|
83
|
+
|
|
84
|
+
| Feature | CORA | SonarQube | CodeClimate | DeepSource |
|
|
85
|
+
|---------|------|-----------|-------------|------------|
|
|
86
|
+
| **Setup Time** | 30 seconds | Hours | Hours | Hours |
|
|
87
|
+
| **Pre-commit** | ✅ Native | ❌ Plugin | ❌ Plugin | ❌ Plugin |
|
|
88
|
+
| **AI-Powered** | ✅ GPT-4/Claude | ❌ Rule-based | ❌ Rule-based | ❌ Rule-based |
|
|
89
|
+
| **Your AI Key** | ✅ Use your own | ❌ Locked in | ❌ Locked in | ❌ Locked in |
|
|
90
|
+
| **Privacy** | ✅ Code stays local | ⚠️ Cloud scan | ⚠️ Cloud scan | ⚠️ Cloud scan |
|
|
91
|
+
| **Free Tier** | ✅ 100 reviews/mo | ❌ $120/yr min | ❌ $50/yr min | ❌ Subscription |
|
|
92
|
+
| **Languages** | All languages | Limited | Limited | Limited |
|
|
93
|
+
|
|
94
|
+
**Key Differentiators:**
|
|
95
|
+
- **Fastest Setup** - Install and run in 30 seconds, no configuration needed
|
|
96
|
+
- **AI-Powered** - Uses latest GPT-4/Claude models, not outdated rule engines
|
|
97
|
+
- **Your AI Key** - Use your own OpenAI/Anthropic key, no vendor lock-in
|
|
98
|
+
- **Privacy-First** - Code analyzed by YOUR AI provider, we never see your code
|
|
99
|
+
- **Zero Maintenance** - No servers to manage, no databases to configure
|
|
100
|
+
- **Always Updated** - Automatically benefits from latest AI model improvements
|
|
101
|
+
|
|
77
102
|
## Usage
|
|
78
103
|
|
|
79
104
|
### Authentication
|
|
@@ -92,12 +117,6 @@ cora auth logout
|
|
|
92
117
|
cora auth config [key] [value]
|
|
93
118
|
```
|
|
94
119
|
|
|
95
|
-
**Important:** For CLI authentication to work, you must add `http://localhost:4200/callback` to your GitHub App's redirect URIs:
|
|
96
|
-
|
|
97
|
-
1. Go to your GitHub App settings
|
|
98
|
-
2. Navigate to **General** → **Homepage URL**
|
|
99
|
-
3. Add `http://localhost:4200/callback` to the redirect URIs
|
|
100
|
-
|
|
101
120
|
### Review Code
|
|
102
121
|
|
|
103
122
|
```bash
|
|
@@ -110,8 +129,11 @@ cora review --unstaged
|
|
|
110
129
|
# Review specific files
|
|
111
130
|
cora review --files src/app.ts src/utils.ts
|
|
112
131
|
|
|
113
|
-
#
|
|
114
|
-
cora review --
|
|
132
|
+
# Review committed changes
|
|
133
|
+
cora review --base main # Review branch vs main
|
|
134
|
+
cora review --commits 3 # Review last 3 commits
|
|
135
|
+
cora review --revision-range abc..def # Review specific range
|
|
136
|
+
cora review --unpushed # Review unpushed commits
|
|
115
137
|
|
|
116
138
|
# JSON output for CI/CD
|
|
117
139
|
cora review --format json
|
|
@@ -144,9 +166,10 @@ cora disable # Uninstall pre-commit hook
|
|
|
144
166
|
| `-s, --staged` | Review staged changes (default) |
|
|
145
167
|
| `-u, --unstaged` | Review unstaged changes |
|
|
146
168
|
| `-f, --files <files...>` | Review specific files |
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
| `--
|
|
169
|
+
| `--base <ref>` | Review changes from base ref to HEAD (e.g., "main") |
|
|
170
|
+
| `--revision-range <range>` | Review specific commit range (e.g., "HEAD~3..HEAD") |
|
|
171
|
+
| `--commits <number>` | Review last N commits |
|
|
172
|
+
| `--unpushed` | Review unpushed commits |
|
|
150
173
|
| `--format <format>` | Output format (pretty, json, compact) |
|
|
151
174
|
|
|
152
175
|
## Configuration
|
|
@@ -163,13 +186,32 @@ Configuration is stored in `~/.codecora/`:
|
|
|
163
186
|
| `CORA_SKIP` | Skip pre-commit hook when set to 1 |
|
|
164
187
|
| `CORA_SERVER` | Override server URL |
|
|
165
188
|
| `CORA_WORKSPACE` | Override workspace ID |
|
|
166
|
-
| `CORA_API_KEY` | API key for CI/CD authentication
|
|
189
|
+
| `CORA_API_KEY` | API key for CI/CD authentication |
|
|
167
190
|
|
|
168
191
|
## CI/CD Integration
|
|
169
192
|
|
|
193
|
+
### Supported Languages
|
|
194
|
+
|
|
195
|
+
CORA CLI supports code review for all programming languages including:
|
|
196
|
+
- JavaScript / TypeScript
|
|
197
|
+
- Python
|
|
198
|
+
- Java / Kotlin
|
|
199
|
+
- Go
|
|
200
|
+
- Rust
|
|
201
|
+
- PHP
|
|
202
|
+
- Ruby
|
|
203
|
+
- C# / .NET
|
|
204
|
+
- And more...
|
|
205
|
+
|
|
170
206
|
### Using API Keys (Recommended)
|
|
171
207
|
|
|
172
|
-
For CI/CD workflows, use API Keys instead of session tokens
|
|
208
|
+
For CI/CD workflows, use API Keys instead of session tokens.
|
|
209
|
+
|
|
210
|
+
**Getting an API Key:**
|
|
211
|
+
1. Login to [codecora.dev](https://codecora.dev)
|
|
212
|
+
2. Go to Dashboard → API Keys
|
|
213
|
+
3. Click "Generate API Key"
|
|
214
|
+
4. Copy the key and use in your CI/CD pipeline
|
|
173
215
|
|
|
174
216
|
```yaml
|
|
175
217
|
# Example: GitHub Actions
|
|
@@ -190,8 +232,6 @@ For CI/CD workflows, use API Keys instead of session tokens:
|
|
|
190
232
|
|
|
191
233
|
**Create API Key:** Visit Dashboard → API Keys to generate a key for CI/CD.
|
|
192
234
|
|
|
193
|
-
See [API Keys Documentation](../../../docs/API_KEYS.md) for complete guide.
|
|
194
|
-
|
|
195
235
|
## Troubleshooting
|
|
196
236
|
|
|
197
237
|
### Authentication Errors
|
|
@@ -226,17 +266,28 @@ CORA_SKIP=1 git commit -m "message"
|
|
|
226
266
|
|
|
227
267
|
## Requirements
|
|
228
268
|
|
|
229
|
-
- **Node.js 20+**
|
|
230
|
-
- **OR** standalone binary (no dependencies)
|
|
269
|
+
- **Node.js 20+** or **Bun 1.0+**
|
|
231
270
|
- A Codecora account (sign up at https://codecora.dev)
|
|
232
271
|
- An OpenAI-compatible API key configured in your workspace
|
|
233
272
|
|
|
273
|
+
## Pricing
|
|
274
|
+
|
|
275
|
+
- **Free Tier** - 100 reviews/month during beta
|
|
276
|
+
- **Pro Tier** - Coming soon
|
|
277
|
+
- **Enterprise** - Contact us for custom solutions
|
|
278
|
+
|
|
234
279
|
## License
|
|
235
280
|
|
|
236
281
|
MIT © [CORA](https://codecora.dev)
|
|
237
282
|
|
|
238
283
|
## Support
|
|
239
284
|
|
|
240
|
-
-
|
|
241
|
-
- [
|
|
242
|
-
- [
|
|
285
|
+
- 📧 **Email**: support@codecora.dev
|
|
286
|
+
- 📚 [Documentation](https://codecora.dev/docs/cli)
|
|
287
|
+
- 🌐 [Website](https://codecora.dev)
|
|
288
|
+
- 💬 [Community Discord](https://discord.gg/codecora)
|
|
289
|
+
|
|
290
|
+
**Getting Help:**
|
|
291
|
+
- Check our [Documentation](https://codecora.dev/docs/cli) for detailed guides
|
|
292
|
+
- Join our [Discord community](https://discord.gg/codecora) for quick questions
|
|
293
|
+
- Email us at support@codecora.dev for technical issues
|
package/bin/cora.js
CHANGED
|
@@ -84,6 +84,10 @@ program
|
|
|
84
84
|
.option('-s, --staged', 'Review staged changes (default: true)')
|
|
85
85
|
.option('-u, --unstaged', 'Review unstaged changes')
|
|
86
86
|
.option('-f, --files <files...>', 'Review specific files')
|
|
87
|
+
.option('--base <ref>', 'Review changes from base ref to HEAD (e.g., "main", "develop")')
|
|
88
|
+
.option('--revision-range <range>', 'Review specific commit range (e.g., "HEAD~3..HEAD", "abc123..def456")')
|
|
89
|
+
.option('--commits <number>', 'Review last N commits', parseInt)
|
|
90
|
+
.option('--unpushed', 'Review unpushed commits')
|
|
87
91
|
.option('-m, --max-tokens <number>', 'Maximum tokens to use', parseInt)
|
|
88
92
|
.option('-i, --include-walkthrough', 'Include full walkthrough')
|
|
89
93
|
.option('--mock', 'Mock mode for testing')
|
|
@@ -96,6 +100,10 @@ program
|
|
|
96
100
|
branch: options.branch,
|
|
97
101
|
staged: options.unstaged ? false : options.staged !== false,
|
|
98
102
|
files: options.files,
|
|
103
|
+
base: options.base,
|
|
104
|
+
revisionRange: options.revisionRange,
|
|
105
|
+
commits: options.commits,
|
|
106
|
+
unpushed: options.unpushed,
|
|
99
107
|
maxTokens: options.maxTokens,
|
|
100
108
|
includeWalkthrough: options.includeWalkthrough,
|
|
101
109
|
mock: options.mock,
|
package/dist/commands/auth.js
CHANGED
|
@@ -48,7 +48,7 @@ export async function login(serverUrl) {
|
|
|
48
48
|
}
|
|
49
49
|
// Store session directly from server response
|
|
50
50
|
await setAuthToken(authResult.token, targetServerUrl, authResult.userId, authResult.email, authResult.expiresAt);
|
|
51
|
-
console.log(`\nSuccessfully logged in as ${authResult.email}`);
|
|
51
|
+
console.log(`\nSuccessfully logged in${authResult.email ? ` as ${authResult.email}` : ''}`);
|
|
52
52
|
process.exit(0);
|
|
53
53
|
}
|
|
54
54
|
catch (error) {
|
|
@@ -171,7 +171,7 @@ function createCallbackServer() {
|
|
|
171
171
|
const url = new URL(req.url, `http://localhost:${FIXED_PORT}`);
|
|
172
172
|
const token = url.searchParams.get('token');
|
|
173
173
|
const userId = url.searchParams.get('userId');
|
|
174
|
-
const email = url.searchParams.get('email');
|
|
174
|
+
const email = url.searchParams.get('email'); // Optional, can be fetched via API
|
|
175
175
|
const expiresAt = url.searchParams.get('expiresAt');
|
|
176
176
|
const error = url.searchParams.get('error');
|
|
177
177
|
if (error) {
|
|
@@ -181,7 +181,8 @@ function createCallbackServer() {
|
|
|
181
181
|
server.close();
|
|
182
182
|
return;
|
|
183
183
|
}
|
|
184
|
-
|
|
184
|
+
// Email is optional - can be fetched via API after login
|
|
185
|
+
if (token && userId && expiresAt) {
|
|
185
186
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
186
187
|
res.end(`
|
|
187
188
|
<!DOCTYPE html>
|
|
@@ -193,7 +194,7 @@ function createCallbackServer() {
|
|
|
193
194
|
</body>
|
|
194
195
|
</html>
|
|
195
196
|
`);
|
|
196
|
-
resolvePromise({ token, userId, email, expiresAt });
|
|
197
|
+
resolvePromise({ token, userId, email: email || undefined, expiresAt });
|
|
197
198
|
server.close();
|
|
198
199
|
}
|
|
199
200
|
else {
|
package/dist/commands/review.js
CHANGED
|
@@ -36,6 +36,10 @@ export async function review(options = {}) {
|
|
|
36
36
|
staged: options.staged !== false,
|
|
37
37
|
files: options.files,
|
|
38
38
|
cwd,
|
|
39
|
+
base: options.base,
|
|
40
|
+
revisionRange: options.revisionRange,
|
|
41
|
+
commits: options.commits,
|
|
42
|
+
unpushed: options.unpushed,
|
|
39
43
|
});
|
|
40
44
|
}
|
|
41
45
|
catch (error) {
|
package/dist/config/storage.js
CHANGED
package/dist/git/diff.js
CHANGED
|
@@ -149,7 +149,21 @@ export function validateDiffSize(diff, maxSize = 10 * 1024 * 1024 // 10MB defaul
|
|
|
149
149
|
* Main function to get diff based on options.
|
|
150
150
|
*/
|
|
151
151
|
export function getReviewDiff(options) {
|
|
152
|
-
const { staged = true, files, cwd = process.cwd() } = options;
|
|
152
|
+
const { staged = true, files, cwd = process.cwd(), base, revisionRange, commits, unpushed, } = options;
|
|
153
|
+
// Commit-based review takes precedence
|
|
154
|
+
if (revisionRange) {
|
|
155
|
+
return getCommitDiff(revisionRange, cwd);
|
|
156
|
+
}
|
|
157
|
+
if (unpushed) {
|
|
158
|
+
return getUnpushedDiff(cwd);
|
|
159
|
+
}
|
|
160
|
+
if (commits !== undefined) {
|
|
161
|
+
return getLastCommitsDiff(commits, cwd);
|
|
162
|
+
}
|
|
163
|
+
if (base) {
|
|
164
|
+
return getBaseDiff(base, cwd);
|
|
165
|
+
}
|
|
166
|
+
// Default behavior: staged/unstaged/files
|
|
153
167
|
if (files && files.length > 0) {
|
|
154
168
|
return getFilesDiff(files, staged, cwd);
|
|
155
169
|
}
|
|
@@ -160,3 +174,51 @@ export function getReviewDiff(options) {
|
|
|
160
174
|
return getUnstagedDiff(cwd);
|
|
161
175
|
}
|
|
162
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Get diff between two git refs (commits, branches, tags)
|
|
179
|
+
*
|
|
180
|
+
* Examples:
|
|
181
|
+
* - "main...HEAD" - changes from main to current branch
|
|
182
|
+
* - "abc123..def456" - changes between two commits
|
|
183
|
+
* - "v1.0.0..HEAD" - changes since tag v1.0.0
|
|
184
|
+
*/
|
|
185
|
+
export function getCommitDiff(revisionRange, cwd = process.cwd()) {
|
|
186
|
+
const result = execFileSafe('git', ['diff', revisionRange], { cwd });
|
|
187
|
+
if (result.status !== 0) {
|
|
188
|
+
throw new Error(`Failed to get commit diff: ${result.stderr || result.error?.message}`);
|
|
189
|
+
}
|
|
190
|
+
return result.stdout;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Get diff of unpushed commits
|
|
194
|
+
*
|
|
195
|
+
* Returns diff between HEAD and the remote tracking branch.
|
|
196
|
+
*/
|
|
197
|
+
export function getUnpushedDiff(cwd = process.cwd()) {
|
|
198
|
+
// First, get the remote tracking branch
|
|
199
|
+
const trackingResult = execFileSafe('git', ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], { cwd });
|
|
200
|
+
if (trackingResult.status !== 0) {
|
|
201
|
+
throw new Error('No upstream branch found. Cannot determine unpushed commits. ' +
|
|
202
|
+
'Hint: Set upstream with `git push -u origin <branch>`');
|
|
203
|
+
}
|
|
204
|
+
const trackingBranch = trackingResult.stdout.trim();
|
|
205
|
+
return getCommitDiff(`${trackingBranch}...HEAD`, cwd);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get diff of last N commits
|
|
209
|
+
*
|
|
210
|
+
* Returns diff between HEAD~N and HEAD.
|
|
211
|
+
*/
|
|
212
|
+
export function getLastCommitsDiff(count, cwd = process.cwd()) {
|
|
213
|
+
const revisionRange = `HEAD~${count}..HEAD`;
|
|
214
|
+
return getCommitDiff(revisionRange, cwd);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get diff from base branch to HEAD
|
|
218
|
+
*
|
|
219
|
+
* Compares current HEAD with the specified base branch.
|
|
220
|
+
*/
|
|
221
|
+
export function getBaseDiff(base, cwd = process.cwd()) {
|
|
222
|
+
const revisionRange = `${base}...HEAD`;
|
|
223
|
+
return getCommitDiff(revisionRange, cwd);
|
|
224
|
+
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.0.
|
|
1
|
+
export const VERSION = '0.0.5';
|