The project's README from github.com/fallow-rs/fallow. As one markdown file: README.md.
Codebase intelligence for TypeScript and JavaScript.
One binary finds unused code, circular dependencies, duplication, complexity hotspots, boundary violations, and design-system styling drift. An optional paid layer, Fallow Runtime, adds production execution evidence.
Deterministic findings and typed output contracts. No AI inside the analyzer, and no TypeScript compiler or Node.js runtime needed for static analysis.
Docs · Quickstart · MCP · Benchmarks
Most repositories carry code nobody dares to delete, because deleting means proving a negative: fallow reads the repository as one dependency graph, from import edges to styling tokens, and reports what that graph shows.
Audit scope: 19 changed files vs HEAD~15 (8fbfcb054..HEAD)
● Unused files (2)
packages/vitest/src/public/reporters.ts
test/coverage-test/test/configuration-options.test-d.ts
● Circular dependencies (6)
packages/vitest/src/integrations/vi.ts
→ wait.ts → vi.ts
✗ dead code: 156 issues · complexity: 6 findings · duplication: 8 clone groups · 19 changed files (1.05s)
audit gate excluded 163 inherited findings (run with --gate all to enforce)
Excerpt from fallow audit on the vitest monorepo, auditing its last 15 commits. fallow 3.5.0, warm base-snapshot cache. The gate passed: the 163 inherited findings are pre-existing and excluded by design, so they do not block the change. The same run with --format json returns one typed JSON document.
# Zero-install, full pipeline (dead code + duplication + health)
npx fallow
# Gate only what a PR changed
npx fallow audit
# Install as a devDependency
npm install --save-dev fallow
# For agents and scripts: exit 0 and 1 both mean the run succeeded (1 = findings);
# exit 2 is a real error, reported as a JSON envelope on stdout
npx fallow audit --format json --quiet 2>/dev/null
The npm package ships the fallow, fallow-lsp, and fallow-mcp launchers plus a version-matched agent skill, so the editor and agent integrations resolve the project-local binary instead of whatever happens to be on PATH. Runs are deterministic: the same input produces the same output with stable fingerprints. Re-running to verify an edit is safe. Other channels (pnpm, yarn, cargo install fallow-cli, and a local Docker build with a Compose example at examples/docker/compose.yaml) are covered in the installation guide.
fallow dead-codefallow similar-code)bulletproof, layered, hexagonal, and feature-sliced presetsfallow audit)fallow security)--type-aware)Over 100 built-in framework plugins detect entry points and framework-consumed exports automatically, so the first run needs no configuration. Fallow Runtime, the optional paid layer, merges production execution evidence into these same reports; see Runtime intelligence (optional) and static vs runtime.
Findings on a first run usually mean fallow is missing an entry point or a framework convention, or is analyzing generated files you never meant to include. The built-in plugins take care of framework detection; it's generated code that usually needs a hint:
{
"$schema": "./node_modules/fallow/schema.json",
"ignorePatterns": ["**/*.generated.ts"]
}
You do not have to author that config yourself. npx fallow recommend detects the stack (frameworks, workspace layout, test runner, package manager), prints a proposed config as a safe starting point, and ends with the few genuinely subjective choices it will not decide for you. For TypeScript projects it also points to the optional, slower --type-aware pass without enabling it. It is read-only and always exits 0; nothing changes until you save the config.
Patterns are relative to the project root and add to fallow's built-in ignore defaults (node_modules, dist, coverage, minified bundles). Config precedence is first match wins per directory, with no merging: .fallowrc.json (JSONC accepted) > .fallowrc.jsonc > fallow.toml > .fallow.toml. The full reference is the configuration overview; the boundaries of the default syntactic and optional type-aware analyses are documented in limitations; for a hung or failed run, see debugging.
Adopting on an existing codebase? fallow audit fails only on findings a change introduces, so a legacy backlog does not block day one, and --save-baseline / --baseline quarantine the existing findings for the standalone commands. The adoption guide covers the staged path.
| Command | What it does |
|---|---|
npx fallow |
Full pipeline: dead code, duplication, health |
npx fallow audit |
Changed-file gate over dead code, complexity, duplication, and styling drift: verdict pass/warn/fail against a base ref. Fails only on findings the change introduced (--gate all widens) |
npx fallow dead-code |
Unused code and circular dependencies (alias: check) |
npx fallow dead-code --trace src/file.ts:symbol |
Prove a symbol is unused before deleting it |
npx fallow dead-code --type-aware --symbol-impact src/file.ts:symbol |
Find exact consumers, affected files, and targeted tests for an export or Class.method |
npx fallow dupes |
Duplication; modes strict, mild (default), weak, semantic |
npx fallow similar-code |
Opt-in semantic function candidates from a pinned local model; inspect and verify before any refactor |
npx fallow health --score |
Complexity, 0 to 100 health score, hotspots; --css adds structural CSS analytics |
npx fallow fix --dry-run |
Preview auto-fixes; apply with npx fallow fix |
npx fallow guard src/file.ts |
Which boundary rules apply to a file before editing |
npx fallow security |
Opt-in security candidates; --gate new --changed-since <ref> fails only on introduced ones |
npx fallow explain <issue-type> |
Explain a rule without analyzing |
npx fallow recommend |
Detect the stack and propose a config; subjective choices stay open questions |
npx fallow doctor |
Read-only readiness checks for the root, config, workspaces, plugins, and optional type-aware companion |
npx fallow init |
Scaffold config; --agents scaffolds an AGENTS.md |
npx fallow migrate |
Migrate from knip, jscpd, or stylelint config |
npx fallow viz |
Interactive HTML map with Unused, Duplication, Architecture, Health, and static Security lenses, plus dependency, framework, styling, and feature-flag analysis |
npx fallow schema |
Machine-readable capability manifest (always JSON) |
| Command | Purpose |
|---|---|
fallow review --brief |
Advisory orientation brief over changed files; always exits 0 |
fallow inspect --file src/api.ts |
Evidence bundle for one file, or one symbol via --symbol src/api.ts:client |
fallow trace src/utils.ts:formatDate |
Symbol-level call chains: callers up, callees down |
fallow type-aware status |
Check whether the version-matched optional TypeScript companion is available |
fallow similar-code status |
Check the exact local companion and pinned-model readiness without reading project source |
fallow similar-code setup --local |
Explicitly download and verify the pinned local model |
fallow watch |
Re-run analysis on file changes (interactive use; agents should not run it) |
fallow flags |
Detect feature-flag patterns |
fallow suppressions |
Inventory of fallow-ignore markers |
fallow list |
Entry points, files, plugins, and boundaries (--boundaries) |
fallow workspaces |
Monorepo workspace discovery diagnostics |
fallow config |
Resolved configuration and which file provided it |
fallow decision-surface |
Ranked structural decisions a change embeds |
fallow impact |
Opt-in, local-only report of what fallow caught; --all spans repos |
fallow report --from results.json |
Re-render saved JSON as SARIF, CodeClimate, GitHub output, or GitHub/GitLab PR feedback without re-analyzing |
fallow ci ... |
PR/MR feedback helpers (comments, reviews, check runs) |
fallow ci-template gitlab --vendor |
Vendor the GitLab CI template for offline runners |
fallow agent install |
One-pass agent onboarding for Claude Code, Codex, and Cursor (status, uninstall, --dry-run) |
fallow hooks install --target git |
Managed pre-commit hook; --target agent writes agent-gate hooks |
fallow rule-pack init |
Declarative policy rule packs (list, test, schema) |
fallow plugin-check |
Dry-run an external framework plugin |
fallow config-schema |
JSON Schema for config; also plugin-schema and rule-pack schema |
fallow license activate --trial --email [email protected] |
Fallow Runtime licensing (status, refresh, deactivate) |
fallow telemetry status |
Opt-in telemetry, off by default (enable, disable, inspect --example) |
fallow coverage setup |
Runtime coverage workflow (analyze, upload-inventory, upload-source-maps, upload-static-findings) |
Default analysis stays Rust-native, syntactic, and independent of Node.js or
the TypeScript compiler. Add --type-aware when a cleanup or refactor depends
on exact TypeScript identity across aliases, re-exports, packages, or tests:
npx fallow dead-code --unused-class-members --type-aware --format json --quiet
npx fallow fix --type-aware --dry-run --format json --quiet
npx fallow dead-code --type-aware --symbol-impact src/api.ts:Client --format json --quiet
npx fallow dead-code --type-aware --symbol-impact src/repository.ts:UserRepository.save --format json --quiet
npx fallow health --type-aware --type-coupling --format json --quiet
This does not replace tsc --noEmit or Oxlint. Fallow does not emit compiler
diagnostics or duplicate local typed lint rules. It uses checker evidence only
for project-wide questions. It removes false positives caused by interfaces,
base classes, aliases, and re-exports. A class member becomes automatically
fixable only after every owning project reports complete negative evidence and
the exact declaration hash still matches. Otherwise Fallow keeps the finding
and explains the gap. See the type-aware analysis contract.
Per-command flags come from fallow schema (machine-readable) or the CLI reference.
For machine consumption, add --format json --quiet to any command, parse the JSON on stdout, and do not depend on whitespace. JSON is compact by default; add --pretty only for manual inspection. Exit 0 and 1 both mean the run succeeded (1 signals findings); exit 2 is a real error and still writes a JSON envelope to stdout. Branch on the code, treating 0 and 1 as success and 2 as failure, rather than blanket-suppressing with || true (which hides real errors from anything that checks the exit code).
--format |
What you get |
|---|---|
human (default) |
Terminal report with a Next: suggestion line |
json |
The machine contract: one compact typed JSON document on stdout (--pretty indents it) |
sarif |
GitHub Code Scanning and other SARIF consumers |
compact |
One grep-friendly line per finding |
markdown (alias md) |
Markdown report |
codeclimate (aliases gitlab-codequality, gitlab-code-quality) |
GitLab Code Quality report |
github-annotations |
Workflow-command annotations; render on fork PRs without a write token |
github-summary |
Job-summary markdown for $GITHUB_STEP_SUMMARY |
pr-comment-github, pr-comment-gitlab, review-github, review-gitlab |
Typed CI feedback from final refined findings; supported by type-aware check and audit runs |
badge |
shields.io-compatible SVG health badge; fallow health only (fallow health --format badge > badge.svg) |
human, json, sarif, compact, and markdown apply to every analysis command; the CI envelopes and badge belong to the command that produces them, as documented per format in the CI guide.
In CI, keep JSON as the provenance-bearing artifact and render presentation
surfaces from it. For example, analyze once with --format json -o results.json,
then run fallow report --from results.json --format pr-comment-gitlab and
fallow report --from results.json --format review-gitlab. This preserves
type-aware refinement, audit verdicts, and one authoritative finding set.
| Exit code | Meaning |
|---|---|
| 0 | Clean, or audit verdict pass or warn |
| 1 | Findings, or audit verdict fail (a normal outcome) |
| 2 | Validation or runtime error (JSON error envelope on stdout with --format json) |
| 3 | Requested resource unavailable: config --path found no config, or a license is unavailable or invalid |
| 4 | Runtime coverage sidecar is unavailable, unverifiable, protocol-incompatible, or terminated unexpectedly |
| 5 | Runtime coverage input could not be prepared or parsed |
| 6 | Runtime coverage sidecar reported an internal error |
| 7 | Network failure (license and cloud operations) |
| 8 | Security gate hit (fallow security --gate) |
| 10 | Coverage inventory or static-findings upload input or project validation failed |
| 11 | Coverage inventory or static-findings upload exceeded the server payload limit |
| 12 | Coverage inventory or static-findings upload authentication or authorization was rejected |
| 13 | Coverage inventory or static-findings upload failed after retries or returned another server error |
Rule severity maps onto exit codes: error fails CI (the default), warn exits 0, off skips the rule (rules reference).
The JSON contract, in short:
kind discriminator names the analysis that produced the documentactions[] with an auto_fixable flag, so a script knows which findings it can hand to fallow fixnext_steps[] suggestions are runnable as-is{"error": true, "message": "...", "exit_code": 2} on stdout, not as a stack traceTyped contracts ship with the npm package: import type { CheckOutput, FallowJsonOutput } from "fallow/types". The generated schema lives at docs/output-schema.json. The output format is CLI-only, via --format or FALLOW_FORMAT, and is never set in config; all environment variables are listed in docs/environment-variables.md.
The JSON contract and exit codes above are the agent interface.
{ "mcpServers": { "fallow": { "command": "npx", "args": ["fallow-mcp"] } } }
The MCP server covers analysis, audit, health, duplication, tracing, fix preview and apply, boundary guard checks, and target inspection; every tool documents its nearest CLI fallback, and a bounded read-only Code Mode sandbox composes analysis calls without filesystem or network access.
npx fallow agent install wires the detected harnesses (Claude Code, Codex, Cursor) in one pass: an AGENTS.md task map (plus a CLAUDE.md import), the fallow skill, the MCP server registration, and the commit/push gate. Every write is marked, --dry-run shows the plan, status and uninstall cover the same surfacesnpx fallow recommend --format json is the onboarding entry point: it returns the detected stack, a proposed config, and every decision with its tier and rationale, and it ships the subjective choices as ready-to-ask questions with options and tradeoffs. An agent authors .fallowrc.json from evidence and asks the user only what fallow will not decidenode_modules/fallow/skills/fallow (agent skills, companion repo fallow-skills)npx fallow init --agents scaffolds an AGENTS.md with a task-to-command matrix, and npx fallow hooks install --target agent gates git commit and git push on fallow audit ([hooks](https://docs.fallow.too