AI coding agents generate code at scale, but they don't perform codebase-level analysis. Building a module graph, tracing re-export chains, detecting duplication across thousands of files, scoring complexity hotspots: these require a dedicated tool. Fallow provides deterministic, exhaustive codebase analysis that agents call via CLI or MCP.
Every agent that can run shell commands can use fallow. The CLI is the primary interface. MCP is an optional structured layer on top.
Codebase analysis means building and traversing a graph, not reading files in a context window.
| What agents can't do | What fallow does |
|---|---|
| Build a complete module graph across thousands of files | Builds and caches the full graph in one pass |
| Track re-export chains through barrel files | Resolves export * chains through unlimited levels |
| Know if an export is used somewhere outside their context window | Exhaustively checks every import in the entire codebase |
| Detect code duplication across files they haven't seen | Suffix array algorithm catches clones across all files |
Determine which package.json dependencies are actually unused | Traces imports and script binaries to actual usage |
| Guarantee completeness (no missed files, no false negatives) | Deterministic: same input always produces same output |
Every AI coding agent can run shell commands. No MCP required:
# Full dead code analysis with JSON output
fallow dead-code --format json
# Only check changed files (great for agent PR workflows)
fallow dead-code --changed-since main --format json
# Find code duplication
fallow dupes --format json
# Preview what auto-fix would remove
fallow fix --dry-run --format json
# Apply fixes (agents should use --yes to skip confirmation)
fallow fix --yes --format json
# Detect feature flags and environment gates
fallow flags --format json
# List project info (plugins, entry points, file count)
fallow list --format json
Always use --format json when agents run fallow. JSON output is structured, machine-readable, and easy for LLMs to parse. The human-readable format works too, but JSON eliminates parsing ambiguity.
Consuming fallow's JSON output from TypeScript? import type { CheckOutput, HealthOutput, DupesOutput, AuditOutput } from "fallow/types" exposes the full output contract, generated from the same schema fallow uses internally. SchemaVersion is pinned to a literal at codegen time so major schema bumps fail to compile at your call sites instead of silently drifting.
For agents that support MCP (Model Context Protocol), fallow-mcp exposes analysis as structured tools. Agents get typed inputs and outputs instead of parsing CLI text.
The MCP server uses stdio transport and a hybrid adapter. Supported requests run in process, while command-owned options use a managed fallow CLI subprocess. Set FALLOW_BIN only when CLI-backed calls need a specific binary (defaults to fallow in PATH).
Install with cargo install fallow-mcp or grab a binary from GitHub Releases.
Register the server with the Claude Code CLI, which writes the configuration for you:
# Available in every project on this machine
claude mcp add fallow --scope user fallow-mcp
# This repository only, checked in for the whole team
claude mcp add fallow --scope project fallow-mcp--scope project creates .mcp.json in the repository root. fallow agent install writes the same entry for every detected harness, probing for a working launcher first. You can also write the file by hand:
{
"mcpServers": {
"fallow": {
"command": "fallow-mcp"
}
}
}Run claude mcp list to confirm fallow is registered.
Claude Code does not read mcpServers from .claude/settings.json. A server defined there is ignored without an error, so use .mcp.json or claude mcp add.
Installed fallow as a project devDependency? "command": "fallow-mcp" assumes the binary is on your PATH (a global install). When fallow lives in node_modules/.bin/, it is not on PATH, so the server fails to start with ENOENT. Launch it through your package manager's runner so the binary resolves from node_modules/.bin/:
{
"mcpServers": {
"fallow": {
"command": "npx",
"args": ["fallow-mcp"]
}
}
}Start the agent from the project root so the runner finds the local install. If you need an explicit fallow binary, keep setting FALLOW_BIN.
| Tool | Description |
|---|---|
analyze | Full dead code analysis (fallow dead-code --format json). Detects unused files, exports, types, dependencies, enum/class members, unresolved imports, unlisted dependencies, duplicate exports, circular dependencies, re-export cycles (barrel files that form a structural loop, silently breaking re-exports), boundary violations, framework component findings (unused props, emits, inputs, outputs, Svelte events, unrendered components, and unprovided injects), rule-pack policy violations (banned calls and banned imports declared via the rulePacks config key), stale suppressions, unused pnpm catalog entries, empty pnpm catalog groups, and unresolved pnpm catalog references (consumer package.json references a catalog that does not declare the package; pnpm install would fail). Private type leaks are opt-in via issue_types: ["private-type-leaks"]. |
check_changed | Incremental analysis of changed files (fallow dead-code --changed-since) |
security_candidates | Unverified local security candidates, not confirmed vulnerabilities (fallow security --format json). Read security_findings[] for category, CWE, severity, evidence, trace, optional reachability, blind-spot counters, and optional unresolved_callee_diagnostics samples for dynamic callee follow-up. severity is a review-priority tier, not a verified vulnerability verdict. Each finding also carries an agent-actionable candidate (source_kind/sink/boundary), where URL-category sinks may include url_shape (fixed-origin-dynamic-path or dynamic-origin), an optional taint_flow source-to-sink triple, and a stable finding_id (equal to the SARIF fingerprint) for cross-run correlation; there is no impact field (deciding exploitability is the agent's job). Set surface: true to include top-level attack_surface[] entries with defensive-boundary prompts for a verifier. Set gate to new for changed-line candidates or newly-reachable for candidates that became reachable from entry points; newly-reachable requires changed_since. reachability.untrusted_source_trace is module-level import context only and does not prove value flow; reachability.taint_confidence tiers each reachable candidate as arg-level (sink argument traces to a same-module source read, strong) or module-level (only the module is import-reachable from a source, weak), so tier from this field instead of the evidence text. Verify trace, reachability context, severity, and evidence before editing code. Supports root, config, workspace, paths, changed_since, changed_workspaces, surface, gate, no_cache, and threads; paths forwards repeated fallow security --file filters for finding anchors, trace hops, untrusted-source reachability trace hops, and unresolved-callee diagnostics. See Security agent verification for the verifier packet and verdict recipe. Inherits FALLOW_DIFF_FILE from the server environment for line-level diff scoping; raise FALLOW_TIMEOUT_SECS for large repos. |
inspect_target | Compose one evidence bundle for a file or exported symbol. File targets use target: { type: "file", file }; symbol targets use target: { type: "symbol", file, export_name }. Returns kind: "inspect_target", normalized target identity, trace_file, optional trace_export, file-scoped dead-code actions, duplication groups filtered to the file, complexity findings filtered to the file, and security candidates scoped to the file. Evidence sections carry status and scope; symbol targets warn when supporting evidence is file-scoped. Set the opt-in symbol_chain: true option to also attach the best-effort symbol-level call chain (the same data as fallow trace) as a symbol_chain evidence section; only meaningful for a symbol target, default off (best-effort, syntactic, off the ranked path). Supports root, config, production, workspace, no_cache, and threads; production applies to trace, dead-code, and health evidence only. Raise FALLOW_TIMEOUT_SECS for large repos. |
code_execute | Bounded read-only Code Mode for composing multiple fallow analysis calls in one JavaScript snippet. The snippet receives { fallow, root }, returns JSON-serializable data, and can call read-only helpers such as fallow.projectInfo, fallow.audit, fallow.checkHealth, and fallow.run(tool, params) for the same allowlist. Mutating fix tools are not exposed. The sandbox has no filesystem, network, imports, eval, Function, process, require, Deno, Bun, or shell access. Params: code, optional root, timeout_ms (capped at 30000), and max_output_bytes (capped at 4000000). |
find_dupes | Code duplication detection (fallow dupes --format json). Each clone group carries a stable fingerprint and numeric spread; near-miss groups also carry similarity. Pass near: true to include function-scoped near-miss clones. Use the fingerprint with trace_clone to inspect a group. Import declarations are excluded by default; pass ignore_imports: false to count them again. stats.clone_groups_ignored reports config-filtered groups, while stats.near_candidates_skipped signals bounded near-miss comparisons that were skipped. |
find_similar_code | Read-only semantic function discovery through the pinned local model (fallow similar-code --format json --quiet). Returns unverified candidates with provider and model provenance, completion, limits, skips, and cache accounting. Scope with files, workspace, changed_since, changed_workspaces, threshold, min_lines, or top. The score is not a probability or verdict. The tool never downloads a model. If setup is missing, ask the user to run fallow similar-code setup --local. |
inspect_similar_code | Reproduce one candidate_id and return bounded source, graph, ownership, churn, test, deterministic-duplication, and side-effect evidence. Read-only. Use it before judging a candidate and abstain when evidence is unavailable. The tool does not write verdicts or edit source. |
fix_preview | Dry-run auto-fix preview (fallow fix --dry-run --format json) |
fix_apply | Apply auto-fixes (fallow fix --yes --format json) |
guard | Report the architecture rules that apply to given files before editing them: boundary zone, allowed import zones, forbidden calls, and rule-pack policies. |
check_health | Complexity metrics, file health scores, hotspots, and refactoring targets (fallow health --format json). Set file_scores: true for maintainability index, hotspots: true for churn analysis, targets: true for ranked recommendations sorted by efficiency, trend: true for per-metric deltas against the most recent snapshot. Set complexity_breakdown: true to add a per-decision-point contributions[] array to each complexity finding (each else-if, nested if, boolean operator, loop, case, etc. with its source line and cyclomatic/cognitive weight) so you can explain WHY a function scored high and pinpoint which lines to refactor. Set css: true to add a css_analytics section: structural CSS slop that per-rule linters do not aggregate (specificity hotspots, !important density, deep nesting, design-token sprawl) plus cleanup candidates (unreferenced custom properties / @keyframes, dead Vue <style scoped> classes, unused @property / @layer, Tailwind arbitrary-value bypasses, Tailwind v4 @theme unused_theme_tokens, duplicate declaration blocks) and undefined-reference candidates, each with a read-only verification step in its actions[]. It also adds token_consumers, a reverse index of where each design token is consumed (per token a consumer_count plus a located consumers[] sample) so an agent can read a token's blast radius before changing it; it covers Tailwind v4 @theme tokens (kind theme-var / css-var / utility / apply) and CSS-in-JS token definitions: StyleX defineVars, vanilla-extract createTheme-family definitions, and PandaCSS defineTokens (token is binding-qualified; kind is js-member for member access and js-call for Panda token(...) calls). consumer_count is a static lower bound (a computed class name like bg-${c}, dynamic import strings, unresolved aliases, generated package state, or computed token access can still be invisible) and the field is descriptive context, not a finding (no actions[]). Opt-in because it reads project stylesheets and cross-checks source files. Standard CSS and Vue/Svelte/Astro standard <style> blocks are parsed structurally; Sass/Less sources are scanned only where fallow can stay conservative without expanding preprocessor semantics. Set churn_file to a fallow-churn/v1 JSON path to drive hotspots/ownership/targets from imported VCS history instead of git, for projects with no git repository (Yandex Arc, Mercurial, Perforce); the file is authoritative for the window, so since then only labels output. Set runtime_coverage to merge a V8 or Istanbul coverage dump; tune it with min_invocations_hot (default 100), min_observation_volume (default 5000), and low_traffic_threshold (default 0.001). Set group_by to owner, directory, package, or section to partition results: each group gets its own vital_signs, health_score, and optional coverage_source_consistency recomputed from the group's files (top-level metrics stay project-wide), SARIF results gain properties.group, CodeClimate issues gain a top-level group field. Findings include a bucketed coverage_tier (none/partial/high) and coverage_source for CRAP-triggered entries; summary.coverage_source_consistency reports whether those sources are uniform or mixed. Actions pick add-tests / increase-coverage when coverage can still clear CRAP, or refactor-function when cyclomatic >= maxCrap, see "Structured actions" below. |
check_runtime_coverage | Merge runtime-coverage data into the health report. Required coverage param accepts a V8 coverage directory, a single V8 coverage JSON, or an Istanbul coverage-final.json. A single local capture is free and runs without a license; continuous or multi-capture runtime monitoring (a V8 directory containing multiple JSON files) requires an active license JWT. Tunable via min_invocations_hot (default 100), min_observation_volume (default 5000), low_traffic_threshold (default 0.001), max_crap (default 30.0), top, and group_by. Protocol-0.3+ sidecars emit a summary.capture_quality block flagging short-window captures. Cloud runtime rows can expose resolutionStatus / mappingQuality on function-list JSON and resolution_status / mapping_quality in runtime-context JSON. Use the confidence table below before acting on file-level runtime signals. Can exceed the default 120s timeout on large dumps; raise FALLOW_TIMEOUT_SECS accordingly. Pick this over check_health when you have a coverage dump. |
get_hot_paths | Runtime-context slice over the same local runtime coverage pipeline. Same input schema and free-vs-paid contract as check_runtime_coverage; read runtime_coverage.hot_paths for production hot paths sorted by percentile and invocation count. |
get_blast_radius | Runtime-context slice for blast-radius review. Same input schema and free-vs-paid contract as check_runtime_coverage; read runtime_coverage.blast_radius for stable fallow:blast:<hash> IDs, caller counts, traffic-weighted caller reach, optional cloud deploy touch counts, and low/medium/high risk bands. |
get_importance | Runtime-context slice for production-importance review. Same input schema and free-vs-paid contract as check_runtime_coverage; read runtime_coverage.importance for stable fallow:importance:<hash> IDs, invocations, cyclomatic complexity, owner count, 0-100 score, and templated reason. |
get_cleanup_candidates | Runtime-context slice for cleanup review. Same input schema and free-vs-paid contract as check_runtime_coverage; read runtime_coverage.findings for safe_to_delete, review_required, low_traffic, and coverage_unavailable verdicts. |
get_token_blast_radius | Design-token blast radius from static analysis (free, no runtime dump). Runs fallow health --css --format json; read css_analytics.token_consumers for, per token, its defining site plus a consumer_count and a capped located consumers[] sample of {path,line,kind}. Covers Tailwind v4 @theme tokens (token is the ---prefixed custom property; kind theme-var / css-var / utility / apply) plus CSS-in-JS token definitions: StyleX defineVars, vanilla-extract createTheme / createThemeContract / createGlobalTheme, and PandaCSS defineTokens. StyleX and vanilla-extract consumers use binding-qualified dotted paths like vars.color.primary with kind js-member; PandaCSS consumers use token paths like tokens.colors.brand with kind js-call. A focused entry point so you do not need css=true on check_health. consumer_count is a static lower bound (a computed class name like bg-${c}, dynamic import strings, unresolved aliases, generated package state, or computed token access can still be invisible), so use it to size the impact of editing or renaming a token, not to decide deletion; the Tailwind dead-token verdict stays on unused_theme_tokens, and CSS-in-JS tokens have no dead-token finding (so a CSS-in-JS consumer_count of 0 is weaker). |
audit | Audit changed files for dead code, complexity, duplication, and styling (fallow audit --format json). Returns a verdict (pass/warn/fail). Set base to specify the comparison ref, gate to new-only or all, and include_entry_exports=true to also catch typos in entry-file exports (meatdata vs metadata). Set coverage to an Istanbul coverage-final.json path (and absolute coverage_root when paths need rebasing for CI / Docker checkouts) for accurate per-function CRAP scoring in the health sub-analysis. Styling analytics are included by default in audit, including styling_findings and css_analytics when the project has CSS or CSS-in-JS evidence. Set css_deep=false to skip project-wide styling reachability, or css_deep=true to force it back on when config disables it. Set runtime_coverage (V8 dir / V8 JSON / Istanbul JSON) to fold runtime-coverage findings into the same audit invocation; tune with min_invocations_hot (default 100). When FALLOW_DIFF_FILE or FALLOW_CHANGED_SINCE is set in the agent's env, runtime_coverage.verdict promotes hot-path-touched over cold-code-detected for PR-review contexts. |
decision_surface | Surface the few consequential structural decisions a change embeds (coupling, public API, dependency), each as a judgment question with the routed expert; ranked, capped, and signal_id-anchored. Reads the same graph-derived review brief as fallow review (the brief path of fallow audit). Returns the decision surface with exactly three shippable categories: coupling-boundary (a new cross-zone dependency edge), public-api-contract (a new exported public-API surface, or a changed contract consumed by modules outside this diff), and dependency (a new third-party dependency). Each decision is anchored to a signal_id fallow deterministically derived from the graph, ranked by consequence (blast radius x reversibility), paired with the routed expert (who to ask), and may carry previous_signal_id (the id the anchor had before a git mv, so a review surface can re-attach a prior comment across a rename). Each decision also carries a tradeoff clause (the named structural sacrifice stated as a fact, e.g. "Couples app to infra; N in-repo modules already depend on this anchor") and internal_consumer_count (the honest per-anchor count of in-repo modules outside the diff that already depend on it, the display number you read reversibility from, distinct from the ranking-only blast). Set base to specify the comparison ref and max_decisions to cap the surfaced decisions (default 4, clamped to a 3 to 5 band). The brief always exits 0; the verdict is carried informationally and never gates. |
fallow_explain | Explain one issue type without running analysis (fallow explain <issue-type> --format json). Returns rationale, example, fix guidance, and docs URL. |
project_info | Project metadata, including plugins, files, and entry points (fallow list --format json). Set entry_points, files, plugins, or boundaries to true to request specific sections. |
recommend | Recommend a project-tailored fallow config for cold-start onboarding (fallow recommend --format json). Read-only: from framework / workspace / tooling detection it returns a loader-validated proposed_config you can write as-is, plus a decisions[] list that classifies each setting as auto (decided from detection, applied silently), default (a disclosed, overridable default with a rationale), or taste (a genuinely subjective choice surfaced as an AskUserQuestion-shaped prompt with no baked-in answer). Detected TypeScript projects receive an informational typeAware.enabled decision with the opt-in command, cost boundary, and guide link; it is never written into proposed_config. root-only; writing no config at all is a valid outcome. |
feature_flags | Detect feature flag patterns in the codebase (fallow flags --format json). Identifies environment variable flags, SDK calls from common providers, and config object patterns. Set top to limit results. |
list_suppressions | List active fallow-ignore suppression markers grouped per file with line, kind, level, reason, and a stale cross-reference (fallow suppressions --format json). A read-only governance inventory for seeing what a clean verdict is hiding, not a gate: always exits 0 even when suppressions exist. Scope with workspace, changed_since (the natural pull-request review scope), or repeated file entries. Runs a full analysis, so raise FALLOW_TIMEOUT_SECS on large repos. |
list_boundaries | Architecture boundary zones and access rules (fallow list --boundaries --format json). Returns zone definitions, access rules, per-zone file counts, and logical_groups[] (pre-expansion autoDiscover parents with verbatim paths, discovered children, a status enum (ok / empty / invalid_path), summed file_count, optional authored_rule, optional fallback_zone cross-reference for the Bulletproof case, optional merged_from for duplicate parent declarations, optional original_zone_root echo for monorepo subtree scopes, and optional child_source_indices attribution for multi-path autoDiscover). Returns {"configured": false} if no boundaries are configured. |
trace_export | Trace why an export is used or unused (fallow dead-code --trace FILE:EXPORT_NAME --format json). Required file and export_name params. Returns file reachability, entry-point status, direct references, re-export chains, and a reason string. If export_name is a class / enum / store MEMBER rather than a top-level export, returns a member trace instead (member_name, member_kind, owner_export, owner_is_used) reporting the owning declaration's reachability and usage plus a pointer to the matching --unused-<kind>-members command; branch on field presence (export_name vs member_name). Use before deleting a supposedly-unused export or debugging an unused-class-member finding. |
trace_symbol | Trace exact TypeScript symbol references, namespaces, aliases, and re-export hops (fallow dead-code --type-aware --trace FILE:EXPORT --format json --quiet). Required file and export_name; optional type_aware_projects and type_aware_require (best-effort or complete). This adds semantic proof to Fallow's project-wide usage evidence without returning TypeScript compiler diagnostics or lint findings. |
symbol_impact | Return exact-symbol consumers, transitive affected files, and targeted tests for a TypeScript export (fallow dead-code --type-aware --symbol-impact FILE:EXPORT --format json --quiet). Required file and export_name; optional type_aware_projects and type_aware_require (best-effort or complete). Use it to plan a rename, deletion, or API change. It is advisory change-impact evidence, not a substitute for tsc or Oxlint. |
trace_file | Trace all graph edges for a file (fallow dead-code --trace-file PATH --format json). Required file param. Returns reachability, entry-point status, exports, imports-from, imported-by, and re-exports. Use to decide whether a file is isolated, barrel-only, or imported by live entry points. |
trace_dependency | Trace where a dependency is imported (fallow dead-code --trace-dependency PACKAGE --format json). Required package_name param. Returns importing files, type-only importers, total import count, used_in_scripts (true when invoked from package.json scripts or CI configs like .github/workflows/*.yml / .gitlab-ci.yml), and is_used (combined import + script signal, mirrors the unused-deps detector so build tools like microbundle or vitest invoked only via scripts are correctly classified as used). Use before removing a dependency or moving it between dependencies and devDependencies. |
trace_clone | Deep-dive a duplicate-code clone group (fallow dupes --trace <spec> --format json). Address it by exactly one of: file + line (a source location), or fingerprint (a dup:<id> from a prior find_dupes result). Returns the matched instance plus every clone group containing it. Each traced group carries its fingerprint, an extract-function suggestion, and an optional suggested_name. Supports mode, near, min_tokens, min_lines, threshold, skip_local, cross_language, and ignore_imports. Use the same near value as the originating find_dupes call when tracing a near-miss group. |
impact | Read the local, opt-in Fallow Impact value report (fallow impact --format json). Runs no analysis: reports current surfacing counts, the 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 (no config / no_cache / threads); the mutating enable / disable / default lifecycle is not exposed. The report carries enabled_source (project / user / default); on a project where tracking was never enabled it returns a populated {"enabled": false, ...} report (never {}), so an agent branches on enabled and enabled_source 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 there it returns an empty report and is not a CI metric. |
impact_closure | Trace the impact closure for one file (fallow dead-code --impact-closure <path> --format json). Returns the transitive affected-but-not-in-diff set plus coordination gaps for consumers of the file contract. Supports path, root, config, production, workspace, no_cache, and threads; use it as review-planning evidence, not proof that affected files are wrong. |
impact_all | Roll every tracked project on this machine into one cross-repo value report (fallow impact --all --format json). Runs no analysis: reads the per-project histories in the user config dir and returns kind: "impact-cross-repo" with project_count, tracked_count, unreadable_count, a totals roll-up summed over all tracked projects (including repos since deleted from disk), and a projects[] array. Each row carries a hashed project_key (never a filesystem path; always present), an optional human label (the repo's folder basename; omitted on rows from older stores, so fall back to project_key), last_recorded, and the same per-project report shape as impact. Use this for a portfolio view; use impact (with root) for one project. sort orders rows (recent default / resolved / contained / name); limit caps rows while totals still cover every project. Projects enabled but with no recorded history are counted but not listed. Read-only; the mutating enable / disable / default / reset lifecycle is not exposed. Local-developer signal: empty in CI, not a CI metric. |
Cloud runtime tools can include source-map confidence metadata when the response capabilities array contains function_identity_v2. Function list responses use resolutionStatus and mappingQuality; runtime-context responses use resolution_status and mapping_quality. These fields describe source-map confidence, not whether the function ran.
| Values | Meaning | Agent action |
|---|---|---|
resolved + high | The source map resolved the generated position to original source. | Trust the file path and line number. Reference the original source confidently. |
fallback + medium | A source map exists, but it did not cover this generated position. | Treat the file-level signal as approximate. Ask the developer to rebuild with denser source maps before making a precise edit. |
unresolved + low | No matching source map was uploaded for this bundle and commit. | Ask the operator to upload the source map before acting on file-level coverage signals. |
null + null | The row does not include source-map confidence metadata. | Treat the row as missing confidence metadata. Do not downgrade it to low without other evidence. |
{
"tool": "analyze",
"arguments": {
"production": true,
"issue_types": ["unused-exports", "unused-files"]
}
}Some tools accept additional parameters beyond the common root, config, no_cache, and threads:
| Tool | Parameter | Type | Description |
|---|---|---|---|
analyze | boundary_violations | bool | Convenience alias for issue_types: ["boundary-violations"] |
find_dupes | changed_since | string | Only report duplication in files changed since a git ref |
find_dupes / trace_clone | near | bool | Include function-scoped near-miss clones with small structural edits. Default false. |
find_dupes / trace_clone | min_occurrences | integer (≥ 2) | Minimum number of occurrences before a clone group is reported. Default 2. Raise to skip pair-only clones and focus on widespread copy-paste worth refactoring. JSON output gains stats.clone_groups_below_min_occurrences when the filter hides anything. |
find_similar_code / inspect_similar_code | threshold | number (0 to 1) | Model-specific discovery cutoff. It is not a probability or quality gate. |
find_similar_code / inspect_similar_code | min_lines / top | integer | Exclude tiny functions and cap returned candidates. |
find_similar_code / inspect_similar_code | files | string[] | Keep candidate pairs touching one of these root-relative files. |
inspect_similar_code | candidate_id | string | Required immutable candidate ID from find_similar_code. |
security_candidates | gate | string | new gates changed-line candidates; newly-reachable gates candidates that became reachable from entry points and requires changed_since. |
audit | gate | string | new-only gates only introduced findings; all gates every finding in changed files |
audit | css_deep | bool | Controls audit deep styling reachability. Omit it for the default project-wide styling pass, set false to skip project-wide styling reachability, or set true to force --css-deep when config disables it. |
audit / check_health | coverage | string | Path to Istanbul-format coverage-final.json for accurate per-function CRAP scores. Resolution is consistent on typed and CLI-backed routes: an explicit tool parameter wins, followed by FALLOW_COVERAGE, then health.coverage from config. |
audit / check_health | coverage_root | string | Absolute prefix to strip from file paths in coverage data before prepending the project root. Use when coverage was generated under a different checkout root in CI or Docker. Resolution is consistent on typed and CLI-backed routes: an explicit tool parameter wins, followed by FALLOW_COVERAGE_ROOT, then health.coverageRoot from config. |
analyze / check_changed / audit | include_entry_exports | bool | Also report unused exports in entry files. Catches typos in framework-convention exports (e.g. meatdata vs metadata). ORs with the includeEntryExports config value. |
fallow_explain | issue_type | string | Issue type token or rule id to explain |
project_info | entry_points | bool | Request detected entry points |
project_info | files | bool | Request all discovered source files |
project_info | plugins | bool | Request active framework plugins |
project_info | boundaries | bool | Request architecture boundary zones and rules |
analyze | group_by | string | Group output by owner (CODEOWNERS), directory (first path component), package (workspace), or section (GitLab CODEOWNERS [Section] headers, with owners metadata per group) |
All tools return structured actions arrays on every finding, enabling agents to programmatically apply fixes or suppressions:
analyze, check_changed): fix action (e.g. remove-export) + suppress action. Agents can use the auto_fixable flag to decide whether to call fix_apply or handle the suggestion manually. See the dead-code CLI reference for action type details.check_health, audit): complexity findings and styling findings carry an actions array. Complexity findings select their primary action with the CRAP/coverage formula keyed off coverage_tier, cyclomatic, and max_crap_threshold; possible action types include refactor-function, add-tests, increase-coverage, and suppress-line. Styling findings use styling-specific read-only verification and suppression actions. When --baseline/--save-baseline is passed OR health.suggestInlineSuppression: false, suppress-line is omitted and a top-level actions_meta: { suppression_hints_omitted: true, reason } breadcrumb is added (under health.actions_meta in combined-mode and audit output). Targets get apply-refactoring + suppress (when evidence exists). Hotspots get refactor-file + add-tests.find_dupes, audit): extract-shared + suppress actions on clone families and groups.audit): inherits actions from all three sub-analyses (dead code, health, duplication).next_steps[]Distinct from the per-finding actions[], the analyze, check_health, find_dupes, and audit responses (and combined output) carry a top-level next_steps[] array of read-only follow-up commands computed from the run's findings. Each entry is { id, command, reason }:
command is runnable as-is and never a fix or any other mutating command (fallow surfaces evidence; deciding and applying the change is the agent's job).id (setup, impact-report, trace-unused-export, trace-clone, complexity-breakdown, scope-workspaces, audit-changed) names a verification step to run before acting. When working through MCP, dispatch on the id to the matching tool (trace_export, trace_clone, check_health with complexity_breakdown: true, audit) or code_execute host call rather than shelling out the CLI command string.setup step (command: fallow schema) appears only on unconfigured, non-CI projects with findings. It has no mutating tool equivalent by design: read the manifest, then offer the guided-setup commands (fallow init --agents, fallow hooks install --target agent) to the user instead of running them unprompted. It disappears once a config exists or after fallow init --decline.impact-report step (command: fallow impact) carries the local value digest (commits contained at the gate, findings resolved) when impact tracking is enabled and has non-zero results. The cadence stamp lives in the impact store, so it is consistent across agents and sessions, and the step may appear even on a clean run. Relay the non-zero numbers to the user in one line.The array is deduplicated, priority-ordered, capped at three, and omitted when empty. Set FALLOW_SUGGESTIONS=off in the server env to suppress it.
value_schema on add-to-config actionsadd-to-config actions (emitted for unused-dependency, type-only-dependency, test-only-dependency, duplicate-export, and similar findings where the resolution is "add an entry to the fallow config") carry an optional value_schema field alongside value:
{
"type": "add-to-config",
"config_key": "ignoreDependencies",
"value": "autoprefixer",
"value_schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json#/properties/ignoreDependencies/items"
}
The value_schema URL is a JSON Pointer fragment into fallow's published schema.json. Agents that want to validate value before writing it into a user's config (for example, to reject a malformed { file, exports } rule object on the ignoreExports action) can fetch the linked schema and apply it locally. The field is strictly additive: actions that did not have a schema before continue to work without one, and agents that ignore the field keep working unchanged.
Besides tools, the server exposes read-only reference material as MCP resources: no subprocess, no analysis run, cacheable by URI (your client reads them through its own resource tool, for example ReadMcpResourceTool in Claude Code). Every payload is plain JSON; the server version travels in each content item's _meta.fallow_version, so a cached copy is self-describing and the schema resources stay valid strict JSON Schema. The catalogue is fixed at build time (no subscriptions, no list-changed notifications).
| Resource | Content |
|---|---|
fallow://tools | The tool manifest: name, one-line description, nearest CLI fallback, key parameters, license, and read-only flag for every tool |
fallow://issue-types | Every issue type with its command, category, config key, zero-config default severity, opt-in and fixable flags, docs URL, and explain URI |
fallow://explain | Index of every explainable issue type with a one-line summary and its fallow://explain/{issue_type} URI |
fallow://explain/{issue_type} | The explain document for one issue type, the same payload as fallow explain <issue-type> --format json |
fallow://task-matrix | The task-to-command matrix that also drives AGENTS.md and fallow --help: which read-only command to run before deleting, refactoring, committing, or scoping work |
fallow://schema/config, fallow://schema/plugin, fallow://schema/rule-pack | The JSON Schemas printed by fallow config-schema, fallow plugin-schema, and fallow rule-pack-schema |
{issue_type} accepts the bare id (unused-export), the namespaced id (fallow/unused-export), or the CLI filter spelling. Unknown URIs return a structured error whose data lists the known URIs; an unknown issue type lists the nearest matches. The numeric code is -32002 for clients on protocol versions before 2026-07-28 and -32602 from then on, so key on data rather than the code. The same catalogue is published as mcp_resources in fallow schema.
fallowRunning bare fallow (no subcommand) executes all analyses in one pass and returns a combined JSON object with dead_code, duplication, and health sections:
fallow --format json
This is the most efficient way for agents to get a full picture of the codebase in a single call. The combined output includes all issue types from dead code, duplication findings, and health metrics.
| Variable | Description |
|---|---|
FALLOW_BIN | Path to the fallow CLI binary for CLI-backed calls. The MCP server checks, in order: this env var, a sibling binary next to fallow-mcp, then fallow in PATH. It does not affect typed in-process calls. |
FALLOW_TIMEOUT_SECS | Deadline in seconds (default: 120) for both typed and CLI-backed calls. A timed-out typed call returns FALLOW_MCP_API_TIMEOUT; a timed-out CLI call kills the process tree and returns FALLOW_MCP_SUBPROCESS_TIMEOUT. Increase for very large codebases. |
The MCP server returns structured JSON errors from both adapter paths:
FALLOW_MCP_API_TIMEOUT code. The response is bounded, although in-process work may finish in the background.{"error": true, "message": "...", "exit_code": N} from stderr.FALLOW_MCP_SUBPROCESS_TIMEOUT code.