fallow 3.30.0 → 3.32.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,21 +1,22 @@
1
1
  {
2
2
  "name": "fallow",
3
- "version": "3.30.0",
3
+ "version": "3.32.0",
4
4
  "mcpName": "io.github.fallow-rs/fallow",
5
- "description": "Codebase intelligence for TypeScript and JavaScript. Free static analysis of code and styles, optional paid runtime intelligence (Fallow Runtime). Quality, risk, architecture, dependencies, duplication, and design-system drift for humans, CI, and the agents writing your code. Zero-config framework support.",
5
+ "description": "Codebase intelligence for TypeScript and JavaScript: health, complexity, duplication, architecture, styling drift, and unused code from one graph. CLI, LSP, and MCP server. Zero config for over 100 frameworks.",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/fallow-rs/fallow.git"
10
10
  },
11
- "homepage": "https://docs.fallow.tools",
11
+ "homepage": "https://fallow.tools/docs/",
12
+ "funding": "https://github.com/sponsors/fallow-rs",
12
13
  "bugs": {
13
14
  "url": "https://github.com/fallow-rs/fallow/issues"
14
15
  },
15
16
  "intent": {
16
17
  "version": 1,
17
18
  "repo": "fallow-rs/fallow",
18
- "docs": "https://docs.fallow.tools"
19
+ "docs": "https://fallow.tools/docs/"
19
20
  },
20
21
  "keywords": [
21
22
  "code-intelligence",
@@ -88,14 +89,14 @@
88
89
  "@tanstack/intent": "0.4.0"
89
90
  },
90
91
  "optionalDependencies": {
91
- "@fallow-cli/darwin-arm64": "3.30.0",
92
- "@fallow-cli/darwin-x64": "3.30.0",
93
- "@fallow-cli/linux-x64-gnu": "3.30.0",
94
- "@fallow-cli/linux-arm64-gnu": "3.30.0",
95
- "@fallow-cli/linux-x64-musl": "3.30.0",
96
- "@fallow-cli/linux-arm64-musl": "3.30.0",
97
- "@fallow-cli/win32-arm64-msvc": "3.30.0",
98
- "@fallow-cli/win32-x64-msvc": "3.30.0",
99
- "fallow-type-aware": "3.30.0"
92
+ "@fallow-cli/darwin-arm64": "3.32.0",
93
+ "@fallow-cli/darwin-x64": "3.32.0",
94
+ "@fallow-cli/linux-x64-gnu": "3.32.0",
95
+ "@fallow-cli/linux-arm64-gnu": "3.32.0",
96
+ "@fallow-cli/linux-x64-musl": "3.32.0",
97
+ "@fallow-cli/linux-arm64-musl": "3.32.0",
98
+ "@fallow-cli/win32-arm64-msvc": "3.32.0",
99
+ "@fallow-cli/win32-x64-msvc": "3.32.0",
100
+ "fallow-type-aware": "3.32.0"
100
101
  }
101
102
  }
package/schema.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "title": "FallowConfig",
4
- "description": "The user-facing fallow configuration as authored in `.fallowrc.json` /\n`.fallowrc.jsonc` / `fallow.toml` (or the `fallow` key of `package.json`).\n\nEvery field documents its serialized meaning, default, and precedence\nagainst CLI flags and environment variables where they exist.\n`FallowConfig::resolve` compiles the loaded config (globs, regexes,\nplugin and rule-pack discovery) into a [`ResolvedConfig`] for analysis.\nUnknown keys are rejected at load so typos fail loud.",
4
+ "description": "The user-facing fallow configuration as authored in `.fallowrc.json` /\n`.fallowrc.jsonc` / `fallow.toml` / `.fallow.toml`.\n\nEvery field documents its serialized meaning, default, and precedence\nagainst CLI flags and environment variables where they exist.\n`FallowConfig::resolve` compiles the loaded config (globs, regexes,\nplugin and rule-pack discovery) into a [`ResolvedConfig`] for analysis.\nUnknown keys are rejected at load so typos fail loud.",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "$schema": {
@@ -36,7 +36,7 @@
36
36
  "default": []
37
37
  },
38
38
  "ignorePatterns": {
39
- "description": "An array of project-root-relative glob patterns for files to exclude from analysis entirely; entries are unioned with fallow's built-in defaults (**/node_modules/**, **/dist/**, **/build/**, **/.git/**, **/coverage/**, **/*.min.js, **/*.min.mjs, **/*.min.cjs, **/*.bundle.js), so custom globs add to rather than replace them. Set it (e.g. `[\"generated/**\"]`) to drop generated or vendored trees from every detector; patterns are validated at load.",
39
+ "description": "An array of project-root-relative glob patterns for files to exclude from analysis entirely; entries are unioned with fallow's built-in defaults (**/node_modules/**, **/dist/**, **/build/**, **/.git/**, **/coverage/**, **/*.min.js, **/*.min.mjs, **/*.min.cjs, **/*.bundle.js), so custom globs add to rather than replace them. Set it (e.g. `[\"generated/**\"]`) to drop generated or vendored trees from every detector; patterns are validated at load. A `!`-prefixed entry is an exception that applies after the defaults and the positive patterns: `\"!src/policy/coverage/**\"` brings back hand-written source under a built-in default such as `**/coverage/**`, and `\"!.config/**\"` adds a hidden directory to discovery. Paths under `node_modules` or `.git` can not be lifted, and a `!` entry that names one of these segments is a config error.",
40
40
  "type": "array",
41
41
  "items": {
42
42
  "type": "string"
@@ -59,7 +59,7 @@
59
59
  "default": []
60
60
  },
61
61
  "workspaces": {
62
- "description": "Monorepo workspace configuration whose sole sub-key patterns (array of globs) adds workspace package roots beyond those discovered from package.json workspaces, pnpm-workspace.yaml, and tsconfig references. Optional and absent by default (discovery uses the manifests alone); set it only when workspaces live in directories the standard manifests do not declare.",
62
+ "description": "Monorepo workspace configuration. `patterns` adds workspace package roots beyond manifest discovery; `changedSince` maps exact project-root-relative workspace roots to Git baseline refs. A global changed-since request overrides those per-package baselines.",
63
63
  "anyOf": [
64
64
  {
65
65
  "$ref": "#/$defs/WorkspaceConfig"
@@ -71,13 +71,20 @@
71
71
  "default": null
72
72
  },
73
73
  "ignoreDependencies": {
74
- "description": "A list of exact package names excluded from BOTH unused-dependency and unlisted-dependency detection, so a runtime-provided or otherwise-untracked package (e.g. `bun:sqlite`, a peer supplied at deploy time) is never flagged as unused when declared nor as unlisted when imported. Set it for packages fallow cannot observe being used and cannot observe being declared; matching is exact string equality against the package name, not a glob.",
74
+ "description": "A list of package names or package-name globs excluded from BOTH unused-dependency and unlisted-dependency detection, so a runtime-provided or otherwise-untracked package (e.g. `bun:sqlite`, a peer supplied at deploy time) is never flagged as unused when declared nor as unlisted when imported. Set it for packages fallow cannot observe being used and cannot observe being declared. An entry without glob characters matches the package name exactly; an entry with `*`, `?`, `[` or `{` is a glob in the `ignorePatterns` syntax matched against the package name, so `@acme/*` covers every package in the `@acme` scope.",
75
75
  "type": "array",
76
76
  "items": {
77
77
  "type": "string"
78
78
  },
79
79
  "default": []
80
80
  },
81
+ "ignoreCommandEntries": {
82
+ "description": "A list of command names whose file arguments fallow does not make entry points. Fallow reads commands in package.json scripts (root and workspace packages), CI files (GitHub Actions and GitLab CI), Dockerfiles, Procfiles, and fly.toml files, and a file that a command names (such as `node scripts/seed.ts`) normally becomes an entry point. A listed command still counts as a used dependency, and its `--config` file is still tracked. Formatters and linters (ESLint, Prettier, Oxlint, Oxfmt, Biome, Stylelint, and similar tools) never make their targets entry points, so they do not need to be listed. Set it for a command whose file arguments are data, not code that runs (e.g. `[\"my-codegen\"]`), or use `[\"*\"]` to turn off entry points from all commands and declare real entries in `entry`. A name matches the command after environment, package-manager, and wrapper prefixes (`npx`, `pnpm exec`, `yarn run`, `varlock run --`), by exact file name; `*` is the only wildcard.",
83
+ "type": "array",
84
+ "items": {
85
+ "type": "string"
86
+ }
87
+ },
81
88
  "ignoreUnresolvedImports": {
82
89
  "description": "A list of glob patterns that suppress only `unresolved-import` findings whose raw import specifier matches; it does not change dependency usage accounting or resolver behavior. Patterns match the import string as written (not a filesystem path), so list both `@example/icons` and `@example/icons/**` to cover a bare package and its subpaths; parent-relative generated specifiers like `../generated/**` are valid, and broad values like `**` can hide real missing modules.",
83
90
  "type": "array",
@@ -129,7 +136,7 @@
129
136
  "default": []
130
137
  },
131
138
  "duplicates": {
132
- "description": "Configures clone detection: `enabled` (default true), `mode` (`strict`, `mild` default, `weak`, `semantic`, from least to most identifier/literal blinding; `strict` and `mild` are equivalent under fallow's AST tokenizer, `weak` blinds string literals, `semantic` blinds all identifiers and literals for Type-2 renamed-variable detection), `near` (false, add bounded function-scoped near-miss detection), `minTokens` (50), `minLines` (5), `minOccurrences` (integer >= 2, deserialization fails below 2), `threshold` (max duplication percentage, 0 = no limit), `ignore` globs, `ignoredClones` (reviewed clone keys to hide until their content or occurrence count changes), `ignoreDefaults` (true, merge built-in generated-file ignores), `skipLocal` (only report cross-directory clones), `crossLanguage` (strip TS type annotations to match .ts against .js), `ignoreImports` (true, strip ES import/re-export/top-level require wiring from the token stream), and `normalization` (per-flag `ignoreIdentifiers`/`ignoreStringValues`/`ignoreNumericValues` overrides on top of `mode`). Raise `minOccurrences` to focus on widespread copy-paste, enable `near` for gapped structural clones, or set `mode` to `semantic` to catch renamed-variable exact clones.",
139
+ "description": "Configures clone detection: `enabled` (default true), `mode` (`strict`, `mild` default, `weak`, `semantic`, from least to most identifier/literal blinding; `strict` and `mild` are equivalent under fallow's AST tokenizer, `weak` blinds string literals, `semantic` blinds all identifiers and literals for Type-2 renamed-variable detection), `near` (false, add bounded function-scoped near-miss detection), `minTokens` (50), `minLines` (5), `minOccurrences` (integer >= 2, deserialization fails below 2), `threshold` (max duplication percentage, 0 = no limit), `ignore` globs, `ignoredClones` (reviewed clone keys to hide until their content or occurrence count changes), `ignoreDefaults` (true, merge built-in generated-file ignores), `skipLocal` (only report cross-directory clones), `ignoreSymlinks` (false, omit clone instances whose path is a symlink or lies under a symlinked directory), `crossLanguage` (strip TS type annotations to match .ts against .js), `ignoreImports` (true, strip ES import/re-export/top-level require wiring from the token stream), and `normalization` (per-flag `ignoreIdentifiers`/`ignoreStringValues`/`ignoreNumericValues` overrides on top of `mode`). Raise `minOccurrences` to focus on widespread copy-paste, enable `near` for gapped structural clones, or set `mode` to `semantic` to catch renamed-variable exact clones.",
133
140
  "$ref": "#/$defs/DuplicatesConfig",
134
141
  "default": {
135
142
  "enabled": true,
@@ -143,6 +150,7 @@
143
150
  "ignoredClones": [],
144
151
  "ignoreDefaults": true,
145
152
  "skipLocal": false,
153
+ "ignoreSymlinks": false,
146
154
  "crossLanguage": false,
147
155
  "ignoreImports": true,
148
156
  "normalization": {},
@@ -207,6 +215,7 @@
207
215
  "unprovided-injects": "warn",
208
216
  "unrendered-components": "warn",
209
217
  "unused-component-props": "warn",
218
+ "absent-component-props": "off",
210
219
  "unused-component-emits": "warn",
211
220
  "unused-component-inputs": "warn",
212
221
  "unused-component-outputs": "warn",
@@ -232,6 +241,7 @@
232
241
  "dev-dependencies-in-production": "warn",
233
242
  "circular-dependencies": "error",
234
243
  "re-export-cycle": "warn",
244
+ "package-cycle": "warn",
235
245
  "boundary-violation": "error",
236
246
  "coverage-gaps": "off",
237
247
  "feature-flags": "off",
@@ -256,6 +266,10 @@
256
266
  "description": "Options for the `unused-component-props` rule, currently only `ignorePattern`: a regex matched against each declared prop's local destructure binding name (falling back to the public prop name when unaliased) to exempt intentionally-unused props such as the leading-underscore convention. Set `{ \"ignorePattern\": \"^_\" }` to skip props like `_stage`; matching is unanchored (substring, like ESLint's `RegExp.test`) so anchor with `^`, the pattern is validated at config load (invalid regex fails load), and it applies to Vue, Svelte, Astro, and React/Preact props (unset leaves the rule unchanged).",
257
267
  "$ref": "#/$defs/UnusedComponentPropsConfig"
258
268
  },
269
+ "circularDependencies": {
270
+ "description": "Options for the `circular-dependencies` rule, currently only `ignoreLazyImports`. Set `{ \"ignoreLazyImports\": true }` to skip import edges that load on demand or on another thread (an `import()` inside a function, a template `import()`, a lazy `import.meta.glob`, a worker URL, a webpack worker loader request such as `worker-loader!./work.js`) when fallow looks for cycles. A top-level `await import()`, `require()`, an eager glob, and an edge that also has a static import stay in the cycle graph. Default `false` leaves the rule unchanged.",
271
+ "$ref": "#/$defs/CircularDependenciesConfig"
272
+ },
259
273
  "boundaries": {
260
274
  "description": "Configures architecture boundary enforcement: which source directories belong to which named zone and which zones may import which others, reported as boundary-violation, boundary-coverage-violation, and boundary-call-violation findings (severity via rules.boundary-violation, default error). Set to enforce a layered/module architecture; the object holds `preset` (one of layered, hexagonal, feature-sliced, bulletproof, whose default zones/rules are merged in with the user-declared zones/rules taking precedence), `zones` (each with `name`, `patterns`, `autoDiscover`, optional `root`), `rules` (each with `from`, `allow`, `allowTypeOnly` target-zone lists), `coverage` (`requireAllFiles` plus `allowUnmatched` globs for files matching no zone), and `calls` (a `forbidden` list of `{from, callee}` banned-call rules per zone).",
261
275
  "$ref": "#/$defs/BoundaryConfig",
@@ -754,6 +768,13 @@
754
768
  "type": "string"
755
769
  },
756
770
  "default": []
771
+ },
772
+ "changedSince": {
773
+ "description": "Git baseline refs keyed by workspace roots, written relative to the project root as `fallow list --workspaces` prints them. Scopes `check`, `dead-code`, `dupes` and editor diagnostics; `health`, `security` and `audit` ignore it. A global changed-since request takes precedence. Unlisted workspaces and root files remain in full scope. A key that names no workspace, or a ref that Git cannot resolve, leaves every package in full scope with a warning.",
774
+ "type": "object",
775
+ "additionalProperties": {
776
+ "type": "string"
777
+ }
757
778
  }
758
779
  }
759
780
  },
@@ -930,6 +951,11 @@
930
951
  "type": "boolean",
931
952
  "default": false
932
953
  },
954
+ "ignoreSymlinks": {
955
+ "description": "Omit clone instances whose file path is a symlink, or lies under a\nsymlinked directory, inside the project root.\n\nDefaults to `false`: symlinked instances stay in the report and carry\n`is_symlink: true` in JSON output. Set to `true` to report only\nduplication between real files. A clone group with fewer than two\nremaining instances is not reported. Symlinked files also leave the\ncorpus, so `stats` (files, lines, tokens and the duplication\npercentage that `threshold` checks) count only real files.",
956
+ "type": "boolean",
957
+ "default": false
958
+ },
933
959
  "crossLanguage": {
934
960
  "description": "Enable cross-language clone detection by stripping type annotations.\n\nWhen enabled, TypeScript type annotations (parameter types, return types,\ngenerics, interfaces, type aliases) are stripped from the token stream,\nallowing detection of clones between `.ts` and `.js` files.",
935
961
  "type": "boolean",
@@ -1369,6 +1395,11 @@
1369
1395
  "$ref": "#/$defs/Severity",
1370
1396
  "default": "warn"
1371
1397
  },
1398
+ "absent-component-props": {
1399
+ "description": "Used optional inputs absent from inspected callers. Requires manual review; off by default.",
1400
+ "$ref": "#/$defs/Severity",
1401
+ "default": "off"
1402
+ },
1372
1403
  "unused-component-emits": {
1373
1404
  "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.",
1374
1405
  "$ref": "#/$defs/Severity",
@@ -1494,6 +1525,11 @@
1494
1525
  "$ref": "#/$defs/Severity",
1495
1526
  "default": "warn"
1496
1527
  },
1528
+ "package-cycle": {
1529
+ "description": "A dependency cycle between workspace packages, built from resolved\ncross-package imports. Defaults to `warn`.",
1530
+ "$ref": "#/$defs/Severity",
1531
+ "default": "warn"
1532
+ },
1497
1533
  "boundary-violation": {
1498
1534
  "description": "An import crossing a forbidden architecture-boundary edge declared in\nthe `boundaries` config. Defaults to `error`.",
1499
1535
  "$ref": "#/$defs/Severity",
@@ -1620,6 +1656,17 @@
1620
1656
  },
1621
1657
  "additionalProperties": false
1622
1658
  },
1659
+ "CircularDependenciesConfig": {
1660
+ "description": "Options for the `circular-dependencies` rule.\n\nThe default leaves the rule unchanged: every runtime import edge takes\npart in cycle detection, and only type-only edges are skipped.",
1661
+ "type": "object",
1662
+ "properties": {
1663
+ "ignoreLazyImports": {
1664
+ "description": "Skip import edges that load their target on demand or on another\nthread when fallow looks for cycles. A literal `import()` inside a\nfunction, a template `import()`, a lazy `import.meta.glob`, a worker\nURL and a webpack worker loader request (`worker-loader!./work.js`)\nare lazy edges. A top-level `await import()`, `require()` and an\neager `import.meta.glob` load before the module finishes, so they stay.\nAn edge that also carries a static import stays. Default `false`.",
1665
+ "type": "boolean"
1666
+ }
1667
+ },
1668
+ "additionalProperties": false
1669
+ },
1623
1670
  "BoundaryConfig": {
1624
1671
  "description": "Architecture boundary configuration.",
1625
1672
  "type": "object",
@@ -1753,7 +1800,7 @@
1753
1800
  "type": "object",
1754
1801
  "properties": {
1755
1802
  "requireAllFiles": {
1756
- "description": "Report source files that do not match any boundary zone.",
1803
+ "description": "Report every analyzed source file that does not match any boundary\nzone, also a file that no entry point reaches.",
1757
1804
  "type": "boolean"
1758
1805
  },
1759
1806
  "allowUnmatched": {
@@ -2195,6 +2242,17 @@
2195
2242
  }
2196
2243
  ]
2197
2244
  },
2245
+ "absent-component-props": {
2246
+ "description": "Optional override for absent optional component inputs.",
2247
+ "anyOf": [
2248
+ {
2249
+ "$ref": "#/$defs/Severity"
2250
+ },
2251
+ {
2252
+ "type": "null"
2253
+ }
2254
+ ]
2255
+ },
2198
2256
  "unused-component-emits": {
2199
2257
  "description": "Optional override for [`RulesConfig::unused_component_emits`].",
2200
2258
  "anyOf": [
@@ -2470,6 +2528,17 @@
2470
2528
  }
2471
2529
  ]
2472
2530
  },
2531
+ "package-cycle": {
2532
+ "description": "Optional override for [`RulesConfig::package_cycle`].",
2533
+ "anyOf": [
2534
+ {
2535
+ "$ref": "#/$defs/Severity"
2536
+ },
2537
+ {
2538
+ "type": "null"
2539
+ }
2540
+ ]
2541
+ },
2473
2542
  "boundary-violation": {
2474
2543
  "description": "Optional override for [`RulesConfig::boundary_violation`].",
2475
2544
  "anyOf": [
@@ -2691,6 +2760,13 @@
2691
2760
  "description": "Saved per-issue-type counts written by `--save-baseline` and compared by\n`--fail-on-regression`. Every count defaults to `0` when its key is missing,\nso hand-trimmed baselines stay loadable.",
2692
2761
  "type": "object",
2693
2762
  "properties": {
2763
+ "absentComponentProps": {
2764
+ "description": "Baseline count of optional component prop review candidates.",
2765
+ "type": "integer",
2766
+ "format": "uint",
2767
+ "minimum": 0,
2768
+ "default": 0
2769
+ },
2694
2770
  "analysisIdentity": {
2695
2771
  "description": "Compatibility identity for the analysis that produced these counts.\nMissing values in existing configs are treated as syntactic.",
2696
2772
  "$ref": "#/$defs/SemanticAnalysisIdentity",
@@ -2801,6 +2877,13 @@
2801
2877
  "minimum": 0,
2802
2878
  "default": 0
2803
2879
  },
2880
+ "packageCycles": {
2881
+ "description": "Baseline count of `package-cycle` findings.",
2882
+ "type": "integer",
2883
+ "format": "uint",
2884
+ "minimum": 0,
2885
+ "default": 0
2886
+ },
2804
2887
  "typeOnlyDependencies": {
2805
2888
  "description": "Baseline count of `type-only-dependencies` findings.",
2806
2889
  "type": "integer",
@@ -6,7 +6,7 @@ license: MIT
6
6
 
7
7
  # Fallow: codebase intelligence for TypeScript and JavaScript
8
8
 
9
- Codebase intelligence for TypeScript and JavaScript. The static layer analyzes code and styles and reports quality, changed-code risk, cleanup opportunities, circular dependencies, code duplication, complexity hotspots, architecture boundary violations, design-system styling drift, feature flag patterns, and opt-in security candidates. Runtime coverage merges production execution data into the same `fallow health` report for hot-path review and cold-path deletion confidence, with a single local capture available by default and continuous/cloud runtime monitoring available as an optional mode. Broad framework plugin coverage, zero configuration, sub-second static analysis.
9
+ Fallow analyzes code and styles for changed-code risk, cleanup opportunities, circular dependencies, duplication, complexity hotspots, architecture boundary violations, design-system styling drift, feature flags, and opt-in security candidates. Runtime coverage merges production execution data into the same `fallow health` report for hot-path review and cold-path deletion confidence. A single local capture is available by default. Continuous or cloud runtime monitoring is optional.
10
10
 
11
11
  ## When to Use
12
12
  - Find cleanup opportunities: unused files, exports, types, members, dependencies, or feature flags that guard unused exports.
@@ -55,9 +55,26 @@ cargo install fallow-cli # build from source
55
55
  12. **Use type-aware analysis only for Fallow-owned project questions**. Reach for `--type-aware` to prove exact symbol use, preserve TypeScript class contracts, guard class-member cleanup, find cross-file private type leaks, suggest targeted tests, or inspect public-signature coupling. Keep `tsc --noEmit` responsible for compiler correctness and Oxlint responsible for local typed lint rules. Treat partial or unavailable semantic results as retained findings, never as deletion proof. Unknown external consumers of a published library remain outside checker-visible evidence, so preserve declared public API unless every relevant consumer project is explicitly in scope.
56
56
  13. **Use `fallow impact statusline` only for a user-facing status surface**. It intentionally emits one plain-text, path-free line and ignores `--format`. It starts no analysis, never enables Impact, and compares only whole-project scans. Do not parse this line as JSON.
57
57
  14. **Treat similar-code output as discovery only**. Never describe its score as a probability, finding, proof of equivalent behavior, or safe-refactor decision. Agents must not authorize setup. Inspect a candidate before judging it: save discovery as `similar-code.json`, inspect with `--candidates similar-code.json`, and pass the unchanged file to `fallow similar-code review`. Over MCP use `find_similar_code` with `paths:` and `inspect_similar_code` with a typed `snapshot`; it fails closed on stale source. Keep `candidate_worthy`, `behaviorally_equivalent`, and `refactor_safe` separate, use `needs-human-review`, and abstain when evidence is incomplete. Only `completion.status: "complete"` makes an empty result conclusive. Follow [the complete workflow to compare semantically similar functions](references/similar-code.md).
58
+ 15. **Check production runtime data before an edit or a delete, when Fallow Cloud is connected**. Prefer the scoped reads over the full `get_cloud_runtime_context` pull. Before an edit, run `fallow coverage review-packet --repo <owner/repo>` (MCP `get_cloud_review_packet`) for the changed files and read `hit_count`, `covered_by_test`, and the callers when present. Before a delete, require `period_tracking_state: "never_called"`, not only `tracking_state`, and read `evidence_window.observed_hours`: few observed hours or a low-traffic surface mean "not visited", not "dead". After a deploy, run `fallow coverage deployment-changes --repo <owner/repo>` (MCP `get_cloud_deployment_changes`) and, when `comparable` is `false`, report `reason` and claim no change. Open files by `repo_path`, not `file_path`. Production data is context, never a gate. Details: [references/mcp.md](references/mcp.md#scoped-cloud-reads).
58
59
 
59
60
  ## Onboarding And Insight
60
- Offer setup only after a human-requested analysis shows findings and all signals match: `fallow config --path` exits 3, not CI, not a pipeline format, `fallow impact --format json --quiet` has `onboarding_declined: false`, and no offer happened this session. Ask after showing value. Choices: guard commits and PRs, baseline the existing backlog and clean by category, add AGENTS.md guidance, or keep as-is. On decline, run `fallow init --decline --quiet` and stay silent for this project. Mutate only after consent. For guards, inspect `fallow hooks status --format json --quiet`, then use `fallow hooks install --target agent` and `fallow hooks install --target git`; for large backlogs, pair the gate with `--save-baseline` / new-only guidance. Offer `fallow impact enable` as local-only value tracking, never as telemetry; also offer it once on already-configured projects when `fallow impact status --format json` has `enabled: false` and `explicit_decision: false`, and record a no with `fallow impact disable --quiet`. Surface value on clear events: if the agent gate blocked a commit or push and a later retry succeeded, mention what was contained; when `next_steps` carries id `impact-report`, run its command and relay the non-zero numbers to the user in one line. On request, summarize non-zero Impact counts. Ask about telemetry only after such a win, only if `fallow telemetry status --format json` has `explicit_decision: false`, and never run `fallow telemetry enable`.
61
+ Offer setup after showing the findings from a human-requested analysis, only when all these conditions hold:
62
+
63
+ - `fallow config --path` exits 3.
64
+ - The run is outside CI and does not use a pipeline format.
65
+ - `fallow impact --format json --quiet` has `onboarding_declined: false`.
66
+ - No offer happened this session.
67
+
68
+ Offer these choices: guard commits and PRs, baseline the existing backlog and clean by category, add AGENTS.md guidance, or keep as-is. Mutate only after consent. On decline, run `fallow init --decline --quiet` and stay silent for this project.
69
+
70
+ For guards, inspect `fallow hooks status --format json --quiet`, then use `fallow hooks install --target agent` and `fallow hooks install --target git`. For large backlogs, pair the gate with `--save-baseline` and new-only guidance.
71
+
72
+ Offer `fallow impact enable` for local value tracking. Impact is separate from telemetry. Also offer it once on an already-configured project when `fallow impact status --format json` has `enabled: false` and `explicit_decision: false`. Record a decline with `fallow impact disable --quiet`.
73
+
74
+ Report value when there is evidence. If the agent gate blocked a commit or push and a later retry succeeded, describe the issues that caused the block. When `next_steps` has id `impact-report`, run its command and report the non-zero numbers in one line. On request, summarize non-zero Impact counts.
75
+
76
+ Ask about telemetry only after one of these events, and only if `fallow telemetry status --format json` has `explicit_decision: false`. Never run `fallow telemetry enable`.
77
+
61
78
  ## Task Cheat Sheet
62
79
  Route by intent before reaching for the big analysis commands. Same matrix as `fallow schema` (`task_matrix`) and the generated AGENTS.md section.
63
80
 
@@ -89,7 +106,9 @@ Full command catalogue, one row per command: **[references/cli-reference.md](ref
89
106
 
90
107
  ## Issue Types
91
108
 
92
- Dead-code filter flags are one per issue type (`--unused-exports`, `--unused-types`, `--unused-deps`, `--circular-deps`, and so on). Passing one or more narrows `fallow dead-code` to those types; passing none reports every type. Every type suppresses the same way: `// fallow-ignore-next-line <issue-type>` above the finding, or `// fallow-ignore-file <issue-type>` at the top of the file; the bare form without a type suppresses all of them.
109
+ Dead-code filter flags select issue categories (`--unused-exports`, `--unused-types`, `--unused-deps`, `--circular-deps`, and so on). Some flags select related types together; `--unused-deps` covers several dependency types. Passing one or more narrows `fallow dead-code` to those categories. Passing none applies no issue-type filter.
110
+
111
+ For suppressible findings, use the placement listed in the issue catalogue: `// fallow-ignore-next-line <issue-type>` above the finding, or `// fallow-ignore-file <issue-type>` at the top of the file. Some types support only file-level suppression; others have no suppression comment. A bare supported form without a type suppresses all matching findings at that placement.
93
112
 
94
113
  `fallow explain <issue-type>` describes one type without running analysis, and the MCP server serves the same catalogue as the `fallow://issue-types` resource.
95
114
 
@@ -99,7 +118,7 @@ Full catalogue, one row per type: **[references/issue-types.md](references/issue
99
118
 
100
119
  Fallow ships an MCP server (`fallow-mcp`) that exposes these same analyses as agent tools. When the server is connected, its tools are already in your context with typed params and structured JSON returns, and each maps to a CLI fallback command. Prefer them when you want JSON without shelling out, or `code_execute` (Code Mode) to compose several read-only analyses in one sandboxed snippet (no single-call CLI equivalent). Otherwise use the CLI.
101
120
 
102
- The server also serves read-only reference resources (no subprocess, no analysis run, cacheable by URI; your client reads them through its own resource tool): `fallow://tools`, `fallow://issue-types`, `fallow://explain/{issue_type}`, `fallow://task-matrix`, and the config, plugin, and rule-pack JSON Schemas. Every payload is JSON and carries `fallow_version`.
121
+ The server also serves read-only reference resources (no subprocess, no analysis run, cacheable by URI; your client reads them through its own resource tool): `fallow://tools`, `fallow://issue-types`, `fallow://explain/{issue_type}`, `fallow://task-matrix`, and the config, plugin, and rule-pack JSON Schemas. Every resource payload is JSON. Each content item carries the server version in `_meta.fallow_version`.
103
122
 
104
123
  Full tool catalogue, resource catalogue, key params, runtime source-map confidence tiers, shared timeouts, and the `next_steps` dispatch mapping: **[references/mcp.md](references/mcp.md)**.
105
124
 
@@ -112,6 +131,8 @@ Full tool catalogue, resource catalogue, key params, runtime source-map confiden
112
131
  - [Similar Code](references/similar-code.md): snapshot-stable discovery, inspection, and verdict workflow
113
132
  - [Node Bindings](references/node-bindings.md): embed the analysis engine in a Node.js process via NAPI
114
133
 
134
+ To set up or modernize the code-quality tooling of a repository (package install, config, agent wiring, CI gate), use the `fallow-setup` skill.
135
+
115
136
  ## Common Workflows
116
137
 
117
138
  ### Audit a project for cleanup opportunities
@@ -239,7 +260,7 @@ fallow health --format json --quiet --group-by owner --score --ownership --save-
239
260
  fallow health --format json --quiet --group-by owner --score --workspace 'packages/*'
240
261
  ```
241
262
 
242
- `--group-by owner` partitions every metric by CODEOWNERS team (last-match-wins, GitHub semantics) with a directory-cached native resolver, so there is no need to parse CODEOWNERS or aggregate per owner yourself. With `--score`, each `groups[]` entry carries a first-class `health_score` (`{ score, grade, penalties: { dead_files, complexity, p90_complexity, maintainability, unused_deps, circular_deps, unit_size, coupling, duplication } }`) alongside its own `vital_signs` and per-file `file_scores[]` (`complexity_density`, `maintainability_index`). Human output renders a `● Per-owner health` table (`score / grade / files / hot`). `--save-snapshot` records a point-in-time entry that `--trend` reads later. This one command replaces a hand-rolled CODEOWNERS-resolution + per-owner-aggregation + scoring script end to end.
263
+ `--group-by owner` partitions every metric by CODEOWNERS team (last-match-wins, GitHub semantics) with a native resolver, so there is no need to parse CODEOWNERS or aggregate per owner yourself. With `--score`, each `groups[]` entry carries a first-class `health_score` (`{ score, grade, penalties: { dead_files, complexity, p90_complexity, maintainability, unused_deps, circular_deps, unit_size, coupling, duplication } }`) alongside its own `vital_signs` and per-file `file_scores[]` (`complexity_density`, `maintainability_index`). Human output renders a `● Per-owner health` table (`score / grade / files / hot`). `--save-snapshot` records a point-in-time entry that `--trend` reads later. This one command replaces a hand-rolled CODEOWNERS-resolution + per-owner-aggregation + scoring script end to end.
243
264
 
244
265
  Caveat for root-only path aliases: in monorepos where TypeScript path aliases (e.g. `@myorg/*`) are declared only in a root `tsconfig.base.json` that the per-package `tsconfig.json` files do not extend, imports through those aliases do not resolve, so dead-code signals (unused files/exports, and the `dead_files` penalty in the per-owner `health_score`) carry false positives. The complexity, maintainability, coupling, hotspot, and ownership signals are computed per file from the AST and git history and stay accurate regardless. Prefer `health` (not `dead-code`) for per-team quality tracking there.
245
266
 
@@ -374,11 +395,11 @@ export const deprecatedHelper = () => {};
374
395
  ## Key Gotchas
375
396
 
376
397
  - **`fix --yes` is required** in non-TTY (agent) environments. Without it, `fix` exits with code 2
377
- - **Zero config by default.** Built-in framework plugins auto-detect, including Wuchale config, Contentlayer content roots, tap and tsd test entry points. Read `fallow schema.plugins` for the current registry and don't create config unless customization is needed
378
- - **Syntactic analysis only.** No TypeScript compiler, so fully dynamic `import(variable)` is not resolved
398
+ - **Zero config by default.** Built-in framework plugins auto-detect, including Wuchale config, Contentlayer content roots, Kibana `kibana.jsonc` plugin entries, tap and tsd test entry points. Read `fallow schema.plugins` for the current registry and don't create config unless customization is needed
399
+ - **Default analysis is syntactic.** Fully dynamic `import(variable)` is not resolved. Optional `--type-aware` analysis adds TypeScript checker evidence
379
400
  - **Function overloads are deduplicated.** TypeScript function overload signatures are merged into a single export (not reported as separate unused exports)
380
- - **Re-export chains are resolved.** Exports through barrel files are tracked, not falsely flagged
381
- - **`--changed-since` is additive.** Only new issues in changed files, not all issues in the project
401
+ - **Re-export chains are resolved.** Fallow tracks exports through barrel files. Trace reported exports before removal when consumers may be outside static analysis
402
+ - **`--changed-since` scopes findings to changed files.** Existing findings in those files can remain, and dead-code dependency findings remain project-wide. Use `fallow audit --gate new-only` to distinguish introduced findings from inherited ones
382
403
 
383
404
  For the full list with examples, see [references/gotchas.md](references/gotchas.md).
384
405