@vibedrift/cli 0.4.0 → 0.4.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 +115 -22
- package/dist/index.js +29 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,27 +21,66 @@ vibedrift ./my-project
|
|
|
21
21
|
|
|
22
22
|
That's it. No signup, no API key, no config file. The default run produces an interactive HTML report and serves it on a local port.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
### Free deep scan
|
|
25
|
+
|
|
26
|
+
Every account gets **1 free deep scan** on signup — no card required. Deep scans add Claude-powered AI analysis on top of the local scan (semantic duplicates, intent mismatches, anomaly detection):
|
|
25
27
|
|
|
26
28
|
```bash
|
|
27
|
-
vibedrift login # one-time browser sign-in
|
|
28
|
-
vibedrift . --deep #
|
|
29
|
+
vibedrift login # one-time browser sign-in
|
|
30
|
+
vibedrift . --deep # uses your free credit (or Pro subscription)
|
|
29
31
|
```
|
|
30
32
|
|
|
31
33
|
---
|
|
32
34
|
|
|
33
35
|
## What It Catches
|
|
34
36
|
|
|
37
|
+
### Layer 1 — Static Analysis (13 analyzers, runs locally)
|
|
35
38
|
- **Architectural contradictions** — when half your handlers use a repository pattern and the other half hit raw SQL
|
|
36
|
-
- **Hidden duplicates** — functions that do the same thing under different names in different files
|
|
37
|
-
- **Security gaps** — routes missing auth, validation, or rate limiting
|
|
38
39
|
- **Naming inconsistency** — `getUserData()`, `get_order_items()`, `FetchProductList()` in the same project
|
|
40
|
+
- **Security patterns** — hardcoded secrets, SQL injection, command injection, weak crypto, unsafe functions
|
|
41
|
+
- **Dependency health** — phantom deps, missing deps, undocumented env vars
|
|
42
|
+
- **Code quality** — cyclomatic complexity, dead code, TODO density, long functions, unclear naming
|
|
43
|
+
|
|
44
|
+
### Layer 1.5 — Cross-File Drift Detection (5 detectors)
|
|
45
|
+
- **Architectural consistency** — data access patterns, error handling, DI, config approaches
|
|
46
|
+
- **Convention oscillation** — naming conventions, file naming across the whole project
|
|
47
|
+
- **Security consistency** — auth middleware, input validation, rate limiting across routes
|
|
48
|
+
- **Semantic duplication** — functions that do the same thing under different names in different files
|
|
39
49
|
- **Phantom scaffolding** — CRUD endpoints the AI generated but never wired up
|
|
40
50
|
|
|
51
|
+
### Layer 1.7 — Code DNA Engine (5 modules, runs locally)
|
|
52
|
+
- **Semantic fingerprinting** — normalizes function bodies and hashes them. Identical hashes = exact semantic duplicates at confidence 1.0
|
|
53
|
+
- **Operation sequence analysis** — reduces functions to abstract operations (INPUT, QUERY, MUTATE, RETURN) and compares via LCS
|
|
54
|
+
- **Pattern classification** — structural pattern detection with probability distributions per file
|
|
55
|
+
- **Taint analysis** — tracks user input from sources (req.params) to dangerous sinks (db.query) within functions
|
|
56
|
+
- **Deviation heuristics** — scores whether architectural deviations are justified or accidental
|
|
57
|
+
|
|
58
|
+
### Layer 2 — AI Deep Analysis (requires `--deep`)
|
|
59
|
+
- **ML duplicate detection** — UniXcoder embeddings + cosine similarity for near-duplicates
|
|
60
|
+
- **Intent mismatch** — detects functions whose name doesn't match their behavior
|
|
61
|
+
- **Anomaly detection** — DBSCAN outlier detection on handler embeddings
|
|
62
|
+
- **Surgical LLM validation** — Claude validates medium-confidence ML findings
|
|
63
|
+
|
|
41
64
|
VibeDrift learns the dominant patterns your codebase follows and flags files that deviate from them. A codebase isn't wrong because it uses raw SQL — it's *drifting* because 8 of its 10 handlers use a repository and 2 don't.
|
|
42
65
|
|
|
43
66
|
---
|
|
44
67
|
|
|
68
|
+
## Scoring
|
|
69
|
+
|
|
70
|
+
VibeDrift scores across 5 categories, each 0–20 points:
|
|
71
|
+
|
|
72
|
+
| Category | What it measures |
|
|
73
|
+
|----------|-----------------|
|
|
74
|
+
| **Architectural Consistency** | Naming, imports, error handling, patterns, drift detection |
|
|
75
|
+
| **Redundancy** | Duplicates, dead code, TODO density, Code DNA fingerprints |
|
|
76
|
+
| **Dependency Health** | Phantom/missing deps, env var documentation |
|
|
77
|
+
| **Security Posture** | Hardcoded secrets, injection risks, taint flows, security drift |
|
|
78
|
+
| **Intent Clarity** | Complexity, unclear naming, commented-out code, documentation |
|
|
79
|
+
|
|
80
|
+
**Composite score** = sum of applicable categories (0–100). Grade thresholds: A ≥ 90, B ≥ 75, C ≥ 50, D ≥ 25, F < 25.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
45
84
|
## Usage
|
|
46
85
|
|
|
47
86
|
```
|
|
@@ -57,6 +96,7 @@ Commands:
|
|
|
57
96
|
billing Open the Stripe Customer Portal
|
|
58
97
|
doctor Diagnose CLI installation, auth, and API
|
|
59
98
|
update Update the CLI to the latest version
|
|
99
|
+
feedback [message] Send feedback, bug reports, or feature requests
|
|
60
100
|
|
|
61
101
|
Scan options:
|
|
62
102
|
--format <type> Output format: html, terminal, json, csv, docx (default: html)
|
|
@@ -64,9 +104,11 @@ Scan options:
|
|
|
64
104
|
--json Shorthand for --format json
|
|
65
105
|
--fail-on-score <n> Exit with code 1 if composite score is below threshold
|
|
66
106
|
--no-codedna Skip Code DNA semantic analysis
|
|
67
|
-
--deep Enable AI-powered deep analysis (requires
|
|
107
|
+
--deep Enable AI-powered deep analysis (requires login)
|
|
108
|
+
--project-name <name> Override the auto-detected project name
|
|
68
109
|
--include <pattern> Only scan files matching this glob (repeatable)
|
|
69
110
|
--exclude <pattern> Exclude files matching this glob (repeatable)
|
|
111
|
+
--feedback [message] Send feedback (alias for `vibedrift feedback`)
|
|
70
112
|
--update Update the VibeDrift CLI to the latest version
|
|
71
113
|
--verbose Show timing breakdown and analyzer details
|
|
72
114
|
-V, --version Show installed version
|
|
@@ -76,6 +118,7 @@ Scan options:
|
|
|
76
118
|
### Examples
|
|
77
119
|
|
|
78
120
|
```bash
|
|
121
|
+
# Scanning
|
|
79
122
|
vibedrift # scan the current directory
|
|
80
123
|
vibedrift ./my-project # scan a specific project
|
|
81
124
|
vibedrift --format terminal # print results to the terminal
|
|
@@ -83,12 +126,20 @@ vibedrift --json > report.json # pipe JSON output to a file
|
|
|
83
126
|
vibedrift --fail-on-score 70 # fail CI if score drops below 70
|
|
84
127
|
vibedrift --include "src/**" # only scan files under src/
|
|
85
128
|
vibedrift --exclude "**/*.spec.*" # skip test files
|
|
86
|
-
vibedrift --deep # run
|
|
87
|
-
|
|
88
|
-
|
|
129
|
+
vibedrift --deep # run AI-powered deep analysis
|
|
130
|
+
|
|
131
|
+
# Account
|
|
132
|
+
vibedrift login # sign in (opens browser)
|
|
133
|
+
vibedrift status # check auth + credit balance
|
|
89
134
|
vibedrift usage # view this month's scan usage
|
|
90
|
-
vibedrift billing # manage your
|
|
135
|
+
vibedrift billing # manage your subscription
|
|
91
136
|
vibedrift update # update to the latest version
|
|
137
|
+
|
|
138
|
+
# Feedback
|
|
139
|
+
vibedrift feedback # interactive prompt
|
|
140
|
+
vibedrift feedback "the report is great but needs dark mode"
|
|
141
|
+
vibedrift --feedback "inline shortcut works too"
|
|
142
|
+
echo "piped input" | vibedrift feedback
|
|
92
143
|
```
|
|
93
144
|
|
|
94
145
|
### Environment
|
|
@@ -103,27 +154,56 @@ vibedrift update # update to the latest version
|
|
|
103
154
|
|
|
104
155
|
| Format | Description |
|
|
105
156
|
|--------|-------------|
|
|
106
|
-
| `html` (default) | Interactive report with charts,
|
|
157
|
+
| `html` (default) | Interactive report with charts, category breakdowns, drift findings, Code DNA results, and export options |
|
|
107
158
|
| `terminal` | Color-coded terminal output with tables |
|
|
108
|
-
| `json` | Full
|
|
109
|
-
| `csv` |
|
|
110
|
-
| `docx` | Word document with formatted
|
|
159
|
+
| `json` | Full ScanResult serialization for CI pipelines |
|
|
160
|
+
| `csv` | Multi-section tabular export (metadata, scores, findings, drift, Code DNA, per-file) |
|
|
161
|
+
| `docx` | Word document with formatted title page, AI summary, scores, and all findings |
|
|
111
162
|
|
|
112
163
|
### CI Integration
|
|
113
164
|
|
|
114
|
-
```
|
|
115
|
-
#
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
165
|
+
```yaml
|
|
166
|
+
# GitHub Actions
|
|
167
|
+
name: VibeDrift
|
|
168
|
+
on: [pull_request]
|
|
169
|
+
jobs:
|
|
170
|
+
drift-check:
|
|
171
|
+
runs-on: ubuntu-latest
|
|
172
|
+
steps:
|
|
173
|
+
- uses: actions/checkout@v4
|
|
174
|
+
- run: npx @vibedrift/cli . --deep --json --fail-on-score 70
|
|
175
|
+
env:
|
|
176
|
+
VIBEDRIFT_TOKEN: ${{ secrets.VIBEDRIFT_TOKEN }}
|
|
121
177
|
```
|
|
122
178
|
|
|
123
179
|
Exit code 1 when the score drops below the threshold. JSON output includes every finding for downstream tooling.
|
|
124
180
|
|
|
125
181
|
---
|
|
126
182
|
|
|
183
|
+
## Dashboard
|
|
184
|
+
|
|
185
|
+
All scans (free and deep) are logged to your dashboard at [vibedrift.ai/dashboard](https://vibedrift.ai/dashboard) when you're logged in:
|
|
186
|
+
|
|
187
|
+
- **Project overview** — score trends, sparklines, grade history
|
|
188
|
+
- **Scan detail** — embedded HTML report, export (JSON/CSV/DOCX), share via public link
|
|
189
|
+
- **Billing** — manage subscription, cancel/switch plans, view credits
|
|
190
|
+
- **Settings** — API tokens, preferences, account management
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Pricing
|
|
195
|
+
|
|
196
|
+
| Tier | Price | What you get |
|
|
197
|
+
|------|-------|-------------|
|
|
198
|
+
| **Free** | $0 | Unlimited local scans + 1 free deep scan on signup |
|
|
199
|
+
| **Per scan** | $5/scan | One-time deep scan credit (Claude AI + ML embeddings) |
|
|
200
|
+
| **Pro** | $29/month | Unlimited deep scans + GitHub Action + dashboard |
|
|
201
|
+
| **Team** | $99/month | Everything in Pro + team features + API access |
|
|
202
|
+
|
|
203
|
+
See [vibedrift.ai/#pricing](https://vibedrift.ai/#pricing) for details.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
127
207
|
## Supported Languages
|
|
128
208
|
|
|
129
209
|
JavaScript · TypeScript · Python · Go · Rust
|
|
@@ -139,6 +219,18 @@ JavaScript · TypeScript · Python · Go · Rust
|
|
|
139
219
|
|
|
140
220
|
---
|
|
141
221
|
|
|
222
|
+
## Feedback
|
|
223
|
+
|
|
224
|
+
Found a bug? Have a feature request? Send it directly from the CLI:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
vibedrift feedback "the naming analyzer flags Go acronyms incorrectly"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Feedback goes straight to the maintainer. If you're logged in, your account email is attached so we can follow up. Anonymous feedback works too.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
142
234
|
## License
|
|
143
235
|
|
|
144
236
|
VibeDrift is proprietary software. Free to install and run for personal and internal commercial use; see [LICENSE](./LICENSE) for full terms.
|
|
@@ -155,5 +247,6 @@ For commercial licensing, partnerships, or enterprise terms: **sami.ahmadkhan12@
|
|
|
155
247
|
|
|
156
248
|
## Links
|
|
157
249
|
|
|
158
|
-
- **Website:** https://vibedrift.ai
|
|
250
|
+
- **Website:** [vibedrift.ai](https://vibedrift.ai)
|
|
251
|
+
- **Dashboard:** [vibedrift.ai/dashboard](https://vibedrift.ai/dashboard)
|
|
159
252
|
- **Issues / Support:** sami.ahmadkhan12@gmail.com
|
package/dist/index.js
CHANGED
|
@@ -1321,9 +1321,29 @@ function buildDeviationPayloads(codeDnaResult, driftFindings) {
|
|
|
1321
1321
|
const hasComment = dj.signals?.some((s) => s.type === "explanatory_comment" && s.present) ?? false;
|
|
1322
1322
|
const sqlComplexity = dj.signals?.find((s) => s.type === "complex_sql")?.present ? 3 : 0;
|
|
1323
1323
|
const funcComplexity = dj.signals?.reduce((sum, s) => sum + (s.present ? Math.abs(s.weight) : 0), 0) ?? 0;
|
|
1324
|
+
const patternToType = {
|
|
1325
|
+
repository: "data_access",
|
|
1326
|
+
raw_sql: "data_access",
|
|
1327
|
+
orm: "data_access",
|
|
1328
|
+
direct_db: "data_access",
|
|
1329
|
+
http_client: "data_access",
|
|
1330
|
+
wrap_with_context: "error_handling",
|
|
1331
|
+
raw_propagation: "error_handling",
|
|
1332
|
+
swallow: "error_handling",
|
|
1333
|
+
http_error_response: "error_handling",
|
|
1334
|
+
exception_throw: "error_handling",
|
|
1335
|
+
result_type: "error_handling",
|
|
1336
|
+
constructor_injection: "di",
|
|
1337
|
+
global_import: "di",
|
|
1338
|
+
service_locator: "di",
|
|
1339
|
+
no_di: "di",
|
|
1340
|
+
env_direct: "config",
|
|
1341
|
+
config_struct_di: "config"
|
|
1342
|
+
};
|
|
1343
|
+
const inferredType = patternToType[dj.deviatingPattern] ?? patternToType[dj.dominantPattern] ?? "data_access";
|
|
1324
1344
|
deviations.push({
|
|
1325
1345
|
file: dj.relativePath,
|
|
1326
|
-
deviation_type:
|
|
1346
|
+
deviation_type: inferredType,
|
|
1327
1347
|
dominant_pattern: dj.dominantPattern,
|
|
1328
1348
|
actual_pattern: dj.deviatingPattern,
|
|
1329
1349
|
dominant_count: 0,
|
|
@@ -1344,7 +1364,7 @@ function buildDeviationPayloads(codeDnaResult, driftFindings) {
|
|
|
1344
1364
|
seen.add(key);
|
|
1345
1365
|
deviations.push({
|
|
1346
1366
|
file: df.path,
|
|
1347
|
-
deviation_type: d.subCategory ?? "
|
|
1367
|
+
deviation_type: d.subCategory ?? "data_access",
|
|
1348
1368
|
dominant_pattern: d.dominantPattern,
|
|
1349
1369
|
actual_pattern: df.detectedPattern,
|
|
1350
1370
|
dominant_count: d.dominantCount,
|
|
@@ -1473,9 +1493,11 @@ function deduplicateFindingsAcrossLayers(findings) {
|
|
|
1473
1493
|
return [...nonDuplicate, ...dedupedDuplicates];
|
|
1474
1494
|
}
|
|
1475
1495
|
function makeFilePairKey(f) {
|
|
1476
|
-
const files =
|
|
1496
|
+
const files = [...new Set(
|
|
1497
|
+
f.locations.map((l) => l.file).filter(Boolean)
|
|
1498
|
+
)].sort();
|
|
1477
1499
|
if (files.length >= 2) {
|
|
1478
|
-
return `dup::${files
|
|
1500
|
+
return `dup::${files.join("::")}`;
|
|
1479
1501
|
}
|
|
1480
1502
|
return `dup::${files[0] ?? "unknown"}::${f.analyzerId}`;
|
|
1481
1503
|
}
|
|
@@ -6017,9 +6039,9 @@ function computeDriftScores(findings) {
|
|
|
6017
6039
|
) / 10;
|
|
6018
6040
|
let grade;
|
|
6019
6041
|
if (composite >= 90) grade = "A";
|
|
6020
|
-
else if (composite >=
|
|
6021
|
-
else if (composite >=
|
|
6022
|
-
else if (composite >=
|
|
6042
|
+
else if (composite >= 75) grade = "B";
|
|
6043
|
+
else if (composite >= 50) grade = "C";
|
|
6044
|
+
else if (composite >= 25) grade = "D";
|
|
6023
6045
|
else grade = "F";
|
|
6024
6046
|
return {
|
|
6025
6047
|
...scores,
|