@vibgrate/cli 2026.610.1 → 2026.610.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/DOCS.md CHANGED
@@ -162,7 +162,7 @@ Creates:
162
162
  The primary command. Scans your project for upgrade drift.
163
163
 
164
164
  ```bash
165
- vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] [--baseline <file>] [--drift-budget <score>] [--drift-worsening <percent>] [--changed-only] [--concurrency <n>]
165
+ vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] [--baseline <file>] [--drift-budget <score>] [--drift-worsening <percent>] [--changed-only] [--exclude <glob>...] [--concurrency <n>]
166
166
  ```
167
167
 
168
168
  | Flag | Default | Description |
@@ -172,6 +172,7 @@ vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on war
172
172
  | `--fail-on <level>` | — | Exit with code 2 if findings at this level exist |
173
173
  | `--baseline <file>` | — | Compare against a previous baseline |
174
174
  | `--changed-only` | — | Only scan changed files |
175
+ | `-e, --exclude <glob>` | — | Exclude paths matching a glob pattern. Repeatable, and a single value may list several patterns separated by commas or semicolons. Merged with `exclude` from the config file |
175
176
  | `--concurrency <n>` | `8` | Max concurrent npm registry calls |
176
177
  | `--drift-budget <score>` | — | Fitness gate: fail if drift score is above this budget |
177
178
  | `--drift-worsening <percent>` | — | Fitness gate: fail if drift worsens by more than % vs baseline |
@@ -189,6 +190,32 @@ By default, the scan writes `.vibgrate/scan_result.json`. Use `--no-local-artifa
189
190
 
190
191
  For offline drift scoring, pass `--package-manifest <file>` with a downloaded manifest bundle such as `https://github.com/vibgrate/manifests/latest-packages.zip`.
191
192
 
193
+ #### Excluding paths from a scan
194
+
195
+ Use `--exclude` (alias `-e`) to skip directories or files from the scan. Values are [glob patterns](#exclude-glob-syntax) matched against repository-relative, forward-slash paths. The flag is **repeatable**, and a single value may carry **several patterns separated by commas or semicolons** — use whichever reads best:
196
+
197
+ ```bash
198
+ # Repeat the flag
199
+ vibgrate scan . --exclude "legacy/**" --exclude "vendor/**"
200
+
201
+ # Or list multiple patterns in one flag (comma- or semicolon-separated)
202
+ vibgrate scan . --exclude "legacy/**,vendor/**;**/fixtures/**"
203
+ ```
204
+
205
+ CLI excludes are **additive**: they are merged (and de-duplicated) with any `exclude` patterns from your [config file](#configuration), so command-line excludes never replace your committed defaults.
206
+
207
+ <a id="exclude-glob-syntax"></a>
208
+ Supported glob syntax:
209
+
210
+ | Pattern | Matches |
211
+ |---------|---------|
212
+ | `*` | Any run of characters within a single path segment (no `/`) |
213
+ | `**` | Any number of path segments, including `/` (recursive) |
214
+ | `?` | Exactly one non-separator character |
215
+ | `{a,b}` | Alternation — either `a` or `b` |
216
+ | `[abc]` | A single character from the set |
217
+ | `legacy` | A bare name is treated as a directory prefix — equivalent to `legacy/**` |
218
+
192
219
  Examples:
193
220
 
194
221
  ```bash
@@ -198,6 +225,9 @@ vibgrate scan .
198
225
  # JSON output for automation
199
226
  vibgrate scan . --format json --out scan.json
200
227
 
228
+ # Skip vendored and generated code
229
+ vibgrate scan . --exclude "vendor/**,**/*.generated.ts;dist/**"
230
+
201
231
  # CI gate with baseline regression protection
202
232
  vibgrate scan . --baseline .vibgrate/baseline.json --drift-budget 40 --drift-worsening 5 --fail-on error
203
233
 
@@ -433,6 +463,18 @@ export default config;
433
463
 
434
464
  Also supports `vibgrate.config.js` and `vibgrate.config.json`.
435
465
 
466
+ ### Exclude patterns
467
+
468
+ `exclude` accepts an array of glob patterns describing paths the scan should skip (relative to the repository root, forward-slash separated). See [exclude glob syntax](#exclude-glob-syntax) for the supported patterns.
469
+
470
+ ```typescript
471
+ const config: VibgrateConfig = {
472
+ exclude: ["legacy/**", "vendor/**", "**/*.generated.ts"],
473
+ };
474
+ ```
475
+
476
+ The same patterns can be supplied per-run on the command line with [`--exclude`](#excluding-paths-from-a-scan). CLI excludes are merged with (not a replacement for) the config `exclude` list, so committed defaults always apply and ad-hoc excludes are additive.
477
+
436
478
  ### Thresholds
437
479
 
438
480
  Control when findings are raised and when the CLI should fail.
package/README.md CHANGED
@@ -193,7 +193,7 @@ When offline mode runs without a package manifest, package freshness is marked a
193
193
  ## Core commands
194
194
 
195
195
  ```bash
196
- vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy]
196
+ vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--exclude <glob>...] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy]
197
197
  vibgrate baseline [path]
198
198
  vibgrate report [--in <artifact.json>] [--format md|text|json]
199
199
  vibgrate push [--dsn <dsn>] [--file <artifact.json>] [--strict]
@@ -225,7 +225,19 @@ Expected result:
225
225
  - Exit code `2` when the configured gate is exceeded
226
226
 
227
227
  ```bash
228
- # 3) Offline scan using local package-version bundle
228
+ # 3) Scan while excluding vendored / generated paths
229
+ # --exclude is repeatable and accepts comma/semicolon-separated globs;
230
+ # patterns are merged with `exclude` from vibgrate.config.*
231
+ npx @vibgrate/cli scan . --exclude "legacy/**,vendor/**" --exclude "**/*.generated.ts"
232
+ ```
233
+
234
+ Expected result:
235
+
236
+ - Matching directories and files are skipped before scanning
237
+ - Excludes from the config file still apply (CLI patterns are additive)
238
+
239
+ ```bash
240
+ # 4) Offline scan using local package-version bundle
229
241
  npx @vibgrate/cli scan . --offline --package-manifest ./latest-packages.zip --format json --out scan.json
230
242
  ```
231
243
 
@@ -236,7 +248,7 @@ Expected result:
236
248
  - Package freshness may be marked unknown if manifest lacks entries
237
249
 
238
250
  ```bash
239
- # 4) Export SBOM and compare two runs
251
+ # 5) Export SBOM and compare two runs
240
252
  npx @vibgrate/cli sbom export --format cyclonedx --out sbom.cdx.json
241
253
  npx @vibgrate/cli sbom delta --from .vibgrate/baseline.json --to .vibgrate/scan_result.json --out sbom-delta.txt
242
254
  ```
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  baselineCommand,
3
3
  runBaseline
4
- } from "./chunk-HQCB2BTS.js";
5
- import "./chunk-X2MPRPZ6.js";
4
+ } from "./chunk-GH53OHBI.js";
5
+ import "./chunk-5HKSJI57.js";
6
6
  import "./chunk-74ZJFYEM.js";
7
- import "./chunk-RAQ76CZO.js";
7
+ import "./chunk-W6LGNQSJ.js";
8
8
  import "./chunk-JSBRDJBE.js";
9
9
  export {
10
10
  baselineCommand,
@@ -14,7 +14,7 @@ import {
14
14
  readTextFile,
15
15
  writeJsonFile,
16
16
  writeTextFile
17
- } from "./chunk-RAQ76CZO.js";
17
+ } from "./chunk-W6LGNQSJ.js";
18
18
  import {
19
19
  __commonJS,
20
20
  __toESM
@@ -4938,7 +4938,7 @@ async function scanPythonProjects(rootDir, pypiCache, cache, projectScanTimeout)
4938
4938
  return results;
4939
4939
  }
4940
4940
  async function findPythonManifests(rootDir) {
4941
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
4941
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
4942
4942
  return findFiles2(rootDir, (name) => PYTHON_MANIFEST_FILES.has(name) || /^requirements.*\.txt$/.test(name));
4943
4943
  }
4944
4944
  async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cache) {
@@ -5335,7 +5335,7 @@ async function scanJavaProjects(rootDir, mavenCache, cache, projectScanTimeout)
5335
5335
  return results;
5336
5336
  }
5337
5337
  async function findJavaManifests(rootDir) {
5338
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
5338
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
5339
5339
  return findFiles2(rootDir, (name) => JAVA_MANIFEST_FILES.has(name));
5340
5340
  }
5341
5341
  async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache) {
@@ -5700,7 +5700,7 @@ async function scanRubyProjects(rootDir, rubygemsCache, cache, projectScanTimeou
5700
5700
  return results;
5701
5701
  }
5702
5702
  async function findRubyManifests(rootDir) {
5703
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
5703
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
5704
5704
  return findFiles2(rootDir, (name) => RUBY_MANIFEST_FILES.has(name) || isGemspec(name));
5705
5705
  }
5706
5706
  async function scanOneRubyProject(dir, manifestFiles, rootDir, rubygemsCache, cache) {
@@ -5924,7 +5924,7 @@ async function scanSwiftProjects(rootDir, swiftCache, cache, projectScanTimeout)
5924
5924
  return results;
5925
5925
  }
5926
5926
  async function findSwiftManifests(rootDir) {
5927
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
5927
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
5928
5928
  return findFiles2(rootDir, (name) => SWIFT_MANIFEST_FILES.has(name));
5929
5929
  }
5930
5930
  async function scanOneSwiftProject(dir, manifestFile, rootDir, swiftCache, cache) {
@@ -6161,7 +6161,7 @@ async function scanGoProjects(rootDir, goCache, cache, projectScanTimeout) {
6161
6161
  return results;
6162
6162
  }
6163
6163
  async function findGoManifests(rootDir) {
6164
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
6164
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
6165
6165
  return findFiles2(rootDir, (name) => GO_MANIFEST_FILES.has(name));
6166
6166
  }
6167
6167
  async function scanOneGoProject(dir, manifestFile, rootDir, goCache, cache) {
@@ -6395,7 +6395,7 @@ async function scanRustProjects(rootDir, cargoCache, cache, projectScanTimeout)
6395
6395
  return results;
6396
6396
  }
6397
6397
  async function findRustManifests(rootDir) {
6398
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
6398
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
6399
6399
  return findFiles2(rootDir, (name) => RUST_MANIFEST_FILES.has(name));
6400
6400
  }
6401
6401
  async function scanOneRustProject(dir, manifestFile, rootDir, cargoCache, cache) {
@@ -6619,7 +6619,7 @@ async function scanPhpProjects(rootDir, composerCache, cache, projectScanTimeout
6619
6619
  return results;
6620
6620
  }
6621
6621
  async function findPhpManifests(rootDir) {
6622
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
6622
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
6623
6623
  return findFiles2(rootDir, (name) => PHP_MANIFEST_FILES.has(name));
6624
6624
  }
6625
6625
  async function scanOnePhpProject(dir, manifestFile, rootDir, composerCache, cache) {
@@ -6884,7 +6884,7 @@ async function scanDartProjects(rootDir, pubCache, cache, projectScanTimeout) {
6884
6884
  return results;
6885
6885
  }
6886
6886
  async function findDartManifests(rootDir) {
6887
- const { findFiles: findFiles2 } = await import("./fs-CMSVYM7J-QRLLRZ2J.js");
6887
+ const { findFiles: findFiles2 } = await import("./fs-IJIQMW3G-NJTQJLB6.js");
6888
6888
  return findFiles2(rootDir, (name) => DART_MANIFEST_FILES.has(name));
6889
6889
  }
6890
6890
  async function scanOneDartProject(dir, manifestFile, rootDir, pubCache, cache) {
@@ -13980,7 +13980,7 @@ async function runScan(rootDir, opts) {
13980
13980
  const composerCache = new ComposerCache(sem, packageManifest, offlineMode);
13981
13981
  const pubCache = new PubCache(sem, packageManifest, offlineMode);
13982
13982
  const fileCache = new FileCache();
13983
- const excludePatterns = config.exclude ?? [];
13983
+ const excludePatterns = [.../* @__PURE__ */ new Set([...config.exclude ?? [], ...opts.exclude ?? []])];
13984
13984
  fileCache.setExcludePatterns(excludePatterns);
13985
13985
  const projectScanTimeoutMs = (opts.projectScanTimeout ?? config.projectScanTimeout ?? 180) * 1e3;
13986
13986
  fileCache.setMaxFileSize(config.maxFileSizeToScan ?? 5242880);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runScan
3
- } from "./chunk-X2MPRPZ6.js";
3
+ } from "./chunk-5HKSJI57.js";
4
4
 
5
5
  // src/commands/baseline.ts
6
6
  import * as path3 from "path";
@@ -1,4 +1,4 @@
1
- // ../vibgrate-core/dist/chunk-6F5NUOIM.js
1
+ // ../vibgrate-core/dist/chunk-IDJRKJOC.js
2
2
  import { execFile } from "child_process";
3
3
  import * as fs from "fs/promises";
4
4
  import * as os from "os";
@@ -32,6 +32,18 @@ var Semaphore = class {
32
32
  else this.available++;
33
33
  }
34
34
  };
35
+ function parseExcludePatterns(input) {
36
+ if (input === void 0) return [];
37
+ const raw = Array.isArray(input) ? input : [input];
38
+ const out = [];
39
+ for (const entry of raw) {
40
+ for (const part of entry.split(/[,;]/)) {
41
+ const trimmed = part.trim();
42
+ if (trimmed) out.push(trimmed);
43
+ }
44
+ }
45
+ return [...new Set(out)];
46
+ }
35
47
  function compileGlobs(patterns) {
36
48
  if (patterns.length === 0) return null;
37
49
  const matchers = patterns.map((p) => compileOne(normalise(p)));
@@ -774,6 +786,7 @@ async function writeTextFile(filePath, content) {
774
786
 
775
787
  export {
776
788
  Semaphore,
789
+ parseExcludePatterns,
777
790
  FileCache,
778
791
  quickTreeCount,
779
792
  normalizeGlobForRipgrep,
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  pathExists,
7
7
  readJsonFile,
8
8
  writeTextFile
9
- } from "./chunk-HQCB2BTS.js";
9
+ } from "./chunk-GH53OHBI.js";
10
10
  import {
11
11
  computeRepoFingerprint,
12
12
  detectVcs,
@@ -16,13 +16,14 @@ import {
16
16
  resolveRepositoryName,
17
17
  runScan,
18
18
  writeDefaultConfig
19
- } from "./chunk-X2MPRPZ6.js";
19
+ } from "./chunk-5HKSJI57.js";
20
20
  import {
21
21
  require_semver
22
22
  } from "./chunk-74ZJFYEM.js";
23
23
  import {
24
+ parseExcludePatterns,
24
25
  pathExists as pathExists2
25
- } from "./chunk-RAQ76CZO.js";
26
+ } from "./chunk-W6LGNQSJ.js";
26
27
  import {
27
28
  __toESM
28
29
  } from "./chunk-JSBRDJBE.js";
@@ -48,7 +49,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
48
49
  console.log(chalk.green("\u2714") + ` Created ${chalk.bold("vibgrate.config.ts")}`);
49
50
  }
50
51
  if (opts.baseline) {
51
- const { runBaseline } = await import("./baseline-Q3S7D7RQ.js");
52
+ const { runBaseline } = await import("./baseline-FYQ2HRTZ.js");
52
53
  await runBaseline(rootDir);
53
54
  }
54
55
  console.log("");
@@ -302,6 +303,9 @@ async function autoPush(artifact, rootDir, opts) {
302
303
  if (opts.strict) process.exit(1);
303
304
  }
304
305
  }
306
+ function collectExcludes(value, previous) {
307
+ return [...previous, ...parseExcludePatterns(value)];
308
+ }
305
309
  function parseNonNegativeNumber(value, label) {
306
310
  if (value === void 0) return void 0;
307
311
  const parsed = Number(value);
@@ -310,7 +314,12 @@ function parseNonNegativeNumber(value, label) {
310
314
  }
311
315
  return parsed;
312
316
  }
313
- var scanCommand = new Command3("scan").description("Scan a project for upgrade drift").argument("[path]", "Path to scan", ".").option("--out <file>", "Output file path").option("--format <format>", "Output format (text|json|sarif|md)", "text").option("--fail-on <level>", "Fail on warn or error").option("--baseline <file>", "Compare against baseline").option("--changed-only", "Only scan changed files").option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--project-scan-timeout <seconds>", "Per-project scan timeout in seconds (default: 180)").option("--drift-budget <score>", "Fail if drift score is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").action(async (targetPath, opts) => {
317
+ var scanCommand = new Command3("scan").description("Scan a project for upgrade drift").argument("[path]", "Path to scan", ".").option("--out <file>", "Output file path").option("--format <format>", "Output format (text|json|sarif|md)", "text").option("--fail-on <level>", "Fail on warn or error").option("--baseline <file>", "Compare against baseline").option("--changed-only", "Only scan changed files").option(
318
+ "-e, --exclude <glob>",
319
+ 'Exclude paths matching a glob pattern. Repeatable, and a single value may list several patterns separated by commas or semicolons (e.g. --exclude "legacy/**,vendor/**"). Merged with excludes from the config file.',
320
+ collectExcludes,
321
+ []
322
+ ).option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--project-scan-timeout <seconds>", "Per-project scan timeout in seconds (default: 180)").option("--drift-budget <score>", "Fail if drift score is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").action(async (targetPath, opts) => {
314
323
  const rootDir = path3.resolve(targetPath);
315
324
  if (!await pathExists2(rootDir)) {
316
325
  console.error(chalk3.red(`Path does not exist: ${rootDir}`));
@@ -374,6 +383,7 @@ var scanCommand = new Command3("scan").description("Scan a project for upgrade d
374
383
  failOn: opts.failOn,
375
384
  baseline: opts.baseline,
376
385
  changedOnly: opts.changedOnly,
386
+ exclude: opts.exclude,
377
387
  concurrency: parseInt(opts.concurrency, 10) || 8,
378
388
  push: opts.push,
379
389
  dsn: opts.dsn,
@@ -14,7 +14,7 @@ import {
14
14
  readTextFile,
15
15
  writeJsonFile,
16
16
  writeTextFile
17
- } from "./chunk-RAQ76CZO.js";
17
+ } from "./chunk-W6LGNQSJ.js";
18
18
  import "./chunk-JSBRDJBE.js";
19
19
  export {
20
20
  FileCache,
package/dist/index.js CHANGED
@@ -5,9 +5,9 @@ import {
5
5
  formatText,
6
6
  generateFindings,
7
7
  runScan
8
- } from "./chunk-X2MPRPZ6.js";
8
+ } from "./chunk-5HKSJI57.js";
9
9
  import "./chunk-74ZJFYEM.js";
10
- import "./chunk-RAQ76CZO.js";
10
+ import "./chunk-W6LGNQSJ.js";
11
11
  import "./chunk-JSBRDJBE.js";
12
12
  export {
13
13
  computeDriftScore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibgrate/cli",
3
- "version": "2026.610.1",
3
+ "version": "2026.610.2",
4
4
  "description": "CLI for measuring upgrade drift across Node, .NET, Python & Java projects",
5
5
  "type": "module",
6
6
  "bin": {