Skip to content
Fallow home
All docs pages

Auto-fix

Remove unused exports, dependencies, enum members, and catalog entries with one command, and preview each change first. Works interactively, in CI, and in agent workflows.

fallow fix removes unused exports and unused dependencies from your codebase, so you do not have to delete them by hand.

In agent workflows, fallow fix --yes --format json removes dead code after code generation, with no prompt.

Always commit your changes before you run fallow fix. Then you can undo the fix with Git.

  1. Preview changes

    Run a dry run. It shows each removal and changes no files.

    fallow fix --dry-run
    Would remove export from src/components/Card/index.ts:1 `CardFooter`
    Would remove export from src/providers/trpc-provider/index.tsx:12 `TRPCProvider`
    Would remove export from src/server/jobs/queue.ts:61 `enqueueJobDelayed`
    Would remove export from src/server/jobs/queue.ts:206 `sweepStuckProcessingJobs`
    Would remove export from src/server/jobs/queue.ts:276 `getDeadLetterJobs`
    Would remove `@trpc/react-query` from dependencies in package.json
    Dry run complete. No files were modified.
  2. Review the output

    Make sure that each proposed removal is safe. Look for exports that external packages use, and for dynamic imports that fallow cannot detect statically.

    fallow fix --dry-run --format json
  3. Apply fixes

    When the preview is correct, apply the changes. In an interactive terminal, fallow asks for confirmation before it writes.

    fallow fix

    In CI or another non-TTY environment, use --yes to skip the confirmation:

    fallow fix --yes

    Agents usually apply fixes with fallow fix --yes --format json, which does not prompt. The JSON output lists each change, so the agent can verify the result.

  4. Verify the result

    Run your build and tests to make sure that nothing broke.

    npm run build && npm test

What gets fixed

  • Unused exports: fallow removes the export keyword and keeps the declaration. An exported enum that the file never references outside its own body is different: fallow deletes the entire enum block.

  • Unused dependencies: fallow removes them from package.json when no other workspace imports them.

  • Unused enum members: fallow removes them from the enum declaration. When every member of an exported enum is unused, fallow deletes the whole declaration in one pass, so no empty export enum X {} shell stays behind. Importers in other files then reference a name that no longer exists. Run your TypeScript build to find and fix them.

  • Duplicate exports: fallow adds ignoreExports rules to your fallow config file. When no config exists outside a monorepo subpackage, it creates .fallowrc.json. Pass --no-create-config to turn off this step.

  • Unused pnpm catalog entries: fallow removes them from pnpm-workspace.yaml line by line. It removes an object-form entry as one block. Fallow keeps the other comments and the style of the file, with these exceptions:

    • By default, fallow also removes a contiguous YAML comment block directly above the entry when that block clearly belongs to the entry. Set this with fix.catalog.deletePrecedingComments ("auto", "always", or "never").
    • When fallow removes the last entry of a catalog group, it rewrites the header to catalog: {} (or <name>: {}), not to a bare catalog:. pnpm rejects a null-valued catalog at install time with Cannot convert undefined or null to object.

    After a successful catalog edit, fallow reminds you to run pnpm install, so that pnpm-lock.yaml stays in sync.

Auto-fix does not delete entire files. It removes a class method only when two conditions are true: type-aware analysis gives complete evidence that the method is unused, and the declaration still matches the analyzed source. Review other class members manually.

Incomplete analysis

Sometimes fallow cannot read or fully parse a source file, or discovery skips source files. The affected findings then have reachability_caveats, and workspace_diagnostics lists the files and the reasons. You still see the finding, but fallow does not offer its removal in these places:

  • fallow fix
  • Editor quick fixes
  • MCP fixes
  • One-click review suggestions

Caveats can apply to unused files, exports, types, dependencies, enum members, and class members. An import that fallow did not see can point outside the affected file, so a caveat can apply across the project. Fix the cause of the diagnostic and run the analysis again before you apply the proposed removal. A type-aware result does not override incomplete source evidence.

auto_fixable is per-finding, not per action type

Each action in the actions[] array of a finding has an auto_fixable bool. Fallow sets the value per finding. The same action type can have auto_fixable: true on one finding and auto_fixable: false on another. The guards that the fallow fix applier runs on each instance decide the value.

An agent that uses auto_fixable: true to find actions that are safe to apply without review must check the bool of each action. The action type alone is not enough.

These actions can change per instance:

  • remove-catalog-entry (unused-catalog-entries): true only when the hardcoded_consumers array of the finding is empty. When a workspace package still pins a hardcoded version of the same package, fallow fix skips the entry so that pnpm install does not break. The action then has auto_fixable: false.

  • remove-dependency vs move-dependency (dependency findings): when the used_in_workspaces array of the finding is not empty, the primary action changes to move-dependency with auto_fixable: false. fallow fix does not remove a dependency that another workspace imports. When no other workspace uses the dependency, the action stays remove-dependency with auto_fixable: true.

  • add-to-config for ignoreExports (duplicate-exports): true when fallow fix can safely apply the action. Today that means one of these:

    • A fallow config file already exists.
    • No config exists, and the working directory is NOT inside a monorepo subpackage. The applier then creates .fallowrc.json with the same content that fallow init writes, and adds the new rules to it.

    The value is false inside a monorepo subpackage that has no config at the workspace root. The applier does not split the configuration into one file for each package. It points you to the workspace root instead. From pre-commit hooks, CI bots, and fallow watch, pass --no-create-config to fallow fix to turn off config creation. The action then has auto_fixable: false, and fallow skips it when it applies fixes.

  • update-catalog-reference (unresolved-catalog-references): always false today. The applier that switches catalogs does not exist yet. The field can vary per finding, so a later release can enable it without a schema change.

All suppress-line and suppress-file actions have auto_fixable: false.

JSON output

For scripts, CI, and agent workflows, use JSON output:

fallow fix --dry-run --format json
{
  "dry_run": true,
  "fixes": [
    {
      "type": "remove_export",
      "path": "src/greet.ts",
      "line": 2,
      "name": "unusedGreeting"
    }
  ],
  "total_fixed": 0,
  "skipped": 0,
  "skipped_content_changed": 0,
  "skipped_mixed_line_endings": 0,
  "skipped_low_confidence_exports": 0,
  "skipped_low_confidence_dependencies": 0,
  "skipped_low_confidence_members": 0
}

fixes lists the proposed actions. In a dry run, total_fixed stays at 0 because fallow changes no files. Paths are relative to the project root.

See also