fallow 2.93.0 → 2.95.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.
@@ -37,47 +37,28 @@ Analyzes the project for unused files, exports, dependencies, types, members, an
37
37
 
38
38
  ### Flags
39
39
 
40
+ <!-- generated:flags:dead-code:start -->
40
41
  | Flag | Type | Default | Description |
41
- |------|------|---------|-------------|
42
- | `--format` | `human\|json\|sarif\|compact\|markdown\|codeclimate\|gitlab-codequality\|pr-comment-github\|pr-comment-gitlab\|review-github\|review-gitlab` | `human` | Output format |
43
- | `--quiet` | bool | `false` | Suppress progress bars and timing on stderr |
44
- | `-o, --output-file` | path | (none) | Write the report to a file instead of stdout, for any `--format` (no ANSI codes). Progress and a confirmation stay on stderr (suppressed by `--quiet`). Valid with dead-code/dupes/health/security/bare; composes with `--sarif-file`. |
45
- | `--legacy-envelope` | bool | `false` | Remove the top-level `kind` field from typed JSON roots for one migration cycle |
46
- | `--changed-since` | string | - | Only analyze files changed since a git ref (e.g., `main`, `HEAD~3`) |
47
- | `--max-file-size` | int (MB) | `5` | Skip source files larger than N megabytes at discovery instead of parsing them (`0` disables). Guards against the OOM a single multi-MB generated/vendored/bundled file causes on large repos. `.d.ts` files are always analyzed. Skipped files appear on stderr and in `--format json` under `workspace_diagnostics` (`kind: "skipped-large-file"`). Also settable via `FALLOW_MAX_FILE_SIZE`. Global flag. |
48
- | `--production` | bool | `false` | Exclude test/dev files, only start/build scripts (applies to every analysis) |
49
- | `--no-production` | bool | `false` | Force production mode off, overriding a project config's `production: true` (applies to every analysis; conflicts with `--production`) |
50
- | `--production-dead-code` | bool | `false` | Per-analysis production mode for dead-code. Bare combined runs and `fallow audit` only. |
51
- | `--production-health` | bool | `false` | Per-analysis production mode for health. Bare combined runs and `fallow audit` only. |
52
- | `--production-dupes` | bool | `false` | Per-analysis production mode for duplication. Bare combined runs and `fallow audit` only. |
53
- | `--baseline` | path | - | Compare against a saved baseline |
54
- | `--save-baseline` | path | - | Save current results as a baseline |
55
- | `--workspace` | string | - | Scope to one or more workspaces. Comma-separated values, globs (`apps/*`, `@scope/*`), and `!`-prefixed negation (`!apps/legacy`) supported. Matched against package name AND workspace path relative to repo root. |
56
- | `--changed-workspaces` | string (git ref) | - | Git-derived monorepo CI scoping: scope to workspaces containing any file changed since `REF` (e.g. `origin/main`). Auto-derives the workspace set from `git diff`. Mutually exclusive with `--workspace`. Missing ref is a hard error (exit 2), not silent full-scope fallback. |
57
- | `--include-dupes` | bool | `false` | Cross-reference with duplication findings |
58
- | `--dupes-mode` | enum | `config` | Override duplicate detection mode in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --mode`. |
59
- | `--dupes-threshold` | number | `config` | Override the duplication percentage failure threshold in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --threshold`. |
60
- | `--dupes-min-tokens` | number | `config` | Override the minimum token count for clone detection in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --min-tokens`. |
61
- | `--dupes-min-lines` | number | `config` | Override the minimum line count for clone detection in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --min-lines`. |
62
- | `--dupes-min-occurrences` | number | `config` | Override the minimum clone occurrences in combined mode (must be >= 2). Falls back to the config value when unset. Mirrors the standalone `dupes --min-occurrences`. |
63
- | `--dupes-skip-local` | bool | `config` | Only report cross-directory duplicates in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --skip-local`. |
64
- | `--dupes-cross-language` | bool | `config` | Enable TypeScript to JavaScript duplicate matching in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --cross-language`. |
65
- | `--dupes-ignore-imports` | bool | `config` | Exclude import declarations from duplicate detection in combined mode. Falls back to the config value when unset. Mirrors the standalone `dupes --ignore-imports`. |
66
- | `--file` | path (multiple) | - | Scope output to specific files. Only issues in the specified files are reported. Project-wide dependency issues are suppressed. Warns on non-existent paths. Useful for lint-staged |
67
- | `--include-entry-exports` | bool | `false` | Report unused exports in entry files (package.json `main`/`exports`, framework pages). Catches typos like `meatdata` vs `metadata`. Global flag, also accepted on combined mode (`fallow --include-entry-exports`) and `fallow audit`. Also configurable as `includeEntryExports: true` in fallow config |
68
- | `--trace` | `FILE:EXPORT` | - | Trace export usage chain |
69
- | `--trace-file` | path | - | Show all edges for a file |
70
- | `--trace-dependency` | string | - | Trace where a dependency is used |
71
-
42
+ |---|---|---|---|
43
+ | `--include-dupes` | `bool` | `false` | Cross-reference with duplication findings |
44
+ | `--trace` | `string` | - | Trace export usage chain |
45
+ | `--trace-file` | `string` | - | Show all edges for a file |
46
+ | `--trace-dependency` | `string` | - | Trace where a dependency is used |
47
+ | `--top` | `string` | - | Show only the top N items per category |
48
+ | `--file` | `string` | - | Scope output to specific files. Only issues in the specified files are reported. Project-wide dependency issues are suppressed. Warns on non-existent paths. Useful for lint-staged |
49
+
50
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--output-file`](#global-flags), [`--legacy-envelope`](#global-flags), [`--changed-since`](#global-flags), [`--max-file-size`](#global-flags), [`--production`](#global-flags), [`--no-production`](#global-flags), [`--production-dead-code`](#global-flags), [`--baseline`](#global-flags), [`--save-baseline`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags), [`--include-entry-exports`](#global-flags).
51
+ <!-- generated:flags:dead-code:end -->
72
52
  ### Issue Type Filters
73
53
 
54
+ <!-- generated:flags:dead-code-filters:start -->
74
55
  | Flag | Issue Type |
75
- |------|------------|
56
+ |---|---|
76
57
  | `--unused-files` | Unused files |
77
58
  | `--unused-exports` | Unused exports |
59
+ | `--unused-deps` | Unused dependencies, devDependencies, optionalDependencies, type-only production deps, and test-only production deps |
78
60
  | `--unused-types` | Unused types |
79
61
  | `--private-type-leaks` | Opt-in API hygiene check (default `off`) for exported signatures that reference same-file private types. Storybook `*.stories.*` story files and framework routing convention files (Next.js App + Pages Router, Gatsby, Remix v2, TanStack Router, Expo Router) are skipped to avoid noise. Enable via this flag or `private-type-leaks: "warn"` / `"error"` in [`rules`](#rules-configuration). |
80
- | `--unused-deps` | Unused dependencies, devDependencies, optionalDependencies, type-only production deps, and test-only production deps |
81
62
  | `--unused-enum-members` | Unused enum members |
82
63
  | `--unused-class-members` | Unused class members |
83
64
  | `--unresolved-imports` | Unresolved imports |
@@ -93,7 +74,7 @@ Analyzes the project for unused files, exports, dependencies, types, members, an
93
74
  | `--unresolved-catalog-references` | Package references to missing pnpm catalog entries |
94
75
  | `--unused-dependency-overrides` | Unused pnpm dependency overrides |
95
76
  | `--misconfigured-dependency-overrides` | Malformed pnpm dependency overrides |
96
-
77
+ <!-- generated:flags:dead-code-filters:end -->
97
78
  ### Examples
98
79
 
99
80
  ```bash
@@ -155,28 +136,22 @@ By default, `fallow dupes` skips generated framework output matching `**/.next/*
155
136
 
156
137
  ### Flags
157
138
 
139
+ <!-- generated:flags:dupes:start -->
158
140
  | Flag | Type | Default | Description |
159
- |------|------|---------|-------------|
160
- | `--format` | `human\|json\|sarif\|compact\|markdown\|codeclimate\|gitlab-codequality\|pr-comment-github\|pr-comment-gitlab\|review-github\|review-gitlab` | `human` | Output format |
161
- | `--quiet` | bool | `false` | Suppress progress bars |
162
- | `--top` | number | - | Show only the N most-duplicated clone groups (sorted by instance count desc, tiebreak: line count desc, then path/line). Summary stats reflect the full project. |
163
- | `--mode` | `strict\|mild\|weak\|semantic` | `mild` | Detection mode |
164
- | `--min-tokens` | number | `50` | Minimum token count for a clone |
165
- | `--min-lines` | number | `5` | Minimum line count for a clone |
166
- | `--min-occurrences` | number | `2` | Minimum number of occurrences before a clone group is reported (must be ≥ 2). Raise to skip pair-only clones and focus on widespread copy-paste worth refactoring. `fallow init` writes `minOccurrences: 3` into new projects. |
167
- | `--threshold` | number | `0` | Fail if duplication exceeds this percentage |
168
- | `--skip-local` | bool | `false` | Only report cross-directory duplicates |
169
- | `--cross-language` | bool | `false` | Strip type annotations for TS↔JS matching |
170
- | `--ignore-imports` | bool | `false` | Exclude import declarations from clone detection |
171
- | `--explain-skipped` | bool | `false` | Human/markdown only: show per-pattern counts for files skipped by default duplicates ignores |
172
- | `--trace` | `FILE:LINE` \| `dup:<fp>` | - | Deep-dive clones. `FILE:LINE` traces all clones at a location; `dup:<id>` traces a clone group by the stable fingerprint shown in the listing and on `clone_groups[].fingerprint` in JSON. Fingerprints are usually `dup:<8hex>` and widen only on rare report collisions. Trace output adds an extract-function suggestion, estimated savings, and a best-effort proposed name per group |
173
- | `--changed-since` | string | - | Only report duplication in files changed since a git ref |
174
- | `--baseline` | path | - | Compare against baseline |
175
- | `--save-baseline` | path | - | Save results as baseline |
176
- | `--workspace` | string | - | Scope to one or more workspaces. Comma-separated values, globs (`apps/*`, `@scope/*`), and `!`-prefixed negation (`!apps/legacy`) supported. Matched against package name AND workspace path relative to repo root. |
177
- | `--changed-workspaces` | string (git ref) | - | Git-derived monorepo CI scoping: scope to workspaces containing any file changed since `REF`. Mutually exclusive with `--workspace`. Missing ref is a hard error. |
178
- | `--group-by` | `owner\|directory\|package\|section` | - | Partition the report into per-group sections. Each clone group is attributed to its **largest owner** (most instances; alphabetical tiebreak): a group split 2 src / 1 lib appears under `src`. JSON adds `grouped_by` plus a `groups` array; each bucket carries dedup-aware `stats`, `clone_groups` (every group tagged with `primary_owner` and per-instance `owner`), and `clone_families`. SARIF results carry `properties.group`, CodeClimate issues a top-level `group` field. Compact and markdown fall back to ungrouped with a stderr note. |
179
-
141
+ |---|---|---|---|
142
+ | `--mode` | `strict\|mild\|weak\|semantic` | - | Detection mode |
143
+ | `--min-tokens` | `string` | - | Minimum token count for a clone |
144
+ | `--min-lines` | `string` | - | Minimum line count for a clone |
145
+ | `--min-occurrences` | `string` | - | Minimum number of occurrences before a clone group is reported (must be ≥ 2). Raise to skip pair-only clones and focus on widespread copy-paste worth refactoring. `fallow init` writes `minOccurrences: 3` into new projects. |
146
+ | `--threshold` | `string` | - | Fail if duplication exceeds this percentage |
147
+ | `--skip-local` | `bool` | `false` | Only report cross-directory duplicates |
148
+ | `--cross-language` | `bool` | `false` | Strip type annotations for TS↔JS matching |
149
+ | `--ignore-imports` | `bool` | `false` | Exclude import declarations from clone detection |
150
+ | `--top` | `string` | - | Show only the N most-duplicated clone groups (sorted by instance count desc, tiebreak: line count desc, then path/line). Summary stats reflect the full project. |
151
+ | `--trace` | `string` | - | Deep-dive clones. `FILE:LINE` traces all clones at a location; `dup:<id>` traces a clone group by the stable fingerprint shown in the listing and on `clone_groups[].fingerprint` in JSON. Fingerprints are usually `dup:<8hex>` and widen only on rare report collisions. Trace output adds an extract-function suggestion, estimated savings, and a best-effort proposed name per group |
152
+
153
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--changed-since`](#global-flags), [`--baseline`](#global-flags), [`--save-baseline`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags), [`--group-by`](#global-flags), [`--explain-skipped`](#global-flags).
154
+ <!-- generated:flags:dupes:end -->
180
155
  ### Detection Modes
181
156
 
182
157
  | Mode | Behavior |
@@ -220,15 +195,15 @@ Auto-removes unused exports, dependencies, enum members, and pnpm catalog entrie
220
195
 
221
196
  ### Flags
222
197
 
198
+ <!-- generated:flags:fix:start -->
223
199
  | Flag | Type | Default | Description |
224
- |------|------|---------|-------------|
225
- | `--dry-run` | bool | `false` | Show what would be removed without modifying files. For `add-to-config` actions, prints a unified-diff preview of the proposed config write; JSON mode includes the diff under a `proposed_diff` field on the fix entry. |
226
- | `--yes` | bool | `false` | Skip confirmation prompt (**required** in non-TTY) |
227
- | `--force` | bool | `false` | Alias for `--yes` |
228
- | `--no-create-config` | bool | `false` | Refuse to create a new `.fallowrc.json` when none exists. The duplicate-export config-add path is skipped with `skip_reason: "no_create_config"`; source-file edits proceed normally. Use in pre-commit hooks, CI bots, and `fallow watch` where silently materialising a new top-level file would surprise the user. |
229
- | `--format` | `human\|json` | `human` | Output format |
230
- | `--quiet` | bool | `false` | Suppress progress bars |
200
+ |---|---|---|---|
201
+ | `--dry-run` | `bool` | `false` | Show what would be removed without modifying files. For `add-to-config` actions, prints a unified-diff preview of the proposed config write; JSON mode includes the diff under a `proposed_diff` field on the fix entry. |
202
+ | `--yes` | `bool` | `false` | Skip confirmation prompt (**required** in non-TTY) |
203
+ | `--no-create-config` | `bool` | `false` | Refuse to create a new `.fallowrc.json` when none exists. The duplicate-export config-add path is skipped with `skip_reason: "no_create_config"`; source-file edits proceed normally. Use in pre-commit hooks, CI bots, and `fallow watch` where silently materialising a new top-level file would surprise the user. |
231
204
 
205
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags).
206
+ <!-- generated:flags:fix:end -->
232
207
  ### What gets fixed
233
208
 
234
209
  - Unused exports (removes the `export` keyword; whole-enum block when every member is unused)
@@ -278,16 +253,17 @@ Inspect discovered files, entry points, detected frameworks, and architecture bo
278
253
 
279
254
  ### Flags
280
255
 
281
- | Flag | Type | Description |
282
- |------|------|-------------|
283
- | `--files` | bool | List all discovered files |
284
- | `--entry-points` | bool | List detected entry points |
285
- | `--plugins` | bool | List active framework plugins |
286
- | `--boundaries` | bool | Show architecture boundary zones, rules, per-zone file counts, and `logical_groups[]` for `autoDiscover` parents |
287
- | `--workspaces` | bool | Show discovered monorepo workspaces plus any workspace-discovery diagnostics (malformed `package.json`, unreachable glob matches, missing tsconfig references). Available as the `fallow workspaces` alias too. |
288
- | `--format` | `human\|json` | Output format |
289
- | `--quiet` | bool | Suppress progress bars |
290
-
256
+ <!-- generated:flags:list:start -->
257
+ | Flag | Type | Default | Description |
258
+ |---|---|---|---|
259
+ | `--entry-points` | `bool` | `false` | List detected entry points |
260
+ | `--files` | `bool` | `false` | List all discovered files |
261
+ | `--plugins` | `bool` | `false` | List active framework plugins |
262
+ | `--boundaries` | `bool` | `false` | Show architecture boundary zones, rules, per-zone file counts, and `logical_groups[]` for `autoDiscover` parents |
263
+ | `--workspaces` | `bool` | `false` | Show discovered monorepo workspaces plus any workspace-discovery diagnostics (malformed `package.json`, unreachable glob matches, missing tsconfig references). Available as the `fallow workspaces` alias too. |
264
+
265
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags).
266
+ <!-- generated:flags:list:end -->
291
267
  ### Examples
292
268
 
293
269
  ```bash
@@ -311,13 +287,17 @@ Creates a config file in the project root.
311
287
 
312
288
  ### Flags
313
289
 
314
- | Flag | Type | Description |
315
- |------|------|-------------|
316
- | `--toml` | bool | Create `fallow.toml` instead of `.fallowrc.json` |
317
- | `--agents` | bool | Scaffold a starter `AGENTS.md` guide for coding agents. Prefills Install (from the `packageManager` field, or pnpm via `pnpm-workspace.yaml`), Test (only when exactly one of Vitest / Jest / Playwright is present), Typecheck (`tsc --noEmit` when `tsconfig.json` exists), and monorepo module-boundary lines; everything ambiguous stays blank (no lockfile sniffing). Prefilled command lines carry an HTML provenance comment. Refuses to overwrite an existing `AGENTS.md` |
318
- | `--hooks` | bool | Scaffold a pre-commit git hook that runs `fallow audit --base <ref> --quiet`. Alias for `fallow hooks install --target git` |
319
- | `--branch` | string | Fallback base branch for the pre-commit hook when no upstream is set (default: `main`). Only used with `--hooks` |
320
-
290
+ <!-- generated:flags:init:start -->
291
+ | Flag | Type | Default | Description |
292
+ |---|---|---|---|
293
+ | `--toml` | `bool` | `false` | Create `fallow.toml` instead of `.fallowrc.json` |
294
+ | `--agents` | `bool` | `false` | Scaffold a starter `AGENTS.md` guide for coding agents. Prefills Install (from the `packageManager` field, or pnpm via `pnpm-workspace.yaml`), Test (only when exactly one of Vitest / Jest / Playwright is present), Typecheck (`tsc --noEmit` when `tsconfig.json` exists), and monorepo module-boundary lines; everything ambiguous stays blank (no lockfile sniffing). Prefilled command lines carry an HTML provenance comment. Refuses to overwrite an existing `AGENTS.md` |
295
+ | `--hooks` | `bool` | `false` | Scaffold a pre-commit git hook that runs `fallow audit --base <ref> --quiet --gate-marker pre-commit`. Alias for `fallow hooks install --target git` |
296
+ | `--branch` | `string` | - | Fallback base branch for the pre-commit hook when no upstream is set (default: `main`). Only used with `--hooks` |
297
+ | `--decline` | `bool` | `false` | Record that this project deliberately stays unconfigured: persists a decline so the first-contact setup hint and the `setup` next-step stop appearing here. Writes no config file; idempotent |
298
+
299
+ Common global flags for this command: [`--root`](#global-flags), [`--config`](#global-flags).
300
+ <!-- generated:flags:init:end -->
321
301
  ### Examples
322
302
 
323
303
  ```bash
@@ -328,6 +308,18 @@ fallow hooks install --target git
328
308
  fallow hooks install --target git --branch develop # fallback base branch when no upstream is set
329
309
  ```
330
310
 
311
+ ## `hooks`: Managed Hook Status And Installation
312
+
313
+ ```bash
314
+ fallow hooks status --format json
315
+ fallow hooks install --target git
316
+ fallow hooks install --target agent
317
+ fallow hooks uninstall --target git
318
+ fallow hooks uninstall --target agent
319
+ ```
320
+
321
+ `hooks status` is read-only and reports `git`, `claude`, and `codex` surfaces. Each surface includes `installed`, `managed_block_present`, `user_edited`, and `path`; generated agent scripts also include `script_version` and `min_version_floor`. Use it before mutating setup so agents can distinguish fallow-managed artifacts from user-owned hooks or partial managed blocks.
322
+
331
323
  ---
332
324
 
333
325
  ## `migrate`: Config Migration
@@ -336,13 +328,16 @@ Migrates configuration from knip and/or jscpd to fallow. Auto-detects config fil
336
328
 
337
329
  ### Flags
338
330
 
339
- | Flag | Type | Description |
340
- |------|------|-------------|
341
- | `--toml` | bool | Output as `fallow.toml` (mutually exclusive with `--jsonc`) |
342
- | `--jsonc` | bool | Write to `.fallowrc.jsonc` instead of `.fallowrc.json`. Same JSONC content either way; the `.jsonc` extension lets editors auto-detect JSON-with-comments syntax highlighting |
343
- | `--dry-run` | bool | Preview without writing |
344
- | `--from` | path | Specify source config file path |
345
-
331
+ <!-- generated:flags:migrate:start -->
332
+ | Flag | Type | Default | Description |
333
+ |---|---|---|---|
334
+ | `--toml` | `bool` | `false` | Output as `fallow.toml` (mutually exclusive with `--jsonc`) |
335
+ | `--jsonc` | `bool` | `false` | Write to `.fallowrc.jsonc` instead of `.fallowrc.json`. Same JSONC content either way; the `.jsonc` extension lets editors auto-detect JSON-with-comments syntax highlighting |
336
+ | `--dry-run` | `bool` | `false` | Preview without writing |
337
+ | `--from` | `string` | - | Specify source config file path |
338
+
339
+ Common global flags for this command: [`--root`](#global-flags), [`--config`](#global-flags).
340
+ <!-- generated:flags:migrate:end -->
346
341
  Without `--jsonc` or `--toml`, fallow auto-mirrors the source extension: a `knip.jsonc` migration writes `.fallowrc.jsonc`, a `knip.json` migration writes `.fallowrc.json`.
347
342
 
348
343
  ### Detected Source Configs
@@ -372,45 +367,40 @@ Angular templates contribute synthetic `<template>` complexity findings whenever
372
367
 
373
368
  ### Flags
374
369
 
370
+ <!-- generated:flags:health:start -->
375
371
  | Flag | Type | Default | Description |
376
- |------|------|---------|-------------|
377
- | `--format` | `human\|json\|sarif\|compact\|markdown\|codeclimate\|gitlab-codequality\|pr-comment-github\|pr-comment-gitlab\|review-github\|review-gitlab\|badge` | `human` | Output format |
378
- | `--quiet` | bool | `false` | Suppress progress bars |
379
- | `--max-cyclomatic` | number | `20` | Fail if any function exceeds this cyclomatic complexity |
380
- | `--max-cognitive` | number | `15` | Fail if any function exceeds this cognitive complexity |
381
- | `--max-crap` | number | `30.0` | Fail if any function has CRAP score >= threshold. CRAP combines complexity with coverage (`CC^2 * (1 - cov/100)^3 + CC`). Pair with `--coverage` for accurate per-function CRAP; without Istanbul data fallow estimates coverage from the module graph. |
382
- | `--top` | number | - | Only show the top N most complex functions (and file scores/hotspots/targets) |
383
- | `--sort` | `cyclomatic\|cognitive\|lines\|severity` | `cyclomatic` | Sort order for complexity findings |
384
- | `--complexity` | bool | `false` | Show only function complexity findings. When no section flags are set, all sections are shown by default. |
385
- | `--complexity-breakdown` | bool | `false` | Add a per-decision-point `contributions[]` array to each complexity finding in `--format json`. Each entry names the construct (`if`, `else-if`, `ternary`, boolean operator, loop, `case`, `catch`, `optional-chain`, ...) and carries its source line, the metric it adds to (`cyclomatic` or `cognitive`), its weight, and the nesting depth, so a consumer can explain WHY a function scored high. Off by default (no change to existing JSON/SARIF/markdown). Used by the VS Code inline editor breakdown and the MCP `check_health` `complexity_breakdown` param. |
386
- | `--file-scores` | bool | `false` | Show only per-file health scores (maintainability index, LOC, fan-in, fan-out, dead code ratio, complexity density, CRAP risk). Runs the full analysis pipeline. Sorted by risk-aware triage concern: lower maintainability index and higher CRAP risk first. When no section flags are set, all sections are shown by default. |
387
- | `--hotspots` | bool | `false` | Show only hotspots: files that are both complex and frequently changing. Combines git churn history with complexity data. Requires a git repository. When no section flags are set, all sections are shown by default. |
388
- | `--targets` | bool | `false` | Show only refactoring targets: ranked recommendations based on complexity, coupling, churn, and dead code signals. Categories: churn+complexity, circular dep, high impact, dead code, complexity, coupling. When no section flags are set, all sections are shown by default. Each target's JSON can include `direct_callers[]` (direct importers with the symbols they import) and `clone_siblings[]` (duplicate-code siblings with stable `dup:<8hex>` fingerprints for `fallow dupes --trace`); both omitted when empty. Human output adds `importers:` / `clones:` lines only when that evidence is present. |
372
+ |---|---|---|---|
373
+ | `--max-cyclomatic` | `string` | - | Fail if any function exceeds this cyclomatic complexity |
374
+ | `--max-cognitive` | `string` | - | Fail if any function exceeds this cognitive complexity |
375
+ | `--max-crap` | `string` | - | Fail if any function has CRAP score >= threshold. CRAP combines complexity with coverage (`CC^2 * (1 - cov/100)^3 + CC`). Pair with `--coverage` for accurate per-function CRAP; without Istanbul data fallow estimates coverage from the module graph. |
376
+ | `--top` | `string` | - | Only show the top N most complex functions (and file scores/hotspots/targets) |
377
+ | `--sort` | `severity\|cyclomatic\|cognitive\|lines` | `cyclomatic` | Sort order for complexity findings |
378
+ | `--complexity` | `bool` | `false` | Show only function complexity findings. When no section flags are set, all sections are shown by default. |
379
+ | `--complexity-breakdown` | `bool` | `false` | Add a per-decision-point `contributions[]` array to each complexity finding in `--format json`. Each entry names the construct (`if`, `else-if`, `ternary`, boolean operator, loop, `case`, `catch`, `optional-chain`, ...) and carries its source line, the metric it adds to (`cyclomatic` or `cognitive`), its weight, and the nesting depth, so a consumer can explain WHY a function scored high. Off by default (no change to existing JSON/SARIF/markdown). Used by the VS Code inline editor breakdown and the MCP `check_health` `complexity_breakdown` param. |
380
+ | `--file-scores` | `bool` | `false` | Show only per-file health scores (maintainability index, LOC, fan-in, fan-out, dead code ratio, complexity density, CRAP risk). Runs the full analysis pipeline. Sorted by risk-aware triage concern: lower maintainability index and higher CRAP risk first. When no section flags are set, all sections are shown by default. |
381
+ | `--coverage-gaps` | `bool` | `false` | Show runtime files and exports that no test dependency path reaches. Opt-in (default off). Configure severity via the `coverage-gaps` rule (`error`/`warn`/`off`). |
382
+ | `--hotspots` | `bool` | `false` | Show only hotspots: files that are both complex and frequently changing. Combines git churn history with complexity data. Requires a git repository. When no section flags are set, all sections are shown by default. |
383
+ | `--ownership` | `bool` | `false` | Attach ownership signals to hotspot entries: bus factor (Avelino truck factor), contributor count, top contributor with stale-days, recent contributors (top-3), `suggested_reviewers`, declared CODEOWNERS owner, `ownership_state`, ownership drift, unowned-hotspot detection. Human output gains a project-level summary line. JSON adds `low-bus-factor`, `unowned-hotspot`, `ownership-drift` action types. Test files get a `[test]` tag. Implies `--hotspots`. Requires git. |
384
+ | `--ownership-emails` | `raw\|handle\|anonymized\|hash` | - | Privacy mode for author emails. `handle` shows the local-part only (default, with GitHub noreply unwrap and deterministic same-handle disambiguation). `anonymized` emits stable `xxh3:` pseudonyms; `hash` remains accepted as the legacy spelling. `raw` shows full addresses. Use `anonymized` in regulated environments. Implies `--ownership`. Configure default via `health.ownership.emailMode`. |
385
+ | `--targets` | `bool` | `false` | Show only refactoring targets: ranked recommendations based on complexity, coupling, churn, and dead code signals. Categories: churn+complexity, circular dep, high impact, dead code, complexity, coupling. When no section flags are set, all sections are shown by default. Each target's JSON can include `direct_callers[]` (direct importers with the symbols they import) and `clone_siblings[]` (duplicate-code siblings with stable `dup:<8hex>` fingerprints for `fallow dupes --trace`); both omitted when empty. Human output adds `importers:` / `clones:` lines only when that evidence is present. |
389
386
  | `--effort` | `low\|medium\|high` | - | Filter refactoring targets by effort level. Implies `--targets`. |
390
- | `--score` | bool | `false` | Show only the project health score (0-100) with letter grade (A/B/C/D/F). The score is included by default when no section flags are set. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown. As of v2.55.0, plain `--score` skips the churn-backed hotspot penalty so it does not run a `git log` shell-out per invocation; pass `--hotspots` (or `--targets` with `--score`) to include the hotspot penalty. Snapshot (`--save-snapshot`) and trend (`--trend`) flows still trigger hotspot vital signs so saved data stays complete. |
391
- | `--min-score` | number | - | Fail (exit 1) only when the health score is below this threshold. Implies `--score`. Authoritative CI quality gate: when set, complexity findings are demoted to informational and the exit code is driven solely by the score, so `--min-score 0` always exits 0. Composes with `--min-severity`. |
387
+ | `--score` | `bool` | `false` | Show only the project health score (0-100) with letter grade (A/B/C/D/F). The score is included by default when no section flags are set. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown. As of v2.55.0, plain `--score` skips the churn-backed hotspot penalty so it does not run a `git log` shell-out per invocation; pass `--hotspots` (or `--targets` with `--score`) to include the hotspot penalty. Snapshot (`--save-snapshot`) and trend (`--trend`) flows still trigger hotspot vital signs so saved data stays complete. |
388
+ | `--min-score` | `string` | - | Fail (exit 1) only when the health score is below this threshold. Implies `--score`. Authoritative CI quality gate: when set, complexity findings are demoted to informational and the exit code is driven solely by the score, so `--min-score 0` always exits 0. Composes with `--min-severity`. |
392
389
  | `--min-severity` | `moderate\|high\|critical` | - | Only exit with an error for findings at or above this severity. Composes with `--min-score` (the run fails if either gate trips). |
393
- | `--report-only` | bool | `false` | Print the score and findings but never fail CI (always exit 0). Advisory mode. Mutually exclusive with `--min-score` and `--min-severity`. |
394
- | `--since` | string | `6m` | Git history window for hotspot analysis. Accepts durations (`6m`, `90d`, `1y`, `2w`) or ISO dates (`2025-06-01`). Ignored when `--churn-file` is set. |
395
- | `--min-commits` | number | `3` | Minimum number of commits for a file to be included in hotspot ranking. |
396
- | `--churn-file` | string | (none) | Import change history from a `fallow-churn/v1` JSON file (`{schema, events:[{path, timestamp, author, added, deleted}]}`, one entry per changed file per commit) instead of `git log`, so `--hotspots`/`--ownership`/`--targets` work on non-git VCS (Yandex Arc, Mercurial, Perforce). Resolved relative to `--root`; wins over git. Authoritative for the window, so `--since` then only labels output. Malformed file exits 2; `audit`/`impact`/`--changed-since` still require git. |
397
- | `--ownership` | bool | `false` | Attach ownership signals to hotspot entries: bus factor (Avelino truck factor), contributor count, top contributor with stale-days, recent contributors (top-3), `suggested_reviewers`, declared CODEOWNERS owner, `ownership_state`, ownership drift, unowned-hotspot detection. Human output gains a project-level summary line. JSON adds `low-bus-factor`, `unowned-hotspot`, `ownership-drift` action types. Test files get a `[test]` tag. Implies `--hotspots`. Requires git. |
398
- | `--ownership-emails` | `raw\|handle\|anonymized\|hash` | `handle` | Privacy mode for author emails. `handle` shows the local-part only (default, with GitHub noreply unwrap and deterministic same-handle disambiguation). `anonymized` emits stable `xxh3:` pseudonyms; `hash` remains accepted as the legacy spelling. `raw` shows full addresses. Use `anonymized` in regulated environments. Implies `--ownership`. Configure default via `health.ownership.emailMode`. |
399
- | `--changed-since` | string | - | Only analyze files changed since a git ref |
400
- | `--workspace` | string | - | Scope to one or more workspaces. Comma-separated values, globs (`apps/*`, `@scope/*`), and `!`-prefixed negation (`!apps/legacy`) supported. Matched against package name AND workspace path relative to repo root. Vital signs, health score, hotspots, file scores, findings, and `summary.files_analyzed` are all recomputed against the scoped subset. |
401
- | `--group-by` | `owner\|directory\|package\|section` | - | Partition the report into per-group sections. JSON adds `grouped_by` plus a `groups` array; each group contains its own `vital_signs`, `health_score`, `findings`, `file_scores`, `hotspots`, `large_functions`, and `targets` recomputed against the group's files. The top-level metrics stay project-wide so consumers that ignore grouping still see the project headline. Human output adds a per-group score / files / hot / p90 summary block (sorted worst-first when `--score`). SARIF results carry `properties.group` and CodeClimate issues carry a top-level `group` field so GitHub Code Scanning / GitLab Code Quality can partition per team / package. Compact, markdown, and badge fall back to ungrouped output with a stderr note. |
402
- | `--baseline` | path | - | Compare against a saved baseline. When set, the JSON `actions` array on each finding omits `suppress-line` (the baseline already suppresses) and the report root carries an `actions_meta: { suppression_hints_omitted: true, reason: "baseline-active" }` breadcrumb. |
403
- | `--save-baseline` | path | - | Save current results as a baseline. Same `suppress-line` omission as `--baseline`. |
404
- | `--save-snapshot` | path (optional) | `.fallow/snapshots/<timestamp>.json` | Save vital signs snapshot for trend tracking. Forces file-scores + hotspot computation. |
405
- | `--trend` | bool | `false` | Compare current metrics against the most recent saved snapshot. Reads from `.fallow/snapshots/` and shows per-metric deltas with directional indicators (improving/declining/stable). Implies `--score`. |
406
- | `--coverage-gaps` | bool | `false` | Show runtime files and exports that no test dependency path reaches. Opt-in (default off). Configure severity via the `coverage-gaps` rule (`error`/`warn`/`off`). |
407
- | `--coverage` | path | none | Path to Istanbul-format coverage data (`coverage-final.json`) for accurate per-function CRAP scores. Uses `CC^2 * (1-cov/100)^3 + CC` instead of static binary model. Relative paths resolve against `--root`. |
408
- | `--coverage-root` | path | none | Absolute prefix to strip from file paths in coverage data before prepending the project root. For CI/Docker environments where coverage was generated with different absolute paths. |
409
- | `--runtime-coverage` | path | none | Merge runtime-coverage input into the health report. Accepts a V8 coverage directory (`NODE_V8_COVERAGE=...`), a single V8 coverage JSON file, or an Istanbul `coverage-final.json`. One local capture is free and does not require a license; continuous/cloud or multi-capture runtime monitoring requires an active license or trial (`fallow license activate --trial --email <addr>`). JSON output gains a `runtime_coverage` object with a top-level report verdict, per-finding `verdict` (`safe_to_delete` / `review_required` / `low_traffic` / `coverage_unavailable` / `active`), a per-finding suppression `id` (`fallow:prod:<hash>`, hashes the current line), an optional cross-surface `stable_id` join key (`fallow:fn:<hash>`, hashes file + name + start line; one value per function across findings / hot-paths / blast-radius / importance and across V8/Istanbul/oxc producers), an optional content-digest `source_hash` (line-move-immune, so baselines survive a pure line shift), an evidence block, and percentile-ranked hot paths. On protocol-0.3+ sidecars the `summary` also carries an optional `capture_quality` block (`window_seconds`, `instances_observed`, `lazy_parse_warning`, `untracked_ratio_percent`) that flags short-window captures where lazy-parsed scripts may not appear. |
410
- | `--min-invocations-hot` | number | `100` | Invocation threshold for hot-path classification. Takes effect only when `--runtime-coverage` is set. |
411
- | `--min-observation-volume` | number | `5000` | Minimum total trace volume before the sidecar may emit high-confidence `safe_to_delete` / `review_required` verdicts. Below this, confidence is capped at `medium`. |
412
- | `--low-traffic-threshold` | number | `0.001` | Fraction of total trace count below which an invoked function is classified `low_traffic` rather than `active`. Expressed as a decimal (0.001 = 0.1%). |
413
-
390
+ | `--report-only` | `bool` | `false` | Print the score and findings but never fail CI (always exit 0). Advisory mode. Mutually exclusive with `--min-score` and `--min-severity`. |
391
+ | `--since` | `string` | - | Git history window for hotspot analysis. Accepts durations (`6m`, `90d`, `1y`, `2w`) or ISO dates (`2025-06-01`). Ignored when `--churn-file` is set. |
392
+ | `--min-commits` | `string` | - | Minimum number of commits for a file to be included in hotspot ranking. |
393
+ | `--save-snapshot` | `string` | - | Save vital signs snapshot for trend tracking. Forces file-scores + hotspot computation. |
394
+ | `--trend` | `bool` | `false` | Compare current metrics against the most recent saved snapshot. Reads from `.fallow/snapshots/` and shows per-metric deltas with directional indicators (improving/declining/stable). Implies `--score`. |
395
+ | `--coverage` | `string` | - | Path to Istanbul-format coverage data (`coverage-final.json`) for accurate per-function CRAP scores. Uses `CC^2 * (1-cov/100)^3 + CC` instead of static binary model. Relative paths resolve against `--root`. Falls back to `FALLOW_COVERAGE`, then `health.coverage`, then auto-detection. |
396
+ | `--coverage-root` | `string` | - | Absolute prefix to strip from file paths in coverage data before prepending the project root. For CI/Docker environments where coverage was generated with different absolute paths. Falls back to `FALLOW_COVERAGE_ROOT`, then `health.coverageRoot`. |
397
+ | `--runtime-coverage` | `string` | - | Merge runtime-coverage input into the health report. Accepts a V8 coverage directory (`NODE_V8_COVERAGE=...`), a single V8 coverage JSON file, or an Istanbul `coverage-final.json`. One local capture is free and does not require a license; continuous/cloud or multi-capture runtime monitoring requires an active license or trial (`fallow license activate --trial --email <addr>`). JSON output gains a `runtime_coverage` object with a top-level report verdict, per-finding `verdict` (`safe_to_delete` / `review_required` / `low_traffic` / `coverage_unavailable` / `active`), a per-finding suppression `id` (`fallow:prod:<hash>`, hashes the current line), an optional cross-surface `stable_id` join key (`fallow:fn:<hash>`, hashes file + name + start line; one value per function across findings / hot-paths / blast-radius / importance and across V8/Istanbul/oxc producers), an optional content-digest `source_hash` (line-move-immune, so baselines survive a pure line shift), an evidence block, and percentile-ranked hot paths. On protocol-0.3+ sidecars the `summary` also carries an optional `capture_quality` block (`window_seconds`, `instances_observed`, `lazy_parse_warning`, `untracked_ratio_percent`) that flags short-window captures where lazy-parsed scripts may not appear. |
398
+ | `--min-invocations-hot` | `string` | `100` | Invocation threshold for hot-path classification. Takes effect only when `--runtime-coverage` is set. |
399
+ | `--min-observation-volume` | `string` | - | Minimum total trace volume before the sidecar may emit high-confidence `safe_to_delete` / `review_required` verdicts. Below this, confidence is capped at `medium`. |
400
+ | `--low-traffic-threshold` | `string` | - | Fraction of total trace count below which an invoked function is classified `low_traffic` rather than `active`. Expressed as a decimal (0.001 = 0.1%). |
401
+
402
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--changed-since`](#global-flags), [`--churn-file`](#global-flags), [`--workspace`](#global-flags), [`--group-by`](#global-flags), [`--baseline`](#global-flags), [`--save-baseline`](#global-flags), [`--production`](#global-flags), [`--no-production`](#global-flags), [`--explain`](#global-flags).
403
+ <!-- generated:flags:health:end -->
414
404
  ### Exit Codes
415
405
 
416
406
  The gate flag in play determines what drives the exit code. Plain `fallow health` (no gate flag) stays advisory but still fails on any finding (back-compat).
@@ -502,7 +492,7 @@ fallow health --format json --quiet --trend
502
492
  {
503
493
  "kind": "health",
504
494
  "schema_version": 7,
505
- "version": "2.93.0",
495
+ "version": "2.95.0",
506
496
  "elapsed_ms": 32,
507
497
  "summary": {
508
498
  "files_analyzed": 482,
@@ -526,6 +516,8 @@ fallow health --format json --quiet --trend
526
516
  }
527
517
  ```
528
518
 
519
+ `health.thresholdOverrides[]` config entries can raise local cyclomatic, cognitive, or CRAP ceilings for matching files and optional exact function names. When an override affects output, health JSON includes top-level `threshold_overrides[]` state entries (`active`, `stale`, or `no_match`). Complexity findings evaluated with local ceilings include `effective_thresholds` and `threshold_source: "override"` so agents can see which thresholds drove the finding and avoid treating configured exceptions as hidden suppressions.
520
+
529
521
  When the unit size very-high-risk percentage is >= 3%, the JSON output includes a `large_functions` array listing functions exceeding 60 lines of code:
530
522
 
531
523
  ```json
@@ -807,31 +799,25 @@ Audits changed files for dead code, complexity, and duplication. Returns a verdi
807
799
 
808
800
  ### Flags
809
801
 
802
+ <!-- generated:flags:audit:start -->
810
803
  | Flag | Type | Default | Description |
811
- |------|------|---------|-------------|
812
- | `--base` | string | merge-base | Git ref to compare against (alias for `--changed-since`). When unset, resolves to the `git merge-base` against the upstream or remote default; `FALLOW_AUDIT_BASE` pins it without a flag. |
813
- | `--gate` | `new-only\|all` | `new-only` | Which findings affect the verdict. `new-only` gates only introduced findings; `all` gates every finding in changed files and skips the extra base-snapshot attribution pass. |
814
- | `--production` | bool | false | Exclude test/story/dev files (applies to dead-code, health, and dupes) |
815
- | `--no-production` | bool | false | Force production mode off, overriding a project config's `production: true` (conflicts with `--production`) |
816
- | `--production-dead-code` | bool | false | Per-analysis production mode for the dead-code sub-analysis only |
817
- | `--production-health` | bool | false | Per-analysis production mode for the health sub-analysis only |
818
- | `--production-dupes` | bool | false | Per-analysis production mode for the duplication sub-analysis only |
819
- | `-w, --workspace` | string | - | Scope to one or more workspaces. Comma-separated, globs, `!` negation. |
820
- | `--explain` | bool | false | JSON: include metric definitions in `_meta`. Human: print a `Description:` line under each section header. |
821
- | `--ci` | bool | false | Equivalent to `--format sarif --fail-on-issues --quiet` |
822
- | `--fail-on-issues` | bool | false | Exit with code 1 if issues are found |
823
- | `--sarif-file` | path | - | Write SARIF output to a file alongside primary format |
824
- | `--dead-code-baseline` | path | - | Baseline file (produced by `fallow dead-code --save-baseline`). Pre-existing dead-code issues are excluded from the verdict. |
825
- | `--health-baseline` | path | - | Baseline file (produced by `fallow health --save-baseline`). Pre-existing complexity findings are excluded from the verdict. |
826
- | `--dupes-baseline` | path | - | Baseline file (produced by `fallow dupes --save-baseline`). Pre-existing clone groups are excluded from the verdict. |
827
- | `--max-crap` | number | `30.0` | Forwarded to the health sub-analysis. Functions meeting or exceeding this CRAP score cause audit to fail. Same formula as `health --max-crap`. Pair with coverage data for accurate per-function CRAP. |
828
- | `--coverage` | path | none | Path to Istanbul-format coverage data (`coverage-final.json`) for accurate per-function CRAP scores in the health sub-analysis. Same format and semantics as `health --coverage`. Also configurable via `FALLOW_COVERAGE`. Relative paths resolve against `--root`. |
829
- | `--coverage-root` | path | none | Absolute prefix to strip from file paths in coverage data before prepending the project root. Use when coverage was generated under a different checkout root in CI / Docker (e.g., `/home/runner/work/myapp` on GitHub Actions). |
830
- | `--fail-on-regression` | bool | false | Fail if issues increased beyond tolerance vs regression baseline |
831
- | `--tolerance` | string | `0` | Allowed increase before regression fails (`N` or `N%`) |
832
- | `--regression-baseline` | path | `.fallow/regression-baseline.json` | Path to the regression baseline file |
833
- | `--save-regression-baseline` | path | - | Save current issue counts as a regression baseline |
834
-
804
+ |---|---|---|---|
805
+ | `--production-dead-code` | `bool` | `false` | Per-analysis production mode for the dead-code sub-analysis only |
806
+ | `--production-health` | `bool` | `false` | Per-analysis production mode for the health sub-analysis only |
807
+ | `--production-dupes` | `bool` | `false` | Per-analysis production mode for the duplication sub-analysis only |
808
+ | `--dead-code-baseline` | `string` | - | Baseline file (produced by `fallow dead-code --save-baseline`). Pre-existing dead-code issues are excluded from the verdict. |
809
+ | `--health-baseline` | `string` | - | Baseline file (produced by `fallow health --save-baseline`). Pre-existing complexity findings are excluded from the verdict. |
810
+ | `--dupes-baseline` | `string` | - | Baseline file (produced by `fallow dupes --save-baseline`). Pre-existing clone groups are excluded from the verdict. |
811
+ | `--max-crap` | `string` | - | Forwarded to the health sub-analysis. Functions meeting or exceeding this CRAP score cause audit to fail. Same formula as `health --max-crap`. Pair with coverage data for accurate per-function CRAP. |
812
+ | `--coverage` | `string` | - | Path to Istanbul-format coverage data (`coverage-final.json`) for accurate per-function CRAP scores in the health sub-analysis. Same format and semantics as `health --coverage`. Also configurable via `FALLOW_COVERAGE`. Relative paths resolve against `--root`. |
813
+ | `--coverage-root` | `string` | - | Absolute prefix to strip from file paths in coverage data before prepending the project root. Also configurable via `FALLOW_COVERAGE_ROOT`. Use when coverage was generated under a different checkout root in CI / Docker (e.g., `/home/runner/work/myapp` on GitHub Actions). |
814
+ | `--gate` | `new-only\|all` | - | Which findings affect the verdict. `new-only` gates only introduced findings; `all` gates every finding in changed files and skips the extra base-snapshot attribution pass. |
815
+ | `--runtime-coverage` | `string` | - | Paid runtime-coverage sidecar input. Accepts a V8 directory, a single V8 JSON file, or an Istanbul coverage map JSON. Spawns the `fallow-cov` sidecar as part of the audit pipeline so the `hot-path-touched` verdict surfaces alongside dead-code and complexity findings without requiring a second `fallow health` invocation in CI. License-gated; the verdict is informational (no exit code change) until a future `--gate hot-path-touched` knob lands |
816
+ | `--min-invocations-hot` | `string` | `100` | Threshold for hot-path classification, forwarded to the sidecar when `--runtime-coverage` is set |
817
+ | `--gate-marker` | `string` | - | Internal marker identifying a gate run (e.g. `pre-commit`), set by the generated git hook so Fallow Impact can record a containment event when the gate blocks then clears. Hidden; never changes the verdict, exit code, or output |
818
+
819
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--changed-since`](#global-flags), [`--diff-file`](#global-flags), [`--diff-stdin`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags), [`--group-by`](#global-flags), [`--output-file`](#global-flags).
820
+ <!-- generated:flags:audit:end -->
835
821
  ### Verdicts
836
822
 
837
823
  | Verdict | Exit code | When |
@@ -893,7 +879,7 @@ fallow audit \
893
879
  {
894
880
  "kind": "audit",
895
881
  "schema_version": 7,
896
- "version": "2.93.0",
882
+ "version": "2.95.0",
897
883
  "command": "audit",
898
884
  "verdict": "fail",
899
885
  "changed_files_count": 12,
@@ -943,12 +929,13 @@ Detects feature flag patterns in the codebase. Identifies environment variable f
943
929
 
944
930
  ### Flags
945
931
 
932
+ <!-- generated:flags:flags:start -->
946
933
  | Flag | Type | Default | Description |
947
- |------|------|---------|-------------|
948
- | `--format` | `human\|json\|sarif\|compact\|markdown\|codeclimate\|gitlab-codequality\|pr-comment-github\|pr-comment-gitlab\|review-github\|review-gitlab` | `human` | Output format |
949
- | `--quiet` | bool | `false` | Suppress progress bars |
950
- | `--top` | number | - | Show only the top N flags |
934
+ |---|---|---|---|
935
+ | `--top` | `string` | - | Show only the top N flags |
951
936
 
937
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--changed-since`](#global-flags), [`--workspace`](#global-flags).
938
+ <!-- generated:flags:flags:end -->
952
939
  ### Examples
953
940
 
954
941
  ```bash
@@ -967,7 +954,7 @@ fallow flags --format json --quiet --workspace my-package
967
954
  ```json
968
955
  {
969
956
  "schema_version": 7,
970
- "version": "2.93.0",
957
+ "version": "2.95.0",
971
958
  "elapsed_ms": 116,
972
959
  "feature_flags": [],
973
960
  "total_flags": 0
@@ -1036,23 +1023,17 @@ Build-config and test files are excluded from candidate generation. Security rul
1036
1023
 
1037
1024
  ### Flags
1038
1025
 
1026
+ <!-- generated:flags:security:start -->
1039
1027
  | Flag | Type | Default | Description |
1040
- |------|------|---------|-------------|
1041
- | `--format` | `human\|json\|sarif` | `human` | Output format |
1042
- | `--quiet` | bool | `false` | Suppress progress output |
1043
- | `--summary` | bool | `false` | Show a compact human summary |
1044
- | `--ci` | bool | `false` | Equivalent to `--format sarif --fail-on-issues --quiet` |
1045
- | `--fail-on-issues` | bool | `false` | Exit 1 when candidates are found |
1046
- | `--sarif-file` | path | none | Write SARIF in addition to the primary output |
1047
- | `--changed-since` | git ref | none | Scope to candidates whose client anchor or trace hops touch changed files |
1048
- | `--file` | path, repeatable | none | Scope output to candidates whose finding anchor or trace hop matches the selected file. The full graph is still analyzed |
1049
- | `--diff-file` | path | none | Scope candidates to added hunks on the client anchor or import trace. Secret-source hops use file-level retention because member-access spans are not yet stored. Use `-` for stdin |
1050
- | `--diff-stdin` | bool | `false` | Read the unified diff from stdin (equivalent to `--diff-file -`) for line-level scoping and the regression gate |
1051
- | `--surface` | bool | `false` | Include the agent-facing `attack_surface[]` inventory in JSON output |
1052
- | `--gate` | `new\|newly-reachable` | none | `new` fails (exit code **8**) only when the change introduces a NEW security-sink candidate in the changed lines. It requires a diff source (`--changed-since`, `--diff-file`, or `--diff-stdin`). `newly-reachable` fails when an existing candidate becomes reachable from entry points compared with `--changed-since <ref>`; diff-only inputs exit 2 because this mode analyzes the base tree. Human output says `REVIEW REQUIRED` (not `FAIL`); SARIF keeps every result at `level: note` with the verdict in `run.properties.fallowGate`; `--format json` carries an additive `gate` block (`mode` / `verdict` / `new_count`) |
1053
- | `--workspace` | string | none | Scope to selected workspace packages |
1054
- | `--changed-workspaces` | git ref | none | Scope to workspaces changed since a git ref |
1055
-
1028
+ |---|---|---|---|
1029
+ | `--runtime-coverage` | `string` | - | Paid runtime-coverage sidecar input. Accepts a V8 directory, a single V8 JSON file, or an Istanbul coverage map JSON. When set, `fallow security` annotates tainted-sink candidates with production runtime state and uses that state as an additive ranking signal |
1030
+ | `--min-invocations-hot` | `string` | `100` | Threshold for hot-path classification, forwarded to the sidecar when `--runtime-coverage` is set |
1031
+ | `--file` | `string` | - | Scope output to candidates whose finding anchor or trace hop matches the selected file. The full graph is still analyzed |
1032
+ | `--gate` | `new\|newly-reachable` | - | `new` fails (exit code **8**) only when the change introduces a NEW security-sink candidate in the changed lines. It requires a diff source (`--changed-since`, `--diff-file`, or `--diff-stdin`). `newly-reachable` fails when an existing candidate becomes reachable from entry points compared with `--changed-since <ref>`; diff-only inputs exit 2 because this mode analyzes the base tree. Human output says `REVIEW REQUIRED` (not `FAIL`); SARIF keeps every result at `level: note` with the verdict in `run.properties.fallowGate`; `--format json` carries an additive `gate` block (`mode` / `verdict` / `new_count`) |
1033
+ | `--surface` | `bool` | `false` | Include the agent-facing `attack_surface[]` inventory in JSON output |
1034
+
1035
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--changed-since`](#global-flags), [`--diff-file`](#global-flags), [`--diff-stdin`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags).
1036
+ <!-- generated:flags:security:end -->
1056
1037
  ### Examples
1057
1038
 
1058
1039
  ```bash
@@ -1073,7 +1054,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1073
1054
  {
1074
1055
  "kind": "security",
1075
1056
  "schema_version": "4",
1076
- "version": "2.93.0",
1057
+ "version": "2.95.0",
1077
1058
  "elapsed_ms": 42,
1078
1059
  "config": {
1079
1060
  "rules": {
@@ -1102,7 +1083,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1102
1083
  {
1103
1084
  "kind": "security",
1104
1085
  "schema_version": "4",
1105
- "version": "2.93.0",
1086
+ "version": "2.95.0",
1106
1087
  "elapsed_ms": 42,
1107
1088
  "config": {
1108
1089
  "rules": {
@@ -1356,6 +1337,7 @@ The inspected payload prints to stderr; stdout (including `--format json`) is un
1356
1337
 
1357
1338
  - **Off by default.** Precedence: `DO_NOT_TRACK` / `FALLOW_TELEMETRY_DISABLED` (kill switches) > `FALLOW_TELEMETRY_DEBUG` (forces inspect) > `FALLOW_TELEMETRY` env > CI (off unless `FALLOW_TELEMETRY` is set) > user config (`fallow telemetry enable/disable`) > off.
1358
1339
  - **CI is off** unless `FALLOW_TELEMETRY` is explicitly set in that CI environment; a local `enable` never turns on org CI telemetry.
1340
+ - **Decision status:** `fallow telemetry status --format json` includes `explicit_decision`. `false` means the user may have only seen the notice; `true` means `telemetry enable` or `telemetry disable` was explicitly run.
1359
1341
  - **Transport:** when enabled, one small JSON event is POSTed to `https://api.fallow.cloud/v1/telemetry/events` (override with `FALLOW_API_URL`), no auth token, no cookies, on a background thread so it does not delay your command. Delivery is best-effort; errors never change output or exit code.
1360
1342
  - **Agent source:** wrappers may set `FALLOW_AGENT_SOURCE=<allowlisted-value>` so an enabled run is attributed correctly. Allowlist: `codex`, `claude_code`, `cursor`, `copilot`, `opencode`, `aider`, `roo`, `windsurf`, `gemini` (aliases `gemini_cli`/`antigravity`), `cline`, `continue`, `zed`, `goose`, `other_known`, `unknown`, `none`. Setting it never enables telemetry and uploads no codebase content.
1361
1343
 
@@ -1490,10 +1472,13 @@ fallow config --path # only the path (scriptable)
1490
1472
 
1491
1473
  ### Flags
1492
1474
 
1493
- | Flag | Type | Description |
1494
- |------|------|-------------|
1495
- | `--path` | bool | Print only the config file path, no JSON |
1475
+ <!-- generated:flags:config:start -->
1476
+ | Flag | Type | Default | Description |
1477
+ |---|---|---|---|
1478
+ | `--path` | `bool` | `false` | Print only the config file path, no JSON |
1496
1479
 
1480
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--config`](#global-flags), [`--root`](#global-flags).
1481
+ <!-- generated:flags:config:end -->
1497
1482
  ### Exit Codes
1498
1483
 
1499
1484
  | Code | Meaning |
@@ -1512,39 +1497,90 @@ The `loaded config: <path>` line is also emitted to stderr automatically at the
1512
1497
 
1513
1498
  Available on all commands:
1514
1499
 
1515
- | Flag | Type | Description |
1516
- |------|------|-------------|
1517
- | `-r, --root` | path | Project root directory |
1518
- | `-c, --config` | path | Config file path |
1519
- | `-f, --format` (alias: `--output`) | string | Output format |
1520
- | `-q, --quiet` | bool | Suppress progress output |
1521
- | `--no-cache` | bool | Disable incremental caching |
1522
- | `--threads` | number | Number of parser threads |
1523
- | `--changed-since` (alias: `--base`) | string | Git-aware incremental analysis |
1524
- | `--baseline` | path | Compare to baseline |
1525
- | `--save-baseline` | path | Save results as baseline |
1526
- | `--fail-on-regression` | bool | Fail if issue count increased beyond tolerance vs a regression baseline |
1527
- | `--tolerance` | string | Allowed increase: `"2%"` (percentage) or `"5"` (absolute). Default: `"0"` |
1528
- | `--regression-baseline` | path | Path to regression baseline file (default: `.fallow/regression-baseline.json`) |
1529
- | `--save-regression-baseline` | path | Save current issue counts as a regression baseline |
1530
- | `--production` | bool | Exclude test/dev files, only start/build scripts (applies to every analysis) |
1531
- | `--production-dead-code` / `--production-health` / `--production-dupes` | bool | Per-analysis production mode for bare combined runs and `fallow audit`. Per-analysis env vars `FALLOW_PRODUCTION_DEAD_CODE`/`HEALTH`/`DUPES` mirror these flags. Per-analysis env beats global `FALLOW_PRODUCTION`. |
1532
- | `--performance` | bool | Show pipeline timing breakdown |
1533
- | `-w, --workspace` | string | Scope to one or more workspaces (comma-separated, globs, `!` negation) |
1534
- | `--changed-workspaces` | string (git ref) | Git-derived monorepo CI scoping: scope to workspaces containing any file changed since `REF`. Mutually exclusive with `--workspace`. Missing ref is a hard error. |
1535
- | `--explain` | bool | JSON: include metric definitions in `_meta`. Human: print a `Description:` line under each section header. Always on for MCP. |
1536
- | `--legacy-envelope` | bool | Emit the previous typed JSON root envelope without top-level `kind` |
1537
- | `--only` | string | Run only specific analyses (e.g., `--only dead-code,dupes`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
1538
- | `--skip` | string | Skip specific analyses (e.g., `--skip health`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
1539
- | `--ci` | bool | CI mode: `--format sarif --fail-on-issues --quiet` |
1540
- | `--fail-on-issues` | bool | Exit 1 if any issues found (promotes `warn` to `error`) |
1541
- | `--sarif-file` | path | Write SARIF output to a file instead of stdout |
1542
- | `--summary` | bool | Show only category counts without individual items. Useful for dashboards and quick overviews |
1543
- | `--group-by` | `owner\|directory\|package\|section` | Group output by CODEOWNERS ownership (`owner`), first path component (`directory`), workspace package (`package`, aliases: `workspace`, `pkg`), or GitLab CODEOWNERS `[Section]` headers (`section`, alias: `gl-section`). All output formats partition issues into labeled groups. `section` mode attaches an `owners` array to each group in JSON output |
1544
- | `--score` | bool | Compute health score (0-100 with letter grade) in combined mode. Enables the health delta header in PR comments. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown |
1545
- | `--trend` | bool | Compare current health metrics against saved snapshot. Implies `--score`. Shows per-metric deltas with directional indicators. Requires at least one saved snapshot in `.fallow/snapshots/` |
1546
- | `--save-snapshot` | path (optional) | Save vital signs snapshot for trend tracking. Default path: `.fallow/snapshots/<timestamp>.json`. Forces file-scores + hotspot computation |
1547
-
1500
+ <!-- generated:flags:global:start -->
1501
+ | Flag | Type | Default | Description |
1502
+ |---|---|---|---|
1503
+ | `-r, --root` | `string` | - | Project root directory |
1504
+ | `-c, --config` | `string` | - | Config file path |
1505
+ | `-f, --format` | `human\|json\|sarif\|compact\|markdown\|codeclimate\|pr-comment-github\|pr-comment-gitlab\|review-github\|review-gitlab\|badge` | `human` | Output format (alias: --output) |
1506
+ | `-q, --quiet` | `bool` | `false` | Suppress progress output |
1507
+ | `--no-cache` | `bool` | `false` | Disable incremental caching |
1508
+ | `--threads` | `string` | - | Number of parser threads |
1509
+ | `--changed-since` | `string` | - | Only report issues in files changed since this git ref (e.g., main, HEAD~5) |
1510
+ | `--diff-file` | `string` | - | Unified diff for line-level scoping. Use `-` to read from stdin. Project-level findings still bypass this filter. When both this and `--changed-since` are set, the diff filter wins for finding scope while `--changed-since` still drives file discovery |
1511
+ | `--diff-stdin` | `bool` | `false` | Read the unified diff from stdin. Equivalent to `--diff-file -` |
1512
+ | `--churn-file` | `string` | - | Import change history from a `fallow-churn/v1` JSON file instead of `git log`, powering hotspots, ownership, and bus-factor on projects with no git repository (Yandex Arc, Mercurial, Perforce). A small wrapper translates your VCS log into the contract. Resolved relative to `--root`. Affects `health --hotspots` / `--ownership` / `--targets` only; `audit`, `impact`, and `--changed-since` still require git |
1513
+ | `--max-file-size` | `string` | - | Skip source files larger than this many megabytes (default 5) instead of parsing them, guarding against the out-of-memory blowup a single multi-MB generated/vendored/bundled file causes on large repos. Use `0` for no limit. Declaration files (`.d.ts`) are always analyzed. Skipped files are reported and excluded from every analysis. Also settable via `FALLOW_MAX_FILE_SIZE` |
1514
+ | `--baseline` | `string` | - | Compare to baseline |
1515
+ | `--parent-run` | `string` | - | Correlate this run with a previous telemetry analysis run |
1516
+ | `--save-baseline` | `string` | - | Save results as baseline |
1517
+ | `--production` | `bool` | `false` | Exclude test/dev files, only start/build scripts (applies to every analysis) |
1518
+ | `--no-production` | `bool` | `false` | Force production mode OFF for every analysis, overriding a project config's `production: true` (and `FALLOW_PRODUCTION`). Conflicts with `--production` |
1519
+ | `--production-dead-code` | `bool` | `false` | Run dead-code analysis in production mode when using bare combined mode |
1520
+ | `--production-health` | `bool` | `false` | Run health analysis in production mode when using bare combined mode |
1521
+ | `--production-dead-code` / `--production-health` / `--production-dupes` | `bool` | `false` | Per-analysis production mode for bare combined runs and `fallow audit`. Per-analysis env vars `FALLOW_PRODUCTION_DEAD_CODE`/`HEALTH`/`DUPES` mirror these flags. Per-analysis env beats global `FALLOW_PRODUCTION`. |
1522
+ | `-w, --workspace` | `string` | - | Scope to one or more workspaces (comma-separated, globs, `!` negation) |
1523
+ | `--changed-workspaces` | `string` | - | Git-derived monorepo CI scoping: scope to workspaces containing any file changed since `REF`. Mutually exclusive with `--workspace`. Missing ref is a hard error. |
1524
+ | `--group-by` | `owner\|directory\|package\|section` | - | Group output by CODEOWNERS ownership (`owner`), first path component (`directory`), workspace package (`package`, aliases: `workspace`, `pkg`), or GitLab CODEOWNERS `[Section]` headers (`section`, alias: `gl-section`). All output formats partition issues into labeled groups. `section` mode attaches an `owners` array to each group in JSON output |
1525
+ | `--performance` | `bool` | `false` | Show pipeline timing breakdown |
1526
+ | `--explain` | `bool` | `false` | JSON: include metric definitions in `_meta`. Human: print a `Description:` line under each section header. Always on for MCP. |
1527
+ | `--legacy-envelope` | `bool` | `false` | Emit the previous typed JSON root envelope without top-level `kind` |
1528
+ | `--explain-skipped` | `bool` | `false` | Show a per-pattern breakdown for default duplicate ignores |
1529
+ | `--summary` | `bool` | `false` | Show only category counts without individual items. Useful for dashboards and quick overviews |
1530
+ | `--ci` | `bool` | `false` | CI mode: `--format sarif --fail-on-issues --quiet` |
1531
+ | `--fail-on-issues` | `bool` | `false` | Exit 1 if any issues found (promotes `warn` to `error`) |
1532
+ | `--sarif-file` | `string` | - | Write SARIF output to a file instead of stdout |
1533
+ | `-o, --output-file` | `string` | - | Write the report to a file instead of stdout, for any --format (no ANSI codes). Useful on large projects where the terminal scrollback truncates the top. Progress and the confirmation stay on stderr |
1534
+ | `--fail-on-regression` | `bool` | `false` | Fail if issue count increased beyond tolerance vs a regression baseline |
1535
+ | `--tolerance` | `string` | `0` | Allowed increase: `"2%"` (percentage) or `"5"` (absolute). Default: `"0"` |
1536
+ | `--regression-baseline` | `string` | - | Path to regression baseline file (default: `.fallow/regression-baseline.json`) |
1537
+ | `--save-regression-baseline` | `string` | - | Save current issue counts as a regression baseline |
1538
+ | `--only` | `dead-code\|dupes\|health` | - | Run only specific analyses (e.g., `--only dead-code,dupes`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
1539
+ | `--skip` | `dead-code\|dupes\|health` | - | Skip specific analyses (e.g., `--skip health`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
1540
+ | `--dupes-mode` | `strict\|mild\|weak\|semantic` | - | Override duplication detection mode in combined mode |
1541
+ | `--dupes-threshold` | `string` | - | Override duplication threshold in combined mode |
1542
+ | `--dupes-min-tokens` | `string` | - | Override the minimum token count for clones in combined mode |
1543
+ | `--dupes-min-lines` | `string` | - | Override the minimum line count for clones in combined mode |
1544
+ | `--dupes-min-occurrences` | `string` | - | Override the minimum clone occurrences in combined mode (must be >= 2) |
1545
+ | `--dupes-skip-local` | `bool` | `false` | Only report cross-directory duplicates in combined mode |
1546
+ | `--dupes-cross-language` | `bool` | `false` | Enable cross-language duplicate detection in combined mode |
1547
+ | `--dupes-ignore-imports` | `bool` | `false` | Exclude import declarations from duplicate detection in combined mode |
1548
+ | `--score` | `bool` | `false` | Compute health score (0-100 with letter grade) in combined mode. Enables the health delta header in PR comments. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown |
1549
+ | `--trend` | `bool` | `false` | Compare current health metrics against saved snapshot. Implies `--score`. Shows per-metric deltas with directional indicators. Requires at least one saved snapshot in `.fallow/snapshots/` |
1550
+ | `--save-snapshot` | `string` | - | Save vital signs snapshot for trend tracking. Default path: `.fallow/snapshots/<timestamp>.json`. Forces file-scores + hotspot computation |
1551
+ | `--coverage` | `string` | - | Path to Istanbul coverage data for exact CRAP scores in combined mode. Also settable via `FALLOW_COVERAGE` or `health.coverage` |
1552
+ | `--coverage-root` | `string` | - | Absolute prefix to strip from Istanbul file paths in combined mode. Also settable via `FALLOW_COVERAGE_ROOT` or `health.coverageRoot` |
1553
+ | `--include-entry-exports` | `bool` | `false` | Report unused exports in entry files instead of auto-marking them as used |
1554
+ <!-- generated:flags:global:end -->
1555
+
1556
+ ### Combined Mode Flags
1557
+
1558
+ <!-- generated:flags:fallow-combined:start -->
1559
+ | Flag | Type | Default | Description |
1560
+ |---|---|---|---|
1561
+ | `--only` | `dead-code\|dupes\|health` | - | Run only specific analyses when no subcommand is given |
1562
+ | `--skip` | `dead-code\|dupes\|health` | - | Skip specific analyses when no subcommand is given |
1563
+ | `--production` | `bool` | `false` | Production mode: exclude test/story/dev files, only start/build scripts, report type-only dependencies |
1564
+ | `--no-production` | `bool` | `false` | Force production mode OFF for every analysis, overriding a project config's `production: true` (and `FALLOW_PRODUCTION`). Conflicts with `--production` |
1565
+ | `--production-dead-code` | `bool` | `false` | Run dead-code analysis in production mode when using bare combined mode |
1566
+ | `--production-health` | `bool` | `false` | Run health analysis in production mode when using bare combined mode |
1567
+ | `--production-dupes` | `bool` | `false` | Run duplication analysis in production mode when using bare combined mode |
1568
+ | `--dupes-mode` | `strict\|mild\|weak\|semantic` | - | Override duplication detection mode in combined mode |
1569
+ | `--dupes-threshold` | `string` | - | Override duplication threshold in combined mode |
1570
+ | `--dupes-min-tokens` | `string` | - | Override the minimum token count for clones in combined mode |
1571
+ | `--dupes-min-lines` | `string` | - | Override the minimum line count for clones in combined mode |
1572
+ | `--dupes-min-occurrences` | `string` | - | Override the minimum clone occurrences in combined mode (must be >= 2) |
1573
+ | `--dupes-skip-local` | `bool` | `false` | Only report cross-directory duplicates in combined mode |
1574
+ | `--dupes-cross-language` | `bool` | `false` | Enable cross-language duplicate detection in combined mode |
1575
+ | `--dupes-ignore-imports` | `bool` | `false` | Exclude import declarations from duplicate detection in combined mode |
1576
+ | `--score` | `bool` | `false` | Compute health score in combined mode |
1577
+ | `--trend` | `bool` | `false` | Compare current health metrics against the most recent saved snapshot |
1578
+ | `--save-snapshot` | `string` | - | Save a vital signs snapshot for trend tracking in combined mode. Provide a path or omit for the default `.fallow/snapshots/` location |
1579
+ | `--coverage` | `string` | - | Path to Istanbul coverage data for exact CRAP scores in combined mode. Also settable via `FALLOW_COVERAGE` or `health.coverage` |
1580
+ | `--coverage-root` | `string` | - | Absolute prefix to strip from Istanbul file paths in combined mode. Also settable via `FALLOW_COVERAGE_ROOT` or `health.coverageRoot` |
1581
+
1582
+ These are global flags with behavior specific to bare `fallow` combined mode.
1583
+ <!-- generated:flags:fallow-combined:end -->
1548
1584
  ---
1549
1585
 
1550
1586
  ## Environment Variables
@@ -1558,6 +1594,8 @@ Available on all commands:
1558
1594
  | `FALLOW_EXTENDS_TIMEOUT_SECS` | Timeout for fetching remote config inheritance in seconds (default: `5`). Do not raise this for untrusted sources. |
1559
1595
  | `FALLOW_CACHE_DIR` | Override the persistent extraction cache directory. Wins over `cache.dir`. Useful for read-only checkouts or CI cache volumes. `--no-cache` disables this knob. |
1560
1596
  | `FALLOW_CACHE_MAX_SIZE` | Maximum on-disk extraction cache (`.fallow/cache.bin`) size in megabytes (default: `256`). Triggers LRU eviction when crossed. Wins over `cache.maxSizeMb` config field. Intended for CI runners with disk quotas. `--no-cache` short-circuits this knob. |
1597
+ | `FALLOW_COVERAGE` | Path to Istanbul coverage data for exact CRAP scoring in `health`, `audit`, and bare `fallow`. |
1598
+ | `FALLOW_COVERAGE_ROOT` | Absolute coverage-data prefix to strip before matching Istanbul paths in `health`, `audit`, and bare `fallow`. |
1561
1599
  | `FALLOW_AUDIT_BASE` | Pin the `fallow audit` comparison base when `--base` / `--changed-since` is unset (precedence: flag > env > auto-detect). Escape hatch for the agent gate and forks, e.g. `FALLOW_AUDIT_BASE=upstream/main`. When unset, audit auto-detects the `git merge-base` against the branch's upstream or the remote default. A malformed value exits 2. |
1562
1600
  | `FALLOW_AUDIT_CACHE_MAX_AGE_DAYS` | Max age (in days since last reuse or fresh create) of a persistent reusable `fallow audit` base-snapshot worktree cache. Older entries are reclaimed at the top of the next `fallow audit` invocation (default: `30`). Wins over `audit.cacheMaxAgeDays` config field. `0` disables the GC; invalid values silently fall back to config / default. |
1563
1601
  | `FALLOW_UPDATE_CHECK` | Set to `off`, `0`, `false`, `disabled`, or `no` to disable the human-TTY upgrade nudge and its background latest-version check. `DO_NOT_TRACK`, `FALLOW_TELEMETRY_DISABLED`, and CI also suppress it. |
@@ -1661,7 +1699,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1661
1699
  {
1662
1700
  "kind": "dead-code",
1663
1701
  "schema_version": 7,
1664
- "version": "2.93.0",
1702
+ "version": "2.95.0",
1665
1703
  "elapsed_ms": 45,
1666
1704
  "total_issues": 12,
1667
1705
  "entry_points": {
@@ -1821,7 +1859,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
1821
1859
  {
1822
1860
  "kind": "dupes",
1823
1861
  "schema_version": 7,
1824
- "version": "2.93.0",
1862
+ "version": "2.95.0",
1825
1863
  "elapsed_ms": 82,
1826
1864
  "total_clones": 15,
1827
1865
  "total_lines_duplicated": 230,
@@ -1865,11 +1903,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
1865
1903
  {
1866
1904
  "kind": "combined",
1867
1905
  "schema_version": 7,
1868
- "version": "2.93.0",
1906
+ "version": "2.95.0",
1869
1907
  "elapsed_ms": 159,
1870
1908
  "check": {
1871
1909
  "schema_version": 7,
1872
- "version": "2.93.0",
1910
+ "version": "2.95.0",
1873
1911
  "elapsed_ms": 45,
1874
1912
  "total_issues": 12,
1875
1913
  "unused_files": [],
@@ -1904,7 +1942,7 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
1904
1942
  }
1905
1943
  ```
1906
1944
 
1907
- Use `--only` or `--skip` to control which analyses are included in the combined output.
1945
+ Use `--only` or `--skip` to control which analyses are included in the combined output. Use `--coverage` and `--coverage-root` to feed Istanbul coverage data to the embedded health analysis for exact CRAP scoring.
1908
1946
 
1909
1947
  With `--score`, the combined output's `health` section includes a `health_score` object (same schema as `health --score`). With `--trend`, it includes a `health_trend` object comparing against the most recent saved snapshot. With `--save-snapshot`, a vital signs snapshot is persisted for future trend comparisons.
1910
1948
 
@@ -2068,6 +2106,16 @@ unused-exports = "off"
2068
2106
  preset = "bulletproof"
2069
2107
  ```
2070
2108
 
2109
+ ### Configuration field notes
2110
+
2111
+ - `ignoreExportsUsedInFile`: knip-compatible; suppress unused-export findings when the exported symbol is referenced inside the file that declares it. Boolean (`true` covers all kinds) or `{ "type": true, "interface": true }` object form for knip parity. Fallow groups type aliases and interfaces under the same `unused-types` issue, so both type-kind fields behave identically. References inside the export specifier itself (`export { foo }`, `export default foo`) do not count as same-file uses; those exports are still reported when no other in-file expression references the binding
2112
+ - `publicPackages`: workspace packages that are public libraries; exported API surface from these packages is not flagged as unused
2113
+ - `dynamicallyLoaded`: glob patterns for files loaded at runtime (plugin dirs, locale files); treated as always-used
2114
+ - `cache.dir`: override the persistent extraction cache directory. `FALLOW_CACHE_DIR` wins over this config field, and `--no-cache` disables caching entirely
2115
+ - `cache.maxSizeMb`: cap the serialized extraction cache size in megabytes. `FALLOW_CACHE_MAX_SIZE` wins over this config field
2116
+ - `usedClassMembers`: class method/property names that extend the built-in Angular/React lifecycle allowlist with framework-invoked names. Each entry is a plain string (global suppression) or a scoped object `{ extends?, implements?, members }` matching only classes with the given heritage. Strings can be exact names (`"agInit"`) or glob patterns (`"*"` matches every member, `"enter*"` prefix, `"*Handler"` suffix, `"on*Event"` combined). Use scoped rules for common names like `refresh` or `execute` to avoid false negatives on unrelated classes; global strings for unique names like `agInit`. Example: `["agInit", { "implements": "ICellRendererAngularComp", "members": ["refresh"] }, { "extends": "BaseCommand", "members": ["execute"] }, { "extends": "GrammarBaseListener", "members": ["enter*", "exit*"] }]`. Glob patterns that match zero members emit a `WARN` so dead allowlist entries surface. An unconstrained scoped rule (no `extends` or `implements`) is rejected at load time. Use plugin-level `usedClassMembers` in a `.fallow/plugins/*.jsonc` file for library-specific allowlists
2117
+ - `resolve.conditions`: additional package.json `exports` / `imports` condition names to honor during module resolution. Baseline conditions (`development`, `import`, `require`, `default`, `types`, `node`, plus `react-native` / `browser` under RN/Expo) are always included; user entries prepend ahead of them. Use for community conditions like `worker`, `edge-light`, `deno`, or custom bundler conditions. Example: `{ "resolve": { "conditions": ["worker", "edge-light"] } }`
2118
+
2071
2119
  ---
2072
2120
 
2073
2121
  ## Inline Suppression Comments