fallow-rs/Fallow - Codebase Intelligence
Deterministic codebase intelligence for TypeScript/JavaScript in CI: quality, PR risk, hotspots, duplication, architecture.
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jul 10, 2026
- License
- MIT
Pinned Snippet
uses: fallow-rs/fallow@c9326d9395c0b46f4077290473060b3e950b6e8c # v3.3.0tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| command | Command to run: dead-code (unused code), dupes (code duplication), health (complexity), audit (changed-file quality gate), security (security candidates), fix (auto-remove unused code). Default runs all analyses. Legacy alias: check = dead-code. | no | "" |
| root | Project root directory | no | . |
| config | Path to config file (.fallowrc.json, .fallowrc.jsonc, fallow.toml, or .fallow.toml) | no | — |
| format | Output format (human, json, sarif, compact, markdown, codeclimate, pr-comment-github, pr-comment-gitlab, review-github, review-gitlab, badge) | no | sarif |
| sarif | Upload SARIF to GitHub Code Scanning. Available on public repos (free) and private or internal repos with GitHub Advanced Security. Requires permissions: security-events: write. | no | false |
| production | Production mode: exclude test/dev files, only analyze start/build scripts | no | false |
| production-dead-code | Combined mode only: run dead-code analysis in production mode | no | false |
| production-health | Combined mode only: run health analysis in production mode | no | false |
| production-dupes | Combined mode only: run duplication analysis in production mode | no | false |
| fail-on-issues | Exit with code 1 if issues are found | no | true |
| changed-since | Only report issues in files changed since this git ref (requires fetch-depth: 0) | no | — |
| auto-changed-since | Automatically scope analysis to changed files in PR context using the base SHA (requires fetch-depth: 0). Ignored when changed-since is explicitly set. | no | true |
| baseline | Path to baseline file for comparison | no | — |
| save-baseline | Save current results as a baseline file | no | — |
| version | Fallow version override. When omitted, the action uses the project package.json fallow dependency spec if present, otherwise latest. Pin a current fallow version so Ed25519 + SHA-256 binary verification can run. | no | "" |
| args | Additional arguments to pass to fallow (space-separated) | no | "" |
| artifacts-dir | Directory for generated action artifacts such as fallow-results.json, fallow-results.sarif, fallow-stderr.log, and fallow-analysis-args.sh. Relative to the workflow workspace. | no | . |
| comment | Post results as a PR comment and Fallow Check Run (requires pull-requests: write for the comment and checks: write for the check) | no | false |
| github-token | GitHub token for PR comments and SARIF upload | no | ${{ github.token }} |
| branded-token | Post PR comments and reviews as the Fallow app (branded) when the workflow grants `permissions: id-token: write`. Set to false to always post with github-token. Falls back to github-token automatically when id-token is unavailable. | no | true |
| broker-url | Base URL of the Fallow token broker used to mint the branded app token. Defaults to Fallow Cloud. | no | https://api.fallow.cloud |
| annotations | Emit findings as inline PR annotations via workflow commands (no Advanced Security required). On fallow >= 3.4.2 the action renders these natively via `fallow report --format github-annotations`; older binaries fall back to the bundled jq renderers, and version: latest users flip to the native path silently. The step log line "fallow: annotations rendered via native github-annotations" (or "via jq fallback") tells you which renderer ran. | no | true |
| review-comments | Post findings as inline PR review comments with rich markdown formatting (code blocks, tables, links, suggestions). Creates a single review per run. Automatically disables plain-text annotations when enabled. | no | false |
| review-guidance | Append collapsed "What to do" guidance blocks to inline review comments. Requires review-comments: true. | no | false |
| max-annotations | Maximum number of inline annotations to emit (default: 50). On the native path the action applies this cap to the rendered stream (GitHub itself displays at most 10 annotations per type per step). | no | 50 |
| max-comments | Maximum number of inline review comments + items in the sticky details table (default: 50). Mirrors max-annotations for the typed pr-comment / review formats. | no | 50 |
| comment-layout | Sticky PR comment layout: default, compact, gate-only, or details. Use gate-only when a native Check Run is the primary PR surface. | no | default |
| comment-id | Sticky-comment marker id, embedded in the HTML comment that identifies fallow's comment for upsert. Defaults to 'fallow-results', auto-suffixed with the workspace name when running scoped to a single workspace package. | no | "" |
| summary-scope | Sticky PR summary comment scope: 'all' (default, include project-level dependency/catalog/override findings even when their anchor line is outside the diff) or 'diff' (apply the diff filter to those findings too). Does not affect inline review comments. If the diff file is unavailable, fallow reports all findings. | no | all |
| diff-filter | Diff-aware finding filter: 'added' (default, only findings on PR-added lines), 'diff_context' (added lines plus surrounding context), 'file' (any file touched by the PR), 'nofilter' (every finding). | no | added |
| diff-file | Path to a unified-diff file. When set (directly OR derived by the analyze step from `gh pr diff` / `git diff --unified=0`), fallow narrows source-anchored findings to lines inside an added hunk; project-level findings (unused deps, catalog entries, dependency overrides) bypass the analysis filter. Sticky summary comments can opt into filtering project-level findings too with `summary-scope: diff`; inline review comments stay line-scoped. Also drives line-level scoping of the runtime-coverage `hot-path-touched` verdict. When both `diff-file` and `changed-since` are set, the diff filter wins for line-level filtering and `changed-since` still scopes file discovery; fallow logs a one-line stderr note. The analyze step propagates the resolved path via $GITHUB_ENV so the comment / review steps reuse the same file. | no | "" |
| api-retries | Maximum HTTP retry attempts for fallow ci reconcile-review and the bash gh-api wrappers. Defaults to 3. | no | 3 |
| api-retry-delay | Floor delay in seconds between rate-limited retries. Server-supplied Retry-After overrides this when present. Defaults to 2. | no | 2 |
| dupes-mode | Detection mode for dupes command (strict, mild, weak, semantic) | no | mild |
| min-tokens | Minimum token count for a clone (dupes command) | no | — |
| min-lines | Minimum line count for a clone (dupes command) | no | — |
| threshold | Fail if duplication exceeds this percentage (dupes command, 0 = no limit) | no | — |
| skip-local | Only report cross-directory duplicates (dupes command) | no | false |
| cross-language | Strip TypeScript type annotations for TS<->JS clone matching (dupes command) | no | false |
| ignore-imports | Exclude import declarations from clone detection (dupes command) | no | false |
| workspace | Scope output to one or more workspaces. Supports exact package names, globs matched against name and workspace path (apps/*, @scope/*), and !-prefixed negations. Comma-separated values ('web,admin') or a single pattern. | no | — |
| changed-workspaces | Git-derived monorepo scoping: scope output to workspaces containing any file changed since REF (e.g., 'origin/main'). Auto-derives the workspace set from git diff so CI jobs don't maintain a hand-written list. Requires git history (fetch-depth: 0). Mutually exclusive with 'workspace'. A missing ref or non-git directory is a hard error (exit 2) rather than silent full-scope fallback. | no | — |
| max-cyclomatic | Maximum cyclomatic complexity threshold (health command, default: 20) | no | — |
| max-cognitive | Maximum cognitive complexity threshold (health command, default: 15) | no | — |
| max-crap | Maximum CRAP score threshold (health and audit commands, default: 30.0). Functions meeting or exceeding this score are reported alongside complexity findings. Pair with coverage data for accurate per-function scoring. | no | — |
| coverage | Path to Istanbul coverage-final.json data for accurate CRAP scoring (health, audit, and bare command). | no | — |
| runtime-coverage | Path to paid runtime coverage input for the health command: a V8 coverage directory, V8 JSON file, or Istanbul coverage-final.json | no | — |
| coverage-root | Rebase Istanbul file paths before matching coverage or runtime coverage input (health and audit commands) | no | — |
| min-invocations-hot | Hot-path threshold for runtime coverage findings (health command, default: 100) | no | — |
| min-observation-volume | Minimum observation volume required for high-confidence runtime coverage verdicts (health command) | no | — |
| low-traffic-threshold | Fraction of total trace volume below which an invoked function is classified as low_traffic instead of active (health command) | no | — |
| top | Show only the N worst offenders (health and dupes commands) | no | — |
| sort | Sort order for health results: cyclomatic (default), cognitive, lines, or severity (health command) | no | — |
| file-scores | Compute per-file maintainability index (health command) | no | false |
| hotspots | Identify files that are both complex and frequently changing (health command) | no | false |
| targets | Show ranked refactoring recommendations (health command) | no | false |
| complexity | Show only complexity findings section (health command) | no | false |
| since | Git history window for hotspot analysis: durations (6m, 90d, 1y) or ISO dates (health command) | no | — |
| min-commits | Minimum commits for a file to appear in hotspot ranking (health command, default: 3) | no | — |
| score | Compute health score (0-100 with letter grade). Enables the health delta header in PR comments. Works with health and bare command (all analyses). | no | false |
| min-severity | Only fail for findings at or above this severity (moderate, high, critical). Use "critical" to only fail on critical complexity findings. | no | — |
| save-snapshot | Save vital signs snapshot to .fallow/snapshots/ for trend tracking. Use actions/cache to persist across runs. Provide a path or leave empty for default. Works with health and bare command. | no | — |
| trend | Compare current metrics against the most recent saved snapshot and show per-metric deltas. Requires a previous snapshot from save-snapshot. Works with health and bare command. | no | — |
| issue-types | Comma-separated issue types to report (dead-code command). Valid: unused-files, unused-exports, unused-types, unused-deps, unused-enum-members, unused-class-members, unresolved-imports, unlisted-deps, duplicate-exports, circular-deps | no | — |
| include-entry-exports | Report unused exports in entry files instead of auto-marking them as used. Catches framework export typos. Applied to dead-code analysis; also configurable persistently via includeEntryExports in your fallow config. | no | false |
| gate | Audit verdict gate: new-only (default) fails only introduced findings, all fails on every finding in changed files. | no | — |
| security-gate | Security regression gate: new fails on candidates introduced on changed lines, newly-reachable fails on existing candidates that became reachable from entry points. | no | — |
| dead-code-baseline | Path to a dead-code baseline for the audit command. | no | — |
| health-baseline | Path to a health baseline for the audit command. | no | — |
| dupes-baseline | Path to a duplication baseline for the audit command. | no | — |
| fail-on-regression | Exit with code 1 if issue counts regressed compared to baseline (dead-code command) | no | false |
| tolerance | Allowed regression tolerance before failing (e.g. "2%" or "5") (dead-code command) | no | 0 |
| regression-baseline | Path to regression baseline file for comparison (dead-code command) | no | — |
| save-regression-baseline | Save current results as a regression baseline file (dead-code command) | no | — |
| dry-run | Preview changes without modifying files (fix command, default: true for CI safety) | no | true |
| no-cache | Disable incremental parse cache (force full re-parse of all files) | no | false |
| threads | Number of parser threads (default: available CPU cores) | no | — |
| only | Run only these analyses when no command is specified (comma-separated: dead-code,dupes,health) | no | — |
| skip | Skip these analyses when no command is specified (comma-separated: dead-code,dupes,health) | no | — |
Outputs
| name | description |
|---|---|
| results | Path to JSON results file |
| sarif | Path to SARIF results file |
| issues | Number of issues (dead-code), clone groups (dupes), security candidates (security), introduced findings counted by the audit verdict (audit), or fixes proposed/applied (fix). Audit count is gate-aware: with `gate: new-only` (default) it sums attribution.*_introduced; with `gate: all` it sums summary.* totals. Security count is gate-aware when `security-gate` is set. For audit, prefer `outputs.verdict` for severity-aware gating. |
| verdict | Audit verdict (pass/warn/fail). Empty when command is not audit. The threshold step gates on this for audit so warn-tier findings do not fail CI. |
| gate | Audit gate (new-only/all) or security gate (new/newly-reachable) that was applied. Empty when no gate ran. |
| changed-files-unavailable | true when the analyze step could not enumerate PR-changed files (transient GitHub API failure, expired token, missing permissions); false on the happy path. Always emitted, regardless of whether changed-since was requested. Gate on this in downstream workflow steps to detect when analysis ran unscoped vs scoped. |
| post-skipped-reason | Reason the Post review comments step skipped posting (pagination_failure / none). Set to pagination_failure only when the inline-review POST was actually aborted to avoid duplicate threads (multi-comment dedup lookup failed). Empty when the Post review comments step did not run. |
| dedup-lookup-failed | true when a dedup lookup failed on the Post PR comment or Post review comments step. Distinct from post-skipped-reason: the summary-only paths post a fresh comment anyway (potential duplicate) when their lookup fails, while the multi-comment review path aborts. Gate on this to detect either degraded state. Resolves to "true" if EITHER step reported a failure, "false" otherwise. |