@nerviq/cli 1.8.9 → 1.10.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/README.md +32 -24
- package/bin/cli.js +173 -104
- package/package.json +59 -59
- package/src/activity.js +68 -12
- package/src/aider/freshness.js +168 -168
- package/src/anti-patterns.js +13 -11
- package/src/audit.js +16 -14
- package/src/auto-suggest.js +62 -9
- package/src/benchmark.js +52 -41
- package/src/codex/freshness.js +167 -167
- package/src/copilot/freshness.js +197 -197
- package/src/cursor/freshness.js +214 -214
- package/src/dashboard.js +36 -14
- package/src/freshness.js +19 -19
- package/src/gemini/freshness.js +204 -204
- package/src/i18n.js +63 -0
- package/src/instruction-surfaces.js +185 -0
- package/src/locales/en.json +34 -0
- package/src/locales/es.json +34 -0
- package/src/mcp-server.js +1 -1
- package/src/opencode/freshness.js +158 -158
- package/src/stack-checks.js +1 -1
- package/src/synergy/report.js +1 -0
- package/src/techniques.js +174 -58
- package/src/windsurf/freshness.js +215 -215
- package/src/workspace.js +51 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@nerviq/cli)
|
|
6
6
|
[](LICENSE)
|
|
7
|
-
[](https://github.com/nerviq/nerviq)
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ Nerviq audits, sets up, and governs AI coding agent configurations for **8 platf
|
|
|
14
14
|
|
|
15
15
|
| Platform | Checks | Status |
|
|
16
16
|
|----------|--------|--------|
|
|
17
|
-
| Claude Code |
|
|
17
|
+
| Claude Code | 400 | Full |
|
|
18
18
|
| Codex (OpenAI) | 272 | Full |
|
|
19
19
|
| Gemini CLI (Google) | 300 | Full |
|
|
20
20
|
| GitHub Copilot | 299 | Full |
|
|
@@ -64,18 +64,26 @@ Nerviq scores your AI coding agent setup from 0 to 100, finds what's missing, an
|
|
|
64
64
|
Next: nerviq setup
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
## Quick Start
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
npx @nerviq/cli
|
|
71
|
-
npx @nerviq/cli audit
|
|
72
|
-
npx @nerviq/cli
|
|
73
|
-
npx @nerviq/cli
|
|
74
|
-
npx @nerviq/cli
|
|
75
|
-
npx @nerviq/cli
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx @nerviq/cli --beginner # Show only the 5 starter commands
|
|
71
|
+
npx @nerviq/cli audit # Quick scan: score + top 3 actions
|
|
72
|
+
npx @nerviq/cli audit --full # Full audit with all checks + badge
|
|
73
|
+
npx @nerviq/cli audit --workspace packages/* # Monorepo: root governance + workspace average/package scores
|
|
74
|
+
npx @nerviq/cli setup # Generate starter-safe baseline
|
|
75
|
+
npx @nerviq/cli augment # Improvement plan, no writes
|
|
76
|
+
npx @nerviq/cli governance # Permission profiles + policy packs
|
|
77
|
+
npx @nerviq/cli benchmark # Baseline vs projected score in isolated copy
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
No install required. Zero dependencies.
|
|
81
|
+
|
|
82
|
+
If you want the shortest possible command list inside the terminal, start with:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npx @nerviq/cli --beginner
|
|
86
|
+
```
|
|
79
87
|
|
|
80
88
|
## Get Started by Role
|
|
81
89
|
|
|
@@ -85,7 +93,7 @@ No install required. Zero dependencies.
|
|
|
85
93
|
| **Team lead / DevEx** | `nerviq governance` → `nerviq audit --json` | CI threshold + `nerviq watch` |
|
|
86
94
|
| **Enterprise / Platform** | `nerviq harmony-audit` → `nerviq harmony-drift` | Policy packs + `nerviq certify` |
|
|
87
95
|
|
|
88
|
-
## 2,
|
|
96
|
+
## 2,438 Checks Across 96 Categories (8 Platforms × ~300 Governance Rules)
|
|
89
97
|
|
|
90
98
|
| Category Group | Checks | Examples |
|
|
91
99
|
|----------------|--------|---------|
|
|
@@ -236,14 +244,14 @@ Levels:
|
|
|
236
244
|
| `nerviq plan` | Export proposal bundles with previews |
|
|
237
245
|
| `nerviq apply` | Apply proposals with rollback |
|
|
238
246
|
| `nerviq governance` | Permission profiles, hooks, policy packs |
|
|
239
|
-
| `nerviq benchmark` |
|
|
247
|
+
| `nerviq benchmark` | Baseline vs projected score in isolated temp copy |
|
|
240
248
|
| `nerviq check-health` | Detect regressions between audit snapshots |
|
|
241
249
|
| `nerviq deep-review` | AI-powered config review (opt-in) |
|
|
242
250
|
| `nerviq interactive` | Step-by-step guided wizard |
|
|
243
251
|
| `nerviq watch` | Live monitoring with score delta |
|
|
244
|
-
| `nerviq history` |
|
|
245
|
-
| `nerviq compare` | Compare latest vs previous |
|
|
246
|
-
| `nerviq trend` | Export trend report |
|
|
252
|
+
| `nerviq history` | Audit snapshot history from saved snapshots |
|
|
253
|
+
| `nerviq compare` | Compare latest vs previous audit snapshot |
|
|
254
|
+
| `nerviq trend` | Export audit snapshot trend report |
|
|
247
255
|
| `nerviq feedback` | Record recommendation outcomes |
|
|
248
256
|
| `nerviq anti-patterns` | Detect anti-patterns in current project |
|
|
249
257
|
| `nerviq freshness` | Show verification freshness for all checks |
|
|
@@ -281,7 +289,7 @@ Levels:
|
|
|
281
289
|
| `--only A,B` | Limit apply to selected proposal IDs |
|
|
282
290
|
| `--format sarif` | SARIF output for code scanning |
|
|
283
291
|
| `--platform NAME` | Target platform (claude, codex, gemini, copilot, cursor, windsurf, aider, opencode) |
|
|
284
|
-
| `--workspace GLOB` | Audit workspaces separately (e.g. packages/*) |
|
|
292
|
+
| `--workspace GLOB` | Audit workspaces separately as package-level live audits (e.g. packages/*) |
|
|
285
293
|
| `--external PATH` | Benchmark an external repo |
|
|
286
294
|
|
|
287
295
|
## Backed by Research
|
|
@@ -290,7 +298,7 @@ Nerviq is built on the NERVIQ knowledge engine — the largest verified catalog
|
|
|
290
298
|
|
|
291
299
|
- **448+ research documents** covering all 8 platforms
|
|
292
300
|
- **332+ experiments** with tested, rated results
|
|
293
|
-
- **2,
|
|
301
|
+
- **2,438 checks** across 8 platforms (~300 unique governance rules × 8 platform adaptations), each with `sourceUrl` and `confidence` level (0.0-1.0)
|
|
294
302
|
- Every check is traceable to primary documentation or verified experiment
|
|
295
303
|
- 90-day freshness cycle: stale findings are re-verified or pruned
|
|
296
304
|
|
|
@@ -333,9 +341,9 @@ If Nerviq helped you, consider giving it a ⭐ on [GitHub](https://github.com/ne
|
|
|
333
341
|
|
|
334
342
|
**Not designed for:** Deeply customized setups with 20+ skills, agent teams, and bespoke MCP integrations. If you've already built advanced agent workflows, you may not need this.
|
|
335
343
|
|
|
336
|
-
**Strongest at:**
|
|
337
|
-
|
|
338
|
-
**Not a replacement for:** Deep architectural review of business logic, runtime performance profiling, or security penetration testing. Nerviq focuses on how your AI coding agents are configured and governed — not on what your application code does.
|
|
344
|
+
**Strongest at:** AI agent governance, configuration intelligence, workflow policy hygiene, cross-platform alignment, and setup standardization.
|
|
345
|
+
|
|
346
|
+
**Not a replacement for:** Deep architectural review of business logic, runtime performance profiling, full SAST coverage, secret scanning, or security penetration testing. Nerviq focuses on how your AI coding agents are configured and governed — not on what your application code does.
|
|
339
347
|
|
|
340
348
|
**Confidence levels:** Every check includes a `confidence` score (0.0–1.0) and a `sourceUrl` linking to primary documentation. Checks marked `heuristic` are pattern-based and may produce false positives on non-standard project structures.
|
|
341
349
|
|
package/bin/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ const { auditWorkspaces } = require('../src/workspace');
|
|
|
14
14
|
const { scanOrg } = require('../src/org');
|
|
15
15
|
const { detectAntiPatterns, printAntiPatterns, printAntiPatternCatalog } = require('../src/anti-patterns');
|
|
16
16
|
const { VERIFICATION_DATES, getVerificationDate, getVerificationStats } = require('../src/verification-metadata');
|
|
17
|
+
const { init: initI18n, t } = require('../src/i18n');
|
|
17
18
|
const { version } = require('../package.json');
|
|
18
19
|
|
|
19
20
|
const args = process.argv.slice(2);
|
|
@@ -60,9 +61,9 @@ function suggestCommand(input) {
|
|
|
60
61
|
return bestDistance <= 3 ? best : null;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
function parseArgs(rawArgs) {
|
|
64
|
-
const flags = [];
|
|
65
|
-
let command = 'audit';
|
|
64
|
+
function parseArgs(rawArgs) {
|
|
65
|
+
const flags = [];
|
|
66
|
+
let command = 'audit';
|
|
66
67
|
let threshold = null;
|
|
67
68
|
let out = null;
|
|
68
69
|
let planFile = null;
|
|
@@ -88,14 +89,16 @@ function parseArgs(rawArgs) {
|
|
|
88
89
|
let migrateFrom = null;
|
|
89
90
|
let migrateTo = null;
|
|
90
91
|
let checkVersion = null;
|
|
91
|
-
let external = null;
|
|
92
|
-
let repos = [];
|
|
93
|
-
let teamProfile = null;
|
|
92
|
+
let external = null;
|
|
93
|
+
let repos = [];
|
|
94
|
+
let teamProfile = null;
|
|
95
|
+
let lang = null;
|
|
96
|
+
let commandExplicit = false;
|
|
94
97
|
|
|
95
98
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
96
99
|
const arg = rawArgs[i];
|
|
97
100
|
|
|
98
|
-
if (arg === '--threshold' || arg === '--out' || arg === '--plan' || arg === '--only' || arg === '--profile' || arg === '--mcp-pack' || arg === '--require' || arg === '--key' || arg === '--status' || arg === '--effect' || arg === '--notes' || arg === '--source' || arg === '--score-delta' || arg === '--platform' || arg === '--format' || arg === '--from' || arg === '--to' || arg === '--port' || arg === '--workspace' || arg === '--check-version' || arg === '--webhook' || arg === '--external' || arg === '--team-profile') {
|
|
101
|
+
if (arg === '--threshold' || arg === '--out' || arg === '--plan' || arg === '--only' || arg === '--profile' || arg === '--mcp-pack' || arg === '--require' || arg === '--key' || arg === '--status' || arg === '--effect' || arg === '--notes' || arg === '--source' || arg === '--score-delta' || arg === '--platform' || arg === '--format' || arg === '--from' || arg === '--to' || arg === '--port' || arg === '--workspace' || arg === '--check-version' || arg === '--webhook' || arg === '--external' || arg === '--team-profile' || arg === '--lang') {
|
|
99
102
|
const value = rawArgs[i + 1];
|
|
100
103
|
if (!value || value.startsWith('--')) {
|
|
101
104
|
throw new Error(`${arg} requires a value`);
|
|
@@ -123,10 +126,16 @@ function parseArgs(rawArgs) {
|
|
|
123
126
|
if (arg === '--webhook') webhookUrl = value.trim();
|
|
124
127
|
if (arg === '--external') external = value.trim();
|
|
125
128
|
if (arg === '--team-profile') teamProfile = value.trim();
|
|
129
|
+
if (arg === '--lang') lang = value.trim().toLowerCase();
|
|
126
130
|
i++;
|
|
127
131
|
continue;
|
|
128
132
|
}
|
|
129
133
|
|
|
134
|
+
if (arg.startsWith('--lang=')) {
|
|
135
|
+
lang = arg.split('=').slice(1).join('=').trim().toLowerCase();
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
130
139
|
if (arg.startsWith('--team-profile=')) {
|
|
131
140
|
teamProfile = arg.split('=').slice(1).join('=').trim();
|
|
132
141
|
continue;
|
|
@@ -248,37 +257,47 @@ function parseArgs(rawArgs) {
|
|
|
248
257
|
continue;
|
|
249
258
|
}
|
|
250
259
|
|
|
251
|
-
if (!commandSet) {
|
|
252
|
-
command = arg;
|
|
253
|
-
commandSet = true;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
if (!commandSet) {
|
|
261
|
+
command = arg;
|
|
262
|
+
commandSet = true;
|
|
263
|
+
commandExplicit = true;
|
|
264
|
+
} else {
|
|
265
|
+
extraArgs.push(arg);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
258
268
|
|
|
259
269
|
const normalizedCommand = COMMAND_ALIASES[command] || command;
|
|
260
270
|
|
|
261
|
-
return { flags, command, normalizedCommand, threshold, out, planFile, only, profile, mcpPacks, requireChecks, feedbackKey, feedbackStatus, feedbackEffect, feedbackNotes, feedbackSource, feedbackScoreDelta, platform, format, port, workspace, extraArgs, convertFrom, convertTo, migrateFrom, migrateTo, checkVersion, webhookUrl, external, repos, teamProfile };
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function printWorkspaceSummary(summary, options) {
|
|
265
|
-
if (options.json) {
|
|
266
|
-
console.log(JSON.stringify(summary, null, 2));
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
console.log(
|
|
274
|
-
console.log(
|
|
275
|
-
console.log(
|
|
276
|
-
console.log(`
|
|
277
|
-
console.log(
|
|
278
|
-
console.log(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
271
|
+
return { flags, command, commandExplicit, normalizedCommand, threshold, out, planFile, only, profile, mcpPacks, requireChecks, feedbackKey, feedbackStatus, feedbackEffect, feedbackNotes, feedbackSource, feedbackScoreDelta, platform, format, port, workspace, extraArgs, convertFrom, convertTo, migrateFrom, migrateTo, checkVersion, webhookUrl, external, repos, teamProfile, lang };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function printWorkspaceSummary(summary, options) {
|
|
275
|
+
if (options.json) {
|
|
276
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const rootScore = summary.rootGovernance?.score === null ? 'ERR' : `${summary.rootGovernance?.score ?? 0}/100`;
|
|
281
|
+
const workspaceAverage = summary.workspaceAggregate?.score ?? summary.averageScore;
|
|
282
|
+
|
|
283
|
+
console.log('');
|
|
284
|
+
console.log('\x1b[1m nerviq workspace audit\x1b[0m');
|
|
285
|
+
console.log('\x1b[2m ═══════════════════════════════════════\x1b[0m');
|
|
286
|
+
console.log(` Root: ${summary.rootDir}`);
|
|
287
|
+
console.log(` Platform: ${summary.platform}`);
|
|
288
|
+
console.log(` Workspaces: ${summary.workspaceCount}`);
|
|
289
|
+
if (summary.patterns?.length > 0) {
|
|
290
|
+
console.log(` Selection: ${summary.patterns.join(', ')}`);
|
|
291
|
+
}
|
|
292
|
+
console.log(` Root governance audit: \x1b[1m${rootScore}\x1b[0m`);
|
|
293
|
+
console.log(` Workspace audit average: \x1b[1m${workspaceAverage}/100\x1b[0m`);
|
|
294
|
+
console.log(' Score semantics: root governance shows shared repo policy health; workspace average shows package-level coverage across the selected workspaces.');
|
|
295
|
+
console.log(' Aggregate vs package: per-workspace scores can legitimately trail the root repo score in a monorepo.');
|
|
296
|
+
console.log('');
|
|
297
|
+
console.log('\x1b[1m Workspace Audit Pass Total Top action\x1b[0m');
|
|
298
|
+
console.log(' ' + '─'.repeat(72));
|
|
299
|
+
for (const item of summary.workspaces) {
|
|
300
|
+
const score = item.score === null ? 'ERR' : String(item.score);
|
|
282
301
|
const topAction = item.error || item.topAction || '-';
|
|
283
302
|
console.log(` ${item.workspace.padEnd(26)} ${score.padStart(5)} ${String(item.passed).padStart(5)} ${String(item.total).padStart(6)} ${topAction}`);
|
|
284
303
|
}
|
|
@@ -358,17 +377,18 @@ function printOrgSummary(summary, options) {
|
|
|
358
377
|
console.log('');
|
|
359
378
|
}
|
|
360
379
|
|
|
361
|
-
const HELP = `
|
|
362
|
-
nerviq v${version}
|
|
363
|
-
The intelligent nervous system for AI coding agents.
|
|
364
|
-
Audit, align, and amplify every platform on every project.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
nerviq audit
|
|
369
|
-
nerviq audit --
|
|
370
|
-
nerviq audit --
|
|
371
|
-
nerviq audit --
|
|
380
|
+
const HELP = `
|
|
381
|
+
nerviq v${version}
|
|
382
|
+
The intelligent nervous system for AI coding agents.
|
|
383
|
+
Audit, align, and amplify every platform on every project.
|
|
384
|
+
New here? Run: nerviq --beginner
|
|
385
|
+
|
|
386
|
+
DISCOVER
|
|
387
|
+
nerviq audit Quick scan: score + top 3 gaps (default)
|
|
388
|
+
nerviq audit --full Full audit with all checks, weakest areas, badge
|
|
389
|
+
nerviq audit --platform X Audit specific platform (claude|codex|cursor|copilot|gemini|windsurf|aider|opencode)
|
|
390
|
+
nerviq audit --json Machine-readable JSON output (for CI)
|
|
391
|
+
nerviq audit --workspace packages/* Audit monorepo workspaces with root-vs-package score semantics
|
|
372
392
|
nerviq scan dir1 dir2 Compare multiple repos side-by-side
|
|
373
393
|
nerviq org scan dir1 dir2 Aggregate multiple repos into one score table
|
|
374
394
|
nerviq catalog Full check catalog (all 8 platforms)
|
|
@@ -405,30 +425,30 @@ const HELP = `
|
|
|
405
425
|
GOVERN
|
|
406
426
|
nerviq governance Permission profiles + hooks + policy packs
|
|
407
427
|
nerviq governance --json Machine-readable governance summary
|
|
408
|
-
nerviq benchmark
|
|
428
|
+
nerviq benchmark Baseline vs projected score in isolated temp copy
|
|
409
429
|
nerviq benchmark --external /path Benchmark an external repo
|
|
410
430
|
nerviq freshness Show verification freshness for all checks
|
|
411
431
|
nerviq certify Generate certification badge for your project
|
|
412
432
|
|
|
413
433
|
CROSS-PLATFORM
|
|
414
|
-
nerviq harmony-audit Drift detection across all active platforms
|
|
415
|
-
nerviq harmony-sync Preview cross-platform sync (dry run)
|
|
416
|
-
nerviq harmony-sync --fix Apply cross-platform sync (write files)
|
|
417
|
-
nerviq harmony-sync --json JSON output for CI/automation
|
|
418
|
-
nerviq harmony-add <platform> Add a new platform to the project
|
|
419
|
-
nerviq synergy-report
|
|
434
|
+
nerviq harmony-audit Drift detection across all active platforms (GA)
|
|
435
|
+
nerviq harmony-sync Preview cross-platform sync (dry run, GA)
|
|
436
|
+
nerviq harmony-sync --fix Apply cross-platform sync (write files, GA)
|
|
437
|
+
nerviq harmony-sync --json JSON output for CI/automation
|
|
438
|
+
nerviq harmony-add <platform> Add a new platform to the project
|
|
439
|
+
nerviq synergy-report [EXPERIMENTAL] Static-rule multi-agent amplification report
|
|
420
440
|
nerviq convert --from X --to Y Convert configs between platforms
|
|
421
441
|
nerviq migrate --platform X Platform version migration helper
|
|
422
442
|
nerviq migrate --platform cursor --from v2 --to v3
|
|
423
443
|
|
|
424
444
|
MONITOR
|
|
425
|
-
nerviq dashboard Generate static
|
|
445
|
+
nerviq dashboard Generate static dashboard from latest audit snapshot (or live audit if none)
|
|
426
446
|
nerviq dashboard --out F Save dashboard to custom file
|
|
427
447
|
nerviq dashboard --open Open dashboard in browser after generating
|
|
428
448
|
nerviq watch Live config monitoring (re-audits on file change)
|
|
429
|
-
nerviq history
|
|
430
|
-
nerviq compare Latest vs previous snapshot diff
|
|
431
|
-
nerviq trend
|
|
449
|
+
nerviq history Audit snapshot history from saved snapshots
|
|
450
|
+
nerviq compare Latest vs previous audit snapshot diff
|
|
451
|
+
nerviq trend Audit snapshot trend over time
|
|
432
452
|
nerviq trend --out report.md Export trend report as markdown
|
|
433
453
|
nerviq feedback Record recommendation outcomes
|
|
434
454
|
|
|
@@ -461,26 +481,28 @@ const HELP = `
|
|
|
461
481
|
--webhook URL Send audit results to a webhook (Slack/Discord/generic JSON)
|
|
462
482
|
--external PATH Benchmark an external repo instead of cwd
|
|
463
483
|
--port N Port for \`serve\` (default: 3000)
|
|
464
|
-
--workspace GLOBS Audit workspaces separately
|
|
484
|
+
--workspace GLOBS Audit workspaces separately and label root governance vs package scores
|
|
465
485
|
--snapshot Save snapshot artifact under .claude/nerviq/snapshots/
|
|
466
486
|
--full Show full audit output (all checks, weakest areas, badge)
|
|
467
487
|
--lite Short top-3 scan (default behavior since v1.5.2)
|
|
468
488
|
--dry-run Preview changes without writing files
|
|
469
489
|
--config-only Only write config files (.claude/, rules, hooks) — never source code
|
|
470
490
|
--verbose Full audit + medium-priority recommendations
|
|
471
|
-
--show-deprecated Show deprecated checks (excluded from scoring)
|
|
472
|
-
--json Output as JSON
|
|
473
|
-
--auto Apply all generated files without prompting
|
|
474
|
-
--
|
|
491
|
+
--show-deprecated Show deprecated checks (excluded from scoring)
|
|
492
|
+
--json Output as JSON
|
|
493
|
+
--auto Apply all generated files without prompting
|
|
494
|
+
--beginner Show only the 5 starter commands for first-time users
|
|
495
|
+
--key NAME Feedback: recommendation key (e.g. permissionDeny)
|
|
475
496
|
--status VALUE Feedback: accepted | rejected | deferred
|
|
476
497
|
--effect VALUE Feedback: positive | neutral | negative
|
|
477
498
|
--score-delta N Feedback: observed score delta
|
|
478
499
|
--help Show this help
|
|
479
500
|
--version Show version
|
|
480
501
|
|
|
481
|
-
EXAMPLES
|
|
482
|
-
npx nerviq
|
|
483
|
-
npx nerviq
|
|
502
|
+
EXAMPLES
|
|
503
|
+
npx nerviq --beginner
|
|
504
|
+
npx nerviq
|
|
505
|
+
npx nerviq --lite
|
|
484
506
|
npx nerviq --platform cursor
|
|
485
507
|
npx nerviq audit --workspace packages/*
|
|
486
508
|
npx nerviq --platform codex augment
|
|
@@ -497,9 +519,34 @@ const HELP = `
|
|
|
497
519
|
npx nerviq feedback --key permissionDeny --status accepted --effect positive
|
|
498
520
|
|
|
499
521
|
EXIT CODES
|
|
500
|
-
0 Success
|
|
501
|
-
1 Error, unknown command, or score below --threshold
|
|
502
|
-
`;
|
|
522
|
+
0 Success
|
|
523
|
+
1 Error, unknown command, or score below --threshold
|
|
524
|
+
`;
|
|
525
|
+
|
|
526
|
+
const BEGINNER_HELP = `
|
|
527
|
+
nerviq v${version}
|
|
528
|
+
Start here.
|
|
529
|
+
|
|
530
|
+
If this is your first time, learn just these 5 commands:
|
|
531
|
+
|
|
532
|
+
STARTER COMMANDS
|
|
533
|
+
nerviq audit Score the repo and show the top gaps
|
|
534
|
+
nerviq setup Generate a starter-safe baseline
|
|
535
|
+
nerviq fix Fix what can be fixed or show manual fix guidance
|
|
536
|
+
nerviq augment Show an improvement plan without writing
|
|
537
|
+
nerviq doctor Check install health, freshness, and platform detection
|
|
538
|
+
|
|
539
|
+
SIMPLE PATH
|
|
540
|
+
1. nerviq audit
|
|
541
|
+
2. nerviq setup --auto
|
|
542
|
+
3. nerviq fix --all-critical --auto
|
|
543
|
+
4. nerviq augment
|
|
544
|
+
5. nerviq doctor
|
|
545
|
+
|
|
546
|
+
WHEN YOU ARE READY
|
|
547
|
+
nerviq --help Show the full command set
|
|
548
|
+
Docs: https://nerviq.net/docs/getting-started
|
|
549
|
+
`;
|
|
503
550
|
|
|
504
551
|
async function main() {
|
|
505
552
|
let parsed;
|
|
@@ -510,17 +557,27 @@ async function main() {
|
|
|
510
557
|
process.exit(1);
|
|
511
558
|
}
|
|
512
559
|
|
|
513
|
-
const { flags, command, normalizedCommand } = parsed;
|
|
560
|
+
const { flags, command, commandExplicit, normalizedCommand } = parsed;
|
|
514
561
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
562
|
+
// Initialize i18n with --lang flag or NERVIQ_LANG env var
|
|
563
|
+
if (parsed.lang) {
|
|
564
|
+
initI18n(parsed.lang);
|
|
518
565
|
}
|
|
519
566
|
|
|
520
|
-
if (flags.includes('--version') || command === 'version') {
|
|
521
|
-
console.log(version);
|
|
522
|
-
process.exit(0);
|
|
523
|
-
}
|
|
567
|
+
if (flags.includes('--version') || command === 'version') {
|
|
568
|
+
console.log(version);
|
|
569
|
+
process.exit(0);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (flags.includes('--beginner') && (!commandExplicit || flags.includes('--help') || command === 'help')) {
|
|
573
|
+
console.log(BEGINNER_HELP);
|
|
574
|
+
process.exit(0);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (flags.includes('--help') || command === 'help') {
|
|
578
|
+
console.log(HELP);
|
|
579
|
+
process.exit(0);
|
|
580
|
+
}
|
|
524
581
|
|
|
525
582
|
const options = {
|
|
526
583
|
verbose: flags.includes('--verbose'),
|
|
@@ -547,6 +604,7 @@ async function main() {
|
|
|
547
604
|
port: parsed.port !== null ? Number(parsed.port) : null,
|
|
548
605
|
workspace: parsed.workspace || null,
|
|
549
606
|
webhookUrl: parsed.webhookUrl || null,
|
|
607
|
+
lang: parsed.lang || null,
|
|
550
608
|
external: parsed.external || null,
|
|
551
609
|
dir: process.cwd()
|
|
552
610
|
};
|
|
@@ -732,9 +790,9 @@ async function main() {
|
|
|
732
790
|
process.exit(1);
|
|
733
791
|
}
|
|
734
792
|
process.exit(0);
|
|
735
|
-
} else if (normalizedCommand === 'history') {
|
|
736
|
-
const { formatHistory, readSnapshotIndex } = require('../src/activity');
|
|
737
|
-
// Handle --prune N
|
|
793
|
+
} else if (normalizedCommand === 'history') {
|
|
794
|
+
const { formatHistory, readSnapshotIndex } = require('../src/activity');
|
|
795
|
+
// Handle --prune N
|
|
738
796
|
const pruneIdx = flags.indexOf('--prune');
|
|
739
797
|
if (pruneIdx >= 0) {
|
|
740
798
|
const keepCount = parseInt(flags[pruneIdx + 1] || parsed.extraArgs[0], 10) || 10;
|
|
@@ -742,7 +800,7 @@ async function main() {
|
|
|
742
800
|
const pathMod = require('path');
|
|
743
801
|
const entries = readSnapshotIndex(options.dir);
|
|
744
802
|
if (entries.length <= keepCount) {
|
|
745
|
-
console.log(`\n Nothing to prune (${entries.length} snapshots, keeping ${keepCount}).\n`);
|
|
803
|
+
console.log(`\n Nothing to prune (${entries.length} audit snapshots, keeping ${keepCount}).\n`);
|
|
746
804
|
} else {
|
|
747
805
|
const toRemove = entries.slice(0, entries.length - keepCount);
|
|
748
806
|
let removed = 0;
|
|
@@ -753,42 +811,53 @@ async function main() {
|
|
|
753
811
|
const kept = entries.slice(entries.length - keepCount);
|
|
754
812
|
const indexPath = pathMod.join(options.dir, '.nerviq', 'snapshots', 'index.json');
|
|
755
813
|
try { fsMod.writeFileSync(indexPath, JSON.stringify(kept, null, 2), 'utf8'); } catch {}
|
|
756
|
-
console.log(`\n Pruned ${removed} snapshots, kept ${kept.length}.\n`);
|
|
814
|
+
console.log(`\n Pruned ${removed} audit snapshots, kept ${kept.length}.\n`);
|
|
757
815
|
}
|
|
758
816
|
process.exit(0);
|
|
759
817
|
}
|
|
760
818
|
console.log('');
|
|
761
|
-
console.log(formatHistory(options.dir));
|
|
762
|
-
console.log('');
|
|
763
|
-
process.exit(0);
|
|
764
|
-
} else if (normalizedCommand === 'compare') {
|
|
765
|
-
const { compareLatest } = require('../src/activity');
|
|
766
|
-
const result = compareLatest(options.dir);
|
|
767
|
-
if (!result) {
|
|
768
|
-
console.log('
|
|
769
|
-
|
|
770
|
-
|
|
819
|
+
console.log(formatHistory(options.dir));
|
|
820
|
+
console.log('');
|
|
821
|
+
process.exit(0);
|
|
822
|
+
} else if (normalizedCommand === 'compare') {
|
|
823
|
+
const { compareLatest, formatSnapshotBootstrap } = require('../src/activity');
|
|
824
|
+
const result = compareLatest(options.dir);
|
|
825
|
+
if (!result) {
|
|
826
|
+
console.log('');
|
|
827
|
+
console.log(formatSnapshotBootstrap(options.dir, 'compare'));
|
|
828
|
+
console.log('');
|
|
829
|
+
process.exit(0);
|
|
830
|
+
}
|
|
771
831
|
if (options.json) {
|
|
772
832
|
console.log(JSON.stringify(result, null, 2));
|
|
773
833
|
} else {
|
|
774
834
|
const sign = result.delta.score >= 0 ? '+' : '';
|
|
775
835
|
console.log('');
|
|
776
|
-
console.log(` Previous: ${result.previous.score}/100 (${result.previous.date?.split('T')[0]})`);
|
|
777
|
-
console.log(` Current: ${result.current.score}/100 (${result.current.date?.split('T')[0]})`);
|
|
778
|
-
console.log(`
|
|
779
|
-
console.log(` Trend: ${result.trend}`);
|
|
836
|
+
console.log(` Previous snapshot: ${result.previous.score}/100 (${result.previous.date?.split('T')[0]})`);
|
|
837
|
+
console.log(` Current snapshot: ${result.current.score}/100 (${result.current.date?.split('T')[0]})`);
|
|
838
|
+
console.log(` Snapshot delta: ${sign}${result.delta.score} points`);
|
|
839
|
+
console.log(` Trend: ${result.trend}`);
|
|
780
840
|
if (result.improvements.length > 0) console.log(` Fixed: ${result.improvements.join(', ')}`);
|
|
781
841
|
if (result.regressions.length > 0) console.log(` New gaps: ${result.regressions.join(', ')}`);
|
|
782
842
|
console.log('');
|
|
783
|
-
}
|
|
784
|
-
process.exit(0);
|
|
785
|
-
} else if (normalizedCommand === 'trend') {
|
|
786
|
-
const { exportTrendReport } = require('../src/activity');
|
|
787
|
-
const
|
|
788
|
-
if (
|
|
789
|
-
console.log('
|
|
790
|
-
|
|
791
|
-
|
|
843
|
+
}
|
|
844
|
+
process.exit(0);
|
|
845
|
+
} else if (normalizedCommand === 'trend') {
|
|
846
|
+
const { exportTrendReport, getHistory, formatSnapshotBootstrap } = require('../src/activity');
|
|
847
|
+
const auditHistory = getHistory(options.dir, 2);
|
|
848
|
+
if (auditHistory.length < 2) {
|
|
849
|
+
console.log('');
|
|
850
|
+
console.log(formatSnapshotBootstrap(options.dir, 'trend'));
|
|
851
|
+
console.log('');
|
|
852
|
+
process.exit(0);
|
|
853
|
+
}
|
|
854
|
+
const report = exportTrendReport(options.dir);
|
|
855
|
+
if (!report) {
|
|
856
|
+
console.log('');
|
|
857
|
+
console.log(formatSnapshotBootstrap(options.dir, 'trend'));
|
|
858
|
+
console.log('');
|
|
859
|
+
process.exit(0);
|
|
860
|
+
}
|
|
792
861
|
if (options.out) {
|
|
793
862
|
require('fs').writeFileSync(options.out, report, 'utf8');
|
|
794
863
|
console.log(`\n Trend report exported to ${options.out}\n`);
|