Skip to main content
The @fallow-cli/fallow-node package exposes the main fallow analyses as async Node.js functions. No subprocess, no JSON parsing, no binary lookup: the bindings reuse the CLI orchestration layer and return the same JSON report envelopes the CLI emits for --format json. Use them when you want to embed fallow inside another tool, a Node.js server, an editor extension, or a custom script that otherwise would shell out to the CLI.

Install

npm install @fallow-cli/fallow-node
The package is a native NAPI-RS addon with platform-specific optionalDependencies for macOS (arm64, x64), Linux (gnu + musl on arm64 and x64), and Windows (x64, arm64). npm picks the matching binary at install time. Node 18 or newer is required.

Basic usage

import {
  detectDeadCode,
  detectDuplication,
  computeHealth,
} from '@fallow-cli/fallow-node';

const deadCode = await detectDeadCode({
  root: process.cwd(),
  explain: true,
});

console.log(deadCode.summary.total_issues);
console.log(deadCode.unused_exports);
Every function returns a promise resolving to the same JSON envelope the CLI emits when called with --format json: a top-level kind discriminator on typed roots, schema_version, summary, relative paths, injected actions arrays, and (when explain: true) a _meta block with docs links. Set legacyEnvelope: true only while migrating consumers that still expect the previous root shape without kind.

API

All six functions are async and accept an optional options object. Unknown fields are ignored. Enum-like fields take lowercase CLI-style literals ("mild", "cyclomatic", "handle", "low").
FunctionCLI equivalentReturns
detectDeadCode(options?)fallow dead-code --format jsonDeadCodeReport
detectCircularDependencies(options?)fallow dead-code --circular-depsDeadCodeReport filtered to the circular_dependencies category
detectBoundaryViolations(options?)fallow dead-code --boundary-violationsDeadCodeReport filtered to the boundary_violations category
detectDuplication(options?)fallow dupes --format jsonDuplicationReport
computeComplexity(options?)fallow health --format jsonHealthReport
computeHealth(options?)fallow health --format jsonAlias for computeComplexity with a product-oriented name

Shared options

Every options object extends AnalysisOptions:
FieldTypeDefaultPurpose
rootstringprocess.cwd()Project root directory
configPathstringauto-discoverPath to .fallowrc.json / .fallowrc.jsonc / fallow.toml / .fallow.toml
noCachebooleanfalseSkip the extraction cache
threadsnumberCPU countParallelism; must be > 0
productionbooleanfalseProduction mode (excludes test/build files)
changedSincestringunsetScope analysis to files changed since a git ref
workspacestring[]unsetRestrict to named workspace packages (monorepo)
changedWorkspacesstringunsetRestrict to workspaces whose files changed since a git ref. Mutually exclusive with workspace.
explainbooleanfalseInject a _meta block with metric / rule documentation

Dead-code options

detectDeadCode, detectCircularDependencies, and detectBoundaryViolations accept the same superset, DeadCodeOptions. Setting any of the filter booleans below restricts the report to the selected issue types; leaving them all unset returns every category (the CLI’s default behavior).
FieldType
unusedFiles / unusedExports / unusedDeps / unusedTypesboolean
unusedEnumMembers / unusedClassMembersboolean
unresolvedImports / unlistedDepsboolean
duplicateExports / circularDeps / boundaryViolations / staleSuppressionsboolean
filesstring[]Restrict to specific files (like fallow dead-code path/to/file.ts)
includeEntryExportsbooleanReport unused exports on entry files

Duplication options

DuplicationOptions adds duplication-specific fields on top of AnalysisOptions:
FieldTypeDefault
mode"strict" | "mild" | "weak" | "semantic""mild"
minTokensnumber50
minLinesnumber5
thresholdnumber0 (no limit)
skipLocalbooleanfalse
crossLanguagebooleanfalse
ignoreImportsbooleanfalse
topnumberunset

Complexity / health options

ComplexityOptions mirrors the fallow health flag surface:
FieldTypeNotes
maxCyclomatic, maxCognitivenumber (0 to 65535)Per-function thresholds
maxCrapnumberCRAP score ceiling
topnumberTruncate rankings
sort"cyclomatic" | "cognitive" | "lines" | "severity"Finding sort order (default cyclomatic)
complexity, fileScores, coverageGaps, hotspots, targets, scorebooleanEnable individual report sections
ownership, ownershipEmailsboolean + "raw" | "handle" | "anonymized" | "hash"Ownership-aware hotspots
effort"low" | "medium" | "high"Filter refactoring targets
since, minCommitsstring, numberGit history window for hotspots
coverage, coverageRootstringIstanbul coverage file + root

Structured errors

Rejected promises throw a FallowNodeError (a plain Error with extra fields) that mirrors the CLI’s structured error surface:
import type { FallowNodeError } from '@fallow-cli/fallow-node';

try {
  await detectDeadCode({ root: '/does/not/exist' });
} catch (err) {
  const e = err as FallowNodeError;
  console.error(e.name);      // "FallowNodeError"
  console.error(e.message);   // "analysis root does not exist: ..."
  console.error(e.exitCode);  // 2
  console.error(e.code);      // "FALLOW_INVALID_ROOT"
  console.error(e.context);   // "analysis.root"
  console.error(e.help);      // optional remediation hint
}
The exit-code ladder matches the CLI: 0 ok, 2 generic / validation, 7 network (paid features only), etc.

When to use bindings vs the CLI

Use the bindingsUse the CLI
Embedding fallow in a long-running Node process (editor, devserver, CI runner)One-off invocation from a shell script or GitHub Action
You already have a Node runtime and want to skip subprocess + JSON parse overheadYou want zero runtime dependencies (native binary via npx fallow)
You need to call many analyses in sequence without re-initializingYou want CLI human output, progress bars, or interactive flags
You need typed access to the result envelope in TypeScriptYou consume the analysis from Rust, Python, Go, or any non-Node language
Both paths run the same analysis engine and return the same data. The bindings are not a reduced subset.

Limitations

  • The bindings wrap the one-shot analyses. Commands that write to the filesystem (fix, init, hooks install, hooks uninstall, audit --save-baseline, license activate, coverage setup) are not exposed.
  • No baseline or regression support yet. Use the CLI’s --baseline / --save-baseline flags for those workflows.
  • No watch mode. If you want incremental analysis, re-invoke the relevant function; fallow’s per-file cache makes repeat runs fast.
  • The API surface is young; breaking changes between minor versions are possible until it stabilizes.