fallow 2.95.0 → 2.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fallow",
3
- "version": "2.95.0",
3
+ "version": "2.97.0",
4
4
  "description": "Deterministic codebase intelligence for TypeScript and JavaScript. Quality, risk, architecture, dependencies, duplication, and safe cleanup evidence for humans, CI, and agents. Optional runtime intelligence layer (Fallow Runtime) adds production execution evidence. Rust-native, sub-second, zero-config framework support.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -80,16 +80,16 @@
80
80
  "detect-libc": "2.1.2"
81
81
  },
82
82
  "devDependencies": {
83
- "@tanstack/intent": "0.0.41"
83
+ "@tanstack/intent": "0.0.42"
84
84
  },
85
85
  "optionalDependencies": {
86
- "@fallow-cli/darwin-arm64": "2.95.0",
87
- "@fallow-cli/darwin-x64": "2.95.0",
88
- "@fallow-cli/linux-x64-gnu": "2.95.0",
89
- "@fallow-cli/linux-arm64-gnu": "2.95.0",
90
- "@fallow-cli/linux-x64-musl": "2.95.0",
91
- "@fallow-cli/linux-arm64-musl": "2.95.0",
92
- "@fallow-cli/win32-arm64-msvc": "2.95.0",
93
- "@fallow-cli/win32-x64-msvc": "2.95.0"
86
+ "@fallow-cli/darwin-arm64": "2.97.0",
87
+ "@fallow-cli/darwin-x64": "2.97.0",
88
+ "@fallow-cli/linux-x64-gnu": "2.97.0",
89
+ "@fallow-cli/linux-arm64-gnu": "2.97.0",
90
+ "@fallow-cli/linux-x64-musl": "2.97.0",
91
+ "@fallow-cli/linux-arm64-musl": "2.97.0",
92
+ "@fallow-cli/win32-arm64-msvc": "2.97.0",
93
+ "@fallow-cli/win32-x64-msvc": "2.97.0"
94
94
  }
95
95
  }
package/schema.json CHANGED
@@ -112,7 +112,7 @@
112
112
  "ignoreDefaults": true,
113
113
  "skipLocal": false,
114
114
  "crossLanguage": false,
115
- "ignoreImports": false,
115
+ "ignoreImports": true,
116
116
  "normalization": {},
117
117
  "minCorpusSizeForShingleFilter": 1024,
118
118
  "minCorpusSizeForTokenCache": 5000
@@ -154,6 +154,16 @@
154
154
  "unused-optional-dependencies": "warn",
155
155
  "unused-enum-members": "error",
156
156
  "unused-class-members": "error",
157
+ "unused-store-members": "warn",
158
+ "unprovided-injects": "warn",
159
+ "unrendered-components": "warn",
160
+ "unused-component-props": "warn",
161
+ "unused-component-emits": "warn",
162
+ "unused-server-actions": "warn",
163
+ "unused-load-data-keys": "warn",
164
+ "prop-drilling": "off",
165
+ "thin-wrapper": "off",
166
+ "duplicate-prop-shape": "off",
157
167
  "unresolved-imports": "error",
158
168
  "unlisted-dependencies": "error",
159
169
  "duplicate-exports": "error",
@@ -172,7 +182,12 @@
172
182
  "misconfigured-dependency-overrides": "error",
173
183
  "security-client-server-leak": "off",
174
184
  "security-sink": "off",
175
- "policy-violation": "warn"
185
+ "policy-violation": "warn",
186
+ "invalid-client-export": "warn",
187
+ "mixed-client-server-barrel": "warn",
188
+ "misplaced-directive": "warn",
189
+ "route-collision": "error",
190
+ "dynamic-segment-name-conflict": "error"
176
191
  }
177
192
  },
178
193
  "boundaries": {
@@ -697,9 +712,9 @@
697
712
  "default": false
698
713
  },
699
714
  "ignoreImports": {
700
- "description": "Exclude ES `import` declarations from clone detection.\n\nWhen enabled, all `import` statements (value imports, type imports, and\nside-effect imports) are stripped from the token stream before clone\ndetection. This reduces noise from sorted import blocks that naturally\nlook similar across files. Only affects ES `import` declarations;\nCommonJS `require()` calls are not filtered.",
715
+ "description": "Exclude module-wiring declarations from clone detection.\n\nDefaults to `true`: token-identical module wiring is a structural\nproperty of well-formatted code, not copy-paste, so it should not\nsurface as clone groups. Set to `false` to count module wiring again.\nWhen enabled, ES imports, re-export declarations, and top-level static\nCommonJS `require(\"...\")` binding declarations are stripped from the\ntoken stream before clone detection. Dynamic imports, side-effect\n`require()` calls, nested `require()` calls, dynamic require arguments,\nand mixed declarations are still counted.",
701
716
  "type": "boolean",
702
- "default": false
717
+ "default": true
703
718
  },
704
719
  "normalization": {
705
720
  "description": "Fine-grained normalization overrides on top of the detection mode.",
@@ -1012,6 +1027,56 @@
1012
1027
  "$ref": "#/$defs/Severity",
1013
1028
  "default": "error"
1014
1029
  },
1030
+ "unused-store-members": {
1031
+ "description": "Store members (Pinia `state` / `getters` / `actions` key, or a\nsetup-store returned key) declared but never accessed by any consumer\nproject-wide. Defaults to `warn`, not `error` like the closed-set\nclass/enum member rules: a store has an OPEN declaration surface\n(plugins, `$onAction`, dynamic dispatch) so analyzer confidence is\ngenuinely lower; warn encodes that without failing CI. Promotable to\n`error` once validated on a codebase.",
1032
+ "$ref": "#/$defs/Severity",
1033
+ "default": "error"
1034
+ },
1035
+ "unprovided-injects": {
1036
+ "description": "Vue `inject(KEY)` / Svelte `getContext(KEY)` whose symbol KEY is\n`provide`/`setContext`'d nowhere in the project (the\ninjected-never-provided dead-half). Defaults to `warn`, not `error`:\na DI key has an open provide surface (plugins, app-level provide) so\nanalyzer confidence is lower; warn encodes that without failing CI.",
1037
+ "$ref": "#/$defs/Severity",
1038
+ "default": "error"
1039
+ },
1040
+ "unrendered-components": {
1041
+ "description": "Vue/Svelte single-file component reachable in the module graph but\nrendered nowhere in the project (the imported-but-never-rendered\ndead-half). Defaults to `warn`, not `error`: a component can be rendered\nreflectively (dynamic `<component :is>`), so analyzer confidence is\nlower; warn encodes that without failing CI.",
1042
+ "$ref": "#/$defs/Severity",
1043
+ "default": "error"
1044
+ },
1045
+ "unused-component-props": {
1046
+ "description": "Vue `<script setup>` `defineProps` declared prop referenced nowhere\ninside its own single-file component (neither `<script>` nor\n`<template>`). The single-file dead-input direction. Defaults to `warn`,\nnot `error`: a prop can be part of a deliberately-stable public component\nAPI, so analyzer confidence is lower; warn encodes that without failing\nCI.",
1047
+ "$ref": "#/$defs/Severity",
1048
+ "default": "error"
1049
+ },
1050
+ "unused-component-emits": {
1051
+ "description": "Vue `<script setup>` `defineEmits` declared event emitted nowhere inside\nits own single-file component (no `emit('<name>')` call). The single-file\ndead-input direction. Defaults to `warn`, not `error`: an emit can be part\nof a deliberately-stable public component API, so analyzer confidence is\nlower; warn encodes that without failing CI.",
1052
+ "$ref": "#/$defs/Severity",
1053
+ "default": "error"
1054
+ },
1055
+ "unused-server-actions": {
1056
+ "description": "Next.js Server Action (an export of a `\"use server\"` file) referenced by\nno code in the project: no import-and-call, no `action={fn}` binding, no\n`<form action={fn}>`. Cross-graph dead-export direction, reclassified out\nof `unused-export` for `\"use server\"` files. Defaults to `warn`, not\n`error`: the rule is new and false-negative-preferring, and reflective\naction-dispatch shapes can hide a real consumer; warn encodes that\nwithout failing CI until corpus-validated.",
1057
+ "$ref": "#/$defs/Severity",
1058
+ "default": "error"
1059
+ },
1060
+ "unused-load-data-keys": {
1061
+ "description": "SvelteKit `+page.{ts,server.ts,js,server.js}` `load()` return-object key\nread by no consumer: not off the sibling `+page.svelte`'s `data.<key>`,\nnor project-wide via `page.data.<key>` / `$page.data.<key>`. Cross-file\ndead-input direction. Defaults to `warn`, not `error`: the rule is new and\nfalse-negative-preferring (a whole-object `data` pass abstains), and a\nload fetch can have side effects so deletion is a human call; warn encodes\nthat without failing CI until corpus-validated.",
1062
+ "$ref": "#/$defs/Severity",
1063
+ "default": "warn"
1064
+ },
1065
+ "prop-drilling": {
1066
+ "description": "React/Preact prop forwarded unchanged through `>= N` intermediate\npass-through components until a component that substantively consumes it.\nA graph-derived health signal. Defaults to `off` (opt-in), like\n`private-type-leak` / `security-*`: the located per-chain records and the\nsmall capped health penalty are dormant until the user enables the rule.",
1067
+ "$ref": "#/$defs/Severity",
1068
+ "default": "off"
1069
+ },
1070
+ "thin-wrapper": {
1071
+ "description": "A React/Preact component whose entire body is `return <Child {...props}/>`\n(pure structural indirection, a candidate for inlining). A graph-derived\nhealth signal. Defaults to `off` (opt-in), like `prop-drilling`: the\nlocated per-wrapper records are dormant until the user enables the rule.",
1072
+ "$ref": "#/$defs/Severity",
1073
+ "default": "off"
1074
+ },
1075
+ "duplicate-prop-shape": {
1076
+ "description": "Three or more React/Preact components across two or more files whose\nstatically-harvested prop NAME set is identical after stripping ubiquitous\nDOM / passthrough names (a missing shared `Props` type / base component).\nA graph-derived structural-refactor health signal. Defaults to `off`\n(opt-in), like `thin-wrapper`: the located per-component records are\ndormant until the user enables the rule.",
1077
+ "$ref": "#/$defs/Severity",
1078
+ "default": "off"
1079
+ },
1015
1080
  "unresolved-imports": {
1016
1081
  "$ref": "#/$defs/Severity",
1017
1082
  "default": "error"
@@ -1090,6 +1155,31 @@
1090
1155
  "description": "Master severity for rule-pack findings (`rulePacks` config). Defaults\nto `warn` so enabling a brand-new policy pack never hard-fails CI on\nits first run; individual pack rules opt up via `\"severity\": \"error\"`.\n`off` is a kill switch that disables the whole evaluator (per-rule\nseverity cannot resurrect it).",
1091
1156
  "$ref": "#/$defs/Severity",
1092
1157
  "default": "warn"
1158
+ },
1159
+ "invalid-client-export": {
1160
+ "description": "A `\"use client\"` file that exports a Next.js server-only /\nroute-segment config name (e.g. `metadata`, `revalidate`, `GET`).\nNext.js rejects this at build time; fallow catches it statically.\nDefaults to `warn`.",
1161
+ "$ref": "#/$defs/Severity",
1162
+ "default": "warn"
1163
+ },
1164
+ "mixed-client-server-barrel": {
1165
+ "description": "A barrel file that re-exports BOTH a `\"use client\"` origin module AND a\nserver-only origin module. Importing one name from such a barrel drags\nthe other's directive context across the React Server Components\nboundary (the Next.js App Router footgun). Defaults to `warn`.",
1166
+ "$ref": "#/$defs/Severity",
1167
+ "default": "warn"
1168
+ },
1169
+ "misplaced-directive": {
1170
+ "description": "A `\"use client\"` / `\"use server\"` directive written as an expression\nstatement after a non-directive statement (an import, a const), so the\nRSC bundler parses it as an ordinary string and silently ignores it.\nThe intended client/server boundary never takes effect. Defaults to\n`warn`.",
1171
+ "$ref": "#/$defs/Severity",
1172
+ "default": "warn"
1173
+ },
1174
+ "route-collision": {
1175
+ "description": "Two or more Next.js App Router route files that resolve to the same URL\nwithin one app-root. Next.js fails the build (\"You cannot have two\nparallel pages that resolve to the same path\"); fallow catches it\nstatically and names every colliding file. Defaults to `error`: the\nproject already fails `next build`, so flagging it as an error aligns\nfallow's exit code with the build it mirrors.",
1176
+ "$ref": "#/$defs/Severity",
1177
+ "default": "error"
1178
+ },
1179
+ "dynamic-segment-name-conflict": {
1180
+ "description": "Sibling Next.js dynamic route segments at one tree position using\ndifferent param spellings (`[id]` vs `[slug]`). Next.js throws \"You\ncannot use different slug names for the same dynamic path\" at dev and\nproduction runtime when the position is hit; `next build` does NOT catch\nit (the build succeeds), so CI passes while the route crashes on its\nfirst request. fallow catches it statically. Defaults to `error`: the\nroute is a deterministic runtime crash on first request, so failing CI\nis the honest signal even though `next build` stays green (this is the\n\"error-runtime\" severity tier, shared with `route-collision`).",
1181
+ "$ref": "#/$defs/Severity",
1182
+ "default": "error"
1093
1183
  }
1094
1184
  }
1095
1185
  },
@@ -1591,6 +1681,106 @@
1591
1681
  }
1592
1682
  ]
1593
1683
  },
1684
+ "unused-store-members": {
1685
+ "anyOf": [
1686
+ {
1687
+ "$ref": "#/$defs/Severity"
1688
+ },
1689
+ {
1690
+ "type": "null"
1691
+ }
1692
+ ]
1693
+ },
1694
+ "unprovided-injects": {
1695
+ "anyOf": [
1696
+ {
1697
+ "$ref": "#/$defs/Severity"
1698
+ },
1699
+ {
1700
+ "type": "null"
1701
+ }
1702
+ ]
1703
+ },
1704
+ "unrendered-components": {
1705
+ "anyOf": [
1706
+ {
1707
+ "$ref": "#/$defs/Severity"
1708
+ },
1709
+ {
1710
+ "type": "null"
1711
+ }
1712
+ ]
1713
+ },
1714
+ "unused-component-props": {
1715
+ "anyOf": [
1716
+ {
1717
+ "$ref": "#/$defs/Severity"
1718
+ },
1719
+ {
1720
+ "type": "null"
1721
+ }
1722
+ ]
1723
+ },
1724
+ "unused-component-emits": {
1725
+ "anyOf": [
1726
+ {
1727
+ "$ref": "#/$defs/Severity"
1728
+ },
1729
+ {
1730
+ "type": "null"
1731
+ }
1732
+ ]
1733
+ },
1734
+ "unused-server-actions": {
1735
+ "anyOf": [
1736
+ {
1737
+ "$ref": "#/$defs/Severity"
1738
+ },
1739
+ {
1740
+ "type": "null"
1741
+ }
1742
+ ]
1743
+ },
1744
+ "unused-load-data-keys": {
1745
+ "anyOf": [
1746
+ {
1747
+ "$ref": "#/$defs/Severity"
1748
+ },
1749
+ {
1750
+ "type": "null"
1751
+ }
1752
+ ]
1753
+ },
1754
+ "prop-drilling": {
1755
+ "anyOf": [
1756
+ {
1757
+ "$ref": "#/$defs/Severity"
1758
+ },
1759
+ {
1760
+ "type": "null"
1761
+ }
1762
+ ]
1763
+ },
1764
+ "thin-wrapper": {
1765
+ "anyOf": [
1766
+ {
1767
+ "$ref": "#/$defs/Severity"
1768
+ },
1769
+ {
1770
+ "type": "null"
1771
+ }
1772
+ ]
1773
+ },
1774
+ "duplicate-prop-shape": {
1775
+ "anyOf": [
1776
+ {
1777
+ "$ref": "#/$defs/Severity"
1778
+ },
1779
+ {
1780
+ "type": "null"
1781
+ }
1782
+ ]
1783
+ },
1594
1784
  "unresolved-imports": {
1595
1785
  "anyOf": [
1596
1786
  {
@@ -1780,6 +1970,56 @@
1780
1970
  "type": "null"
1781
1971
  }
1782
1972
  ]
1973
+ },
1974
+ "invalid-client-export": {
1975
+ "anyOf": [
1976
+ {
1977
+ "$ref": "#/$defs/Severity"
1978
+ },
1979
+ {
1980
+ "type": "null"
1981
+ }
1982
+ ]
1983
+ },
1984
+ "mixed-client-server-barrel": {
1985
+ "anyOf": [
1986
+ {
1987
+ "$ref": "#/$defs/Severity"
1988
+ },
1989
+ {
1990
+ "type": "null"
1991
+ }
1992
+ ]
1993
+ },
1994
+ "misplaced-directive": {
1995
+ "anyOf": [
1996
+ {
1997
+ "$ref": "#/$defs/Severity"
1998
+ },
1999
+ {
2000
+ "type": "null"
2001
+ }
2002
+ ]
2003
+ },
2004
+ "route-collision": {
2005
+ "anyOf": [
2006
+ {
2007
+ "$ref": "#/$defs/Severity"
2008
+ },
2009
+ {
2010
+ "type": "null"
2011
+ }
2012
+ ]
2013
+ },
2014
+ "dynamic-segment-name-conflict": {
2015
+ "anyOf": [
2016
+ {
2017
+ "$ref": "#/$defs/Severity"
2018
+ },
2019
+ {
2020
+ "type": "null"
2021
+ }
2022
+ ]
1783
2023
  }
1784
2024
  }
1785
2025
  },
@@ -106,12 +106,12 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
106
106
  | `config` | Show the loaded config path and resolved config (verifies which `.fallowrc.json` is in effect) | `--path` |
107
107
  | `list` | Inspect project structure | `--files`, `--entry-points`, `--plugins`, `--boundaries`, `--workspaces` |
108
108
  | `workspaces` | Inspect monorepo workspaces + discovery diagnostics (shorthand for `list --workspaces`) | (no flags) |
109
- | `dupes` | Code duplication detection | `--mode`, `--threshold`, `--top`, `--changed-since`, `--workspace`, `--changed-workspaces`, `--skip-local`, `--cross-language`, `--ignore-imports`, `--explain-skipped`, `--fail-on-regression`, `--tolerance`, `--regression-baseline`, `--save-regression-baseline` |
109
+ | `dupes` | Code duplication detection | `--mode`, `--threshold`, `--top`, `--changed-since`, `--workspace`, `--changed-workspaces`, `--skip-local`, `--cross-language`, `--ignore-imports`, `--no-ignore-imports`, `--explain-skipped`, `--fail-on-regression`, `--tolerance`, `--regression-baseline`, `--save-regression-baseline` |
110
110
  | `health` | Function complexity analysis (also covers Angular templates as synthetic `<template>` findings: external `.html` files via `templateUrl` AND inline `@Component({ template: \`...\` })` literals; suppress external with `<!-- fallow-ignore-file complexity -->` at the top of the `.html` file, suppress inline with `// fallow-ignore-next-line complexity` directly above the `@Component` decorator) | `--complexity`, `--max-cyclomatic`, `--max-cognitive`, `--max-crap`, `--top`, `--sort`, `--file-scores`, `--hotspots`, `--ownership`, `--ownership-emails`, `--targets`, `--effort`, `--score`, `--min-score`, `--since`, `--min-commits`, `--save-snapshot`, `--trend`, `--coverage-gaps`, `--coverage`, `--coverage-root`, `--runtime-coverage`, `--min-invocations-hot`, `--min-observation-volume`, `--low-traffic-threshold`, `--workspace`, `--changed-workspaces`, `--baseline`, `--save-baseline` |
111
111
  | `flags` | Detect feature flag patterns (env vars, SDK calls, config objects) | `--top` |
112
112
  | `explain` | Explain one issue type without running analysis | `<issue-type>`, `--format json` |
113
113
  | `audit` | Combined dead-code + complexity + duplication for changed files | `--base`, `--gate`, `--production`, `--production-dead-code`, `--production-health`, `--production-dupes`, `--workspace`, `--changed-workspaces`, `--ci`, `--fail-on-issues`, `--explain`, `--explain-skipped`, `--dead-code-baseline`, `--health-baseline`, `--dupes-baseline`, `--max-crap`, `--coverage`, `--coverage-root`, `--include-entry-exports` |
114
- | `impact` | Show what fallow has done for you: how many issues it is surfacing, the trend since the last recorded run, and how many commits it contained at the pre-commit gate | |
114
+ | `impact` | Show what fallow has done for you: how many issues it is surfacing, the trend since the last recorded run, and how many commits it contained at the pre-commit gate | `--all`, `--sort`, `--limit` |
115
115
  | `security` | Surface opt-in local security candidates for agent verification (not confirmed vulnerabilities). Rule families include the graph rule `client-server-leak`, a data-driven `tainted-sink` catalogue, and the include-required `hardcoded-secret` category for provider-prefix credentials and high-entropy literals assigned to secret-shaped identifiers. Most catalogue rows require non-literal input; narrowly literal-aware rows flag deterministic unsafe literals. Rules default off; suppress a file with `// fallow-ignore-file security-sink`; scope categories with `security.categories`. Add project-local request object names with `security.requestReceivers`; it extends the built-in `req` / `request` / `ctx` / `context` / `event` allowlist for HTTP `query`, `params`, and `body` reads. `hardcoded-secret` runs only when listed in `security.categories.include`. | `--format human\|json\|sarif`, `--changed-since`, `--file`, `--diff-file`, `--workspace`, `--changed-workspaces`, `--surface`, `--ci`, `--fail-on-issues`, `--sarif-file`, `--summary` |
116
116
  | `schema` | Dump CLI definition as JSON | |
117
117
  | `ci-template` | Print or vendor CI integration templates | |
@@ -141,6 +141,7 @@ Run `fallow <command> --help` for the full flag list per command (see also refer
141
141
  | `test-only-dependency` | `--unused-deps` | - | - | Production deps only imported from test files (should be devDependencies) |
142
142
  | `unused-enum-member` | `--unused-enum-members` | yes | `// fallow-ignore-next-line unused-enum-member` | Enum values never referenced |
143
143
  | `unused-class-member` | `--unused-class-members` | - | `// fallow-ignore-next-line unused-class-member` | Methods and properties |
144
+ | `unused-store-member` | `--unused-store-members` | - | `// fallow-ignore-next-line unused-store-member` | Pinia store state/getter/action (needs `pinia` dep) |
144
145
  | `unresolved-import` | `--unresolved-imports` | - | `// fallow-ignore-next-line unresolved-import` | Imports that can't be resolved |
145
146
  | `unlisted-dependency` | `--unlisted-deps` | - | - | Used packages missing from package.json. In monorepos, importing a workspace package from a workspace whose own `package.json` does not list it is reported here too; self-references stay allowed without requiring a package to depend on itself. |
146
147
  | `duplicate-export` | `--duplicate-exports` | - | `// fallow-ignore-file duplicate-export` | Same symbol exported from multiple modules |
@@ -156,6 +157,20 @@ Run `fallow <command> --help` for the full flag list per command (see also refer
156
157
  | `unresolved-catalog-reference` | `--unresolved-catalog-references` | - | - | `package.json` references to `catalog:` / `catalog:<name>` whose catalog does not declare the package; `pnpm install` would fail. Default `error`. Suppress via `ignoreCatalogReferences: [{ package, catalog?, consumer? }]` in fallow config (package.json has no comment syntax). |
157
158
  | `unused-dependency-override` | `--unused-dependency-overrides` | - | - | `pnpm-workspace.yaml#overrides` / `package.json#pnpm.overrides` entries whose target package is not declared by any workspace `package.json` and is not present in `pnpm-lock.yaml`. Default `warn`. When the lockfile is missing or unreadable the check degrades to a manifest-only fallback and every finding carries a `hint` reminding consumers to verify before removal. Suppress via `ignoreDependencyOverrides: [{ package, source? }]` in fallow config. |
158
159
  | `misconfigured-dependency-override` | `--misconfigured-dependency-overrides` | - | - | `pnpm.overrides` entries whose key is unparsable (empty, dangling separators, malformed selectors) or value is missing/empty. `pnpm install` would fail. Default `error`. Suppression: same `ignoreDependencyOverrides` config rule. |
160
+ | `invalid-client-export` | - | - | `// fallow-ignore-next-line invalid-client-export` | "use client" file exports a server-only / route-config name; Requires the project to declare next |
161
+ | `mixed-client-server-barrel` | - | - | `// fallow-ignore-next-line mixed-client-server-barrel` | Barrel re-exports both a "use client" module and a server-only module; Requires the project to declare next |
162
+ | `misplaced-directive` | - | - | `// fallow-ignore-next-line misplaced-directive` | "use client" / "use server" directive is not in the leading position and is ignored; Requires the project to declare next |
163
+ | `unprovided-inject` | `--unprovided-injects` | - | `// fallow-ignore-next-line unprovided-inject` | inject() / getContext() reads a key that no provide() / setContext() supplies |
164
+ | `unrendered-component` | `--unrendered-components` | - | `// fallow-ignore-next-line unrendered-component` | A Vue / Svelte component is reachable through a barrel but rendered nowhere |
165
+ | `unused-component-prop` | `--unused-component-props` | - | `// fallow-ignore-next-line unused-component-prop` | A Vue defineProps prop or React component prop is referenced nowhere in its own component |
166
+ | `unused-component-emit` | `--unused-component-emits` | - | `// fallow-ignore-next-line unused-component-emit` | A Vue <script setup> defineEmits event is emitted nowhere in its own component |
167
+ | `unused-server-action` | `--unused-server-actions` | - | `// fallow-ignore-next-line unused-server-action` | A Next.js Server Action exported from a "use server" file is referenced by no code in the project |
168
+ | `unused-load-data-key` | `--unused-load-data-keys` | - | `// fallow-ignore-next-line unused-load-data-key` | A SvelteKit load() return-object key is read by no consumer (needs @sveltejs/kit dep) |
169
+ | `prop-drilling` | - | - | `// fallow-ignore-next-line prop-drilling` | A React/Preact prop is forwarded unchanged through 3+ pass-through components to a distant consumer; Opt-in: set rules.prop-drilling to warn or error to enable. Defaults to off. |
170
+ | `thin-wrapper` | - | - | `// fallow-ignore-next-line thin-wrapper` | A React/Preact component whose whole body is a single spread-forwarded child render (a candidate for inlining); Opt-in: set rules.thin-wrapper to warn or error to enable. Defaults to off. |
171
+ | `duplicate-prop-shape` | - | - | `// fallow-ignore-next-line duplicate-prop-shape` | Three or more React/Preact components across two or more files declare an identical prop-name set (a missing shared Props type); Opt-in: set rules.duplicate-prop-shape to warn or error to enable. Defaults to off. |
172
+ | `route-collision` | - | - | - | Two or more Next.js App Router route files resolve to the same URL |
173
+ | `dynamic-segment-name-conflict` | - | - | - | Sibling Next.js dynamic route segments use different slug names at the same position |
159
174
  | `high-cyclomatic-complexity` | `--complexity` | - | `// fallow-ignore-next-line complexity` | Function has high cyclomatic complexity |
160
175
  | `high-cognitive-complexity` | `--complexity` | - | `// fallow-ignore-next-line complexity` | Function has high cognitive complexity |
161
176
  | `high-complexity` | `--complexity` | - | `// fallow-ignore-next-line complexity` | Function exceeds both complexity thresholds |
@@ -198,7 +213,8 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
198
213
  | `project_info` | introspection | free | `entry_points`, `files`, `plugins`, `boundaries` | Project metadata. Set `entry_points`, `files`, `plugins`, or `boundaries` to `true` to request specific sections |
199
214
  | `list_boundaries` | introspection | free | - | Architecture boundary zones, access rules, and pre-expansion `autoDiscover` `logical_groups[]` (user-authored parent name, verbatim paths, discovered children, `status` enum, summed `file_count`). Returns `{"configured": false}` if no boundaries configured |
200
215
  | `feature_flags` | analysis | free | `workspace`, `production` | Detect feature flag patterns (env vars, SDK calls, config objects). Set `top` to limit results |
201
- | `impact` | introspection | free | `root` | Read the local, opt-in Fallow Impact value report (`fallow impact --format json`). Runs no analysis: current surfacing counts, trend since the last recorded run, pre-commit gate containment, and (on impact v1.5+) resolved/suppressed attribution. Read-only and `root`-only; the mutating `enable` / `disable` lifecycle is not exposed. A never-enabled project returns a populated `{"enabled": false, ...}` report (never `{}`); branch on `enabled` then `record_count` and recommend the user run `fallow impact enable` rather than toggling it. Local-developer signal: empty in ephemeral CI runners, so not a CI metric |
216
+ | `impact` | introspection | free | `root` | Read the local, opt-in Fallow Impact value report (`fallow impact --format json`). Runs no analysis: current surfacing counts, trend since the last recorded run, pre-commit gate containment, and (on impact v1.5+) resolved/suppressed attribution. History is read from a per-project file in the user's private config dir (never inside the repo). Read-only and `root`-only; the mutating `enable` / `disable` / `default` lifecycle is not exposed. A never-enabled project returns a populated `{"enabled": false, ...}` report (never `{}`); branch on `enabled` and `enabled_source` (`project` / `user` / `default`) then `record_count`, recommending `fallow impact enable` only when `explicit_decision` is `false` (never asked) and staying silent when `true` (deliberately disabled here). Local-developer signal: fallow never records in CI, so empty there and not a CI metric |
217
+ | `impact_all` | introspection | free | `sort`, `limit` | Roll every tracked fallow project on this machine into one cross-repo value report (hashed keys plus basename labels, never paths; local-dev only) |
202
218
  | `trace_export` | trace | free | `file`, `export_name` | Trace why an export is used or unused (`fallow dead-code --trace FILE:EXPORT_NAME --format json`). Required `file` and `export_name`. Returns file reachability, entry-point status, direct references, re-export chains, and a reason string. Use before deleting a supposedly-unused export |
203
219
  | `trace_file` | trace | free | `file` | Trace all graph edges for a file (`fallow dead-code --trace-file PATH --format json`). Required `file`. Returns reachability, exports, imports-from, imported-by, and re-exports. Use to decide whether a file is isolated, barrel-only, or imported by live entry points |
204
220
  | `trace_dependency` | trace | free | `package_name` | Trace where a dependency is imported (`fallow dead-code --trace-dependency PACKAGE --format json`). Required `package_name`. Returns importing files, type-only importers, total import count, `used_in_scripts` (true when invoked from package.json scripts or CI configs), and `is_used` (combined import + script signal; mirrors the unused-deps detector so build tools like `microbundle` or `vitest` are not falsely flagged as unused). Use before removing a dependency or moving between `dependencies` and `devDependencies` |
@@ -234,7 +250,6 @@ Embedding fallow in a Node.js process (editor extensions, servers, custom toolin
234
250
  ## Common Workflows
235
251
 
236
252
  ### Audit a project for cleanup opportunities
237
-
238
253
  ```bash
239
254
  fallow dead-code --format json --quiet
240
255
  ```
@@ -242,13 +257,11 @@ fallow dead-code --format json --quiet
242
257
  Parse the JSON output. It contains arrays for each issue type (`unused_files`, `unused_exports`, `unused_types`, `unused_dependencies`, etc.) plus `total_issues` and `elapsed_ms` metadata. Each issue object includes an `actions` array with structured fix suggestions (action type, `auto_fixable` flag, description, and optional suppression comment). For dependency findings, a non-empty `used_in_workspaces` array means the package is imported elsewhere in the monorepo; treat it as a workspace placement issue and do not auto-remove it.
243
258
 
244
259
  ### Find only unused exports (smaller output)
245
-
246
260
  ```bash
247
261
  fallow dead-code --format json --quiet --unused-exports
248
262
  ```
249
263
 
250
264
  ### Check if a PR introduces quality risk
251
-
252
265
  ```bash
253
266
  fallow audit --format json --quiet --base main
254
267
  ```
@@ -256,7 +269,6 @@ fallow audit --format json --quiet --base main
256
269
  Returns a pass/warn/fail verdict for issues introduced by the PR. Only analyzes files changed since the `main` branch.
257
270
 
258
271
  ### Find code duplication
259
-
260
272
  ```bash
261
273
  fallow dupes --format json --quiet
262
274
  fallow dupes --format json --quiet --mode semantic
@@ -265,7 +277,6 @@ fallow dupes --format json --quiet --mode semantic
265
277
  The `semantic` mode detects renamed variables. Other modes: `strict` (exact), `mild` (default, syntax normalized), `weak` (different literals).
266
278
 
267
279
  ### Safe auto-fix cycle
268
-
269
280
  ```bash
270
281
  fallow fix --dry-run --format json --quiet # 1. preview what will be removed
271
282
  fallow fix --yes --format json --quiet # 2. review the preview, then apply
@@ -275,7 +286,6 @@ fallow dead-code --format json --quiet # 3. verify the fix worked
275
286
  The `--yes` flag is required in non-TTY environments (agent subprocesses). Without it, `fix` exits with code 2.
276
287
 
277
288
  ### Discover project structure
278
-
279
289
  ```bash
280
290
  fallow list --entry-points --format json --quiet
281
291
  fallow list --plugins --format json --quiet
@@ -284,7 +294,6 @@ fallow list --plugins --format json --quiet
284
294
  Shows detected entry points and active framework plugins (122 built-in: Next.js, Vite, Ember, Wuchale, Jest, Storybook, Tailwind, PandaCSS, Contentlayer, tap, tsd, etc.).
285
295
 
286
296
  ### Production-only analysis
287
-
288
297
  ```bash
289
298
  fallow dead-code --format json --quiet --production
290
299
  ```
@@ -292,7 +301,6 @@ fallow dead-code --format json --quiet --production
292
301
  Excludes test/dev files (`*.test.*`, `*.spec.*`, `*.stories.*`) and only analyzes production scripts.
293
302
 
294
303
  ### Analyze specific workspaces
295
-
296
304
  ```bash
297
305
  fallow dead-code --format json --quiet --workspace my-package # single package (lists: web,admin)
298
306
  fallow dead-code --format json --quiet --workspace 'apps/*,!apps/legacy' # glob + !-exclude
@@ -302,7 +310,6 @@ fallow dead-code --format json --quiet --changed-workspaces origin/main # CI
302
310
  Scopes output while keeping the full cross-workspace graph. Patterns are tested against BOTH the package name AND the workspace path relative to the repo root; either match counts. `--changed-workspaces <REF>` auto-derives the set from `git diff` (the CI primitive; mutually exclusive with `--workspace`); a missing ref or non-git directory is a hard error (exit 2) rather than a silent full-scope fallback.
303
311
 
304
312
  ### Scope to specific files (lint-staged)
305
-
306
313
  ```bash
307
314
  fallow dead-code --format json --quiet --file src/utils.ts --file src/helpers.ts
308
315
  ```
@@ -310,7 +317,6 @@ fallow dead-code --format json --quiet --file src/utils.ts --file src/helpers.ts
310
317
  Only reports issues in the specified files. Project-wide dependency issues are suppressed. Warns on non-existent paths.
311
318
 
312
319
  ### Catch typos in entry file exports
313
-
314
320
  ```bash
315
321
  fallow dead-code --format json --quiet --include-entry-exports
316
322
  ```
@@ -318,7 +324,6 @@ fallow dead-code --format json --quiet --include-entry-exports
318
324
  Reports unused exports in entry files (package.json `main`/`exports`, framework pages). By default, exports in entry files are assumed externally consumed. This flag catches typos like `meatdata` instead of `metadata`.
319
325
 
320
326
  ### Detect feature flag patterns
321
-
322
327
  ```bash
323
328
  fallow flags --format json --quiet
324
329
  fallow flags --format json --quiet --top 20
@@ -327,7 +332,6 @@ fallow flags --format json --quiet --top 20
327
332
  Reports environment-variable gates (`process.env.FEATURE_*`), SDK calls from common flag providers, and config-object patterns, with flag locations, detection confidence, and a cross-reference against dead code. Only `--top N` is command-specific.
328
333
 
329
334
  ### Surface security candidates for verification
330
-
331
335
  ```bash
332
336
  fallow security --format json --quiet
333
337
  fallow security --format json --quiet --surface
@@ -338,7 +342,6 @@ git diff --cached --unified=0 | fallow security --gate new --diff-stdin --format
338
342
  These are unverified candidates, not confirmed vulnerabilities; an agent must verify trace, reachability, and evidence before editing. `--surface` adds a top-level `attack_surface[]` inventory for a verifier. The gate modes are `new` (candidates introduced on changed lines) and `newly-reachable` (candidates that became reachable from entry points, which needs `--changed-since <ref>`); there is no `all` mode by design. The gate fails with exit 8, distinct from the standard exit ladder.
339
343
 
340
344
  ### Find untested runtime-reachable code (coverage gaps)
341
-
342
345
  ```bash
343
346
  fallow health --format json --quiet --coverage-gaps
344
347
  ```
@@ -346,7 +349,6 @@ fallow health --format json --quiet --coverage-gaps
346
349
  Reports `untested-file` and `untested-export` findings: runtime-reachable code with no dependency path from any discovered test root. Opt-in and requires the full analysis pipeline.
347
350
 
348
351
  ### Find complexity hotspots, owners, and refactoring targets
349
-
350
352
  ```bash
351
353
  # Files that are both complex and frequently changing (needs a git repo)
352
354
  fallow health --format json --quiet --hotspots
@@ -361,7 +363,6 @@ fallow health --format json --quiet --hotspots --group-by owner
361
363
  `--ownership` implies `--hotspots` and `--effort` implies `--targets`. The global `--group-by` accepts `owner`, `directory`, `package`, or `section` (the `section` mode reads GitLab CODEOWNERS `[Section]` headers). Hotspots and ownership require a git repository.
362
364
 
363
365
  ### Explain why a complex function scored high
364
-
365
366
  ```bash
366
367
  fallow health --format json --quiet --complexity --complexity-breakdown
367
368
  ```
@@ -369,7 +370,6 @@ fallow health --format json --quiet --complexity --complexity-breakdown
369
370
  Adds a per-decision-point `contributions[]` array to every complexity finding (each `if`, `else-if`, loop, boolean operator, and `case` with its source line and cyclomatic/cognitive weight), so you can pinpoint the exact refactor target.
370
371
 
371
372
  ### Gate CI on regressions (baselines)
372
-
373
373
  ```bash
374
374
  # 1. Save the current issue counts as a regression baseline
375
375
  fallow dead-code --format json --quiet --save-regression-baseline .fallow/baseline.json
@@ -383,7 +383,6 @@ fallow dead-code --format json --quiet --baseline .fallow/snapshot.json
383
383
  `--save-regression-baseline` / `--regression-baseline` / `--fail-on-regression` / `--tolerance` are count-based gates; `--save-baseline` / `--baseline` are identity-based (track finding identity, fail on new). All six are global flags, so they also work on `health` and `dupes`. `audit` rejects the global baseline flags and uses `--dead-code-baseline` / `--health-baseline` / `--dupes-baseline` instead.
384
384
 
385
385
  ### Explain an issue type without running analysis
386
-
387
386
  ```bash
388
387
  fallow explain unused-export --format json
389
388
  fallow explain code-duplication
@@ -392,7 +391,6 @@ fallow explain code-duplication
392
391
  The issue type is a positional argument and accepts forms like `unused-export`, `fallow/unused-export`, `unused exports`, or `code duplication`. It runs no analysis and returns the rule rationale, a worked example, fix guidance, and the docs URL.
393
392
 
394
393
  ### Show what fallow has surfaced over time (Impact)
395
-
396
394
  ```bash
397
395
  # Enable once (local-only, opt-in, never uploads, never affects exit codes)
398
396
  fallow impact enable
@@ -400,10 +398,9 @@ fallow impact enable
400
398
  fallow impact --format json --quiet
401
399
  ```
402
400
 
403
- `fallow impact enable` is a one-time, user-owned local action; the agent-facing line is the read step. The store lives at `.fallow/impact.json` (gitignored), the report is read-only, and it is empty in ephemeral CI runners.
401
+ `fallow impact enable` is a one-time, user-owned local action; the agent-facing line is the read step. History is stored per-project in the user's private config dir (never inside the repo, so no `.fallow/` or `.gitignore` changes); `fallow impact default on` enables it for every project at once. The report is read-only and is empty in CI (fallow never records there).
404
402
 
405
403
  ### Debug why something is flagged
406
-
407
404
  ```bash
408
405
  fallow dead-code --format json --quiet --trace src/utils.ts:myFunction # trace an export's usage chain
409
406
  fallow dead-code --format json --quiet --trace-file src/utils.ts # trace all edges for a file
@@ -411,7 +408,6 @@ fallow dead-code --format json --quiet --trace-dependency lodash # trace
411
408
  ```
412
409
 
413
410
  ### Migrate from knip or jscpd
414
-
415
411
  ```bash
416
412
  fallow migrate --dry-run # preview
417
413
  fallow migrate # apply; mirrors the source extension (knip.jsonc -> .fallowrc.jsonc); --jsonc / --toml force a format
@@ -420,7 +416,6 @@ fallow migrate # apply; mirrors the source extension (knip.jsonc ->
420
416
  Auto-detects `knip.json`, `knip.jsonc`, `.knip.json`, `.knip.jsonc`, `.jscpd.json`, and package.json embedded configs.
421
417
 
422
418
  ### Initialize a new config
423
-
424
419
  ```bash
425
420
  fallow init # creates .fallowrc.json, adds .fallow/ to .gitignore (--toml for fallow.toml)
426
421
  fallow init --agents # scaffolds a starter AGENTS.md prefilled from detected project info (never overwrites)
@@ -461,7 +456,6 @@ Fallow reads config from project root: `.fallowrc.json` > `.fallowrc.jsonc` > `f
461
456
  Rules: `"error"` (fail CI), `"warn"` (report only), `"off"` (skip detection). Other high-value fields: `ignoreDependencies`, `publicPackages` (public library packages whose exported API is never flagged), `cache.dir` / `cache.maxSizeMb`, `usedClassMembers` (extend the framework-invoked member allowlist), `resolve.conditions` (extra package.json export conditions). Field semantics and examples: [CLI Reference](references/cli-reference.md), "Configuration field notes".
462
457
 
463
458
  ### Inline suppression
464
-
465
459
  ```typescript
466
460
  // fallow-ignore-next-line
467
461
  export const keepThis = 1;