Auto-fix

fallow fix removes unused exports and unused dependencies from your codebase.

In agent workflows, fallow fix --yes --format json cleans up dead code non-interactively after code generation.

Always commit your changes before running fallow fix. Git lets you undo if needed.

  1. Preview changes

    Run a dry run to see exactly what would be removed without making any changes.

    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
    
    6 fixes available (5 exports, 1 dependency). Run without --dry-run to apply.
  2. Review the output

    Check that every proposed removal is safe. Pay attention to exports consumed by external packages or dynamic imports that fallow can't detect statically.

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

    After reviewing the preview, apply the changes. In interactive terminals, fallow asks for confirmation before writing.

    fallow fix

    In CI or non-TTY environments, use --yes to skip confirmation:

    fallow fix --yes

    Agents typically use fallow fix --yes --format json to apply fixes non-interactively. The JSON output confirms exactly what was changed, so the agent can verify the result.

  4. Verify the result

    Run your build and tests to confirm nothing broke.

    npm run build && npm test

What gets fixed

  • Unused exports: the export keyword is removed, keeping the declaration. For exported enums where the enum itself is never referenced outside its body in the file, the entire enum block is deleted.
  • Unused dependencies: removed from package.json when they are not imported by another workspace
  • Unused enum members: removed from the enum declaration. When every member of an exported enum is unused, the whole declaration is deleted in one pass instead of leaving behind an empty export enum X {} shell. Importers in other files now reference a name that no longer exists, so run your TypeScript build to find and clean them up.
  • Unused pnpm catalog entries: removed from pnpm-workspace.yaml by line-aware deletion. Object-form entries are removed as one block. By default, fallow also removes a contiguous YAML comment block immediately above the entry when it clearly belongs to that entry; configure this with fix.catalog.deletePrecedingComments ("auto", "always", or "never"). Other comments and stylistic choices in the file are preserved. When the last entry of a catalog group is removed, the header is rewritten to catalog: {} (or <name>: {}) instead of leaving bare catalog:, because pnpm rejects null-valued catalogs with Cannot convert undefined or null to object at install time. After a successful catalog edit fallow reminds you to run pnpm install so pnpm-lock.yaml stays in sync.

Auto-fix does not delete entire files or remove unused class members. Use fallow dead-code to find those and remove them manually.

auto_fixable is per-finding, not per action type

Every action in a finding's actions[] array carries an auto_fixable bool. The value is evaluated per finding, not per action type: the same action type may appear with auto_fixable: true on one finding and auto_fixable: false on another, depending on per-instance guards in the fallow fix applier.

Agents that filter on auto_fixable: true to decide what is safe to apply blindly must branch on the bool of each individual action, not on the action type alone.

Per-instance flips today:

  • remove-catalog-entry (unused-catalog-entries): true only when the finding's hardcoded_consumers array is empty. When a workspace package still pins a hardcoded version of the same package, fallow fix skips the entry to avoid breaking pnpm install, and the action is emitted with auto_fixable: false.
  • remove-dependency vs move-dependency (dependency findings): when the finding's used_in_workspaces array is non-empty, the primary action flips to move-dependency with auto_fixable: false because fallow fix will not remove a dependency that another workspace imports. On findings without cross-workspace consumers 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, which today means EITHER a fallow config file already exists OR no config exists and the working directory is NOT inside a monorepo subpackage. In the second case the applier creates .fallowrc.json using the same scaffolding fallow init emits and layers the new rules on top. false inside a monorepo subpackage with no workspace-root config, because the applier refuses to fragment per-package configs across the monorepo and points at the workspace root instead. Pass --no-create-config to fallow fix from pre-commit hooks, CI bots, and fallow watch to opt out of the create-fallback; the action then surfaces with auto_fixable: false and is skipped at apply time.
  • update-catalog-reference (unresolved-catalog-references): always false today. The catalog-switching applier is not yet wired; the field is non-singleton so future enablement does not require a schema change.

All suppress-line and suppress-file actions are uniformly auto_fixable: false.

JSON output

For scripting, CI, and agent workflows:

fallow fix --dry-run --format json
{
  "changes": [
    {
      "type": "remove-export",
      "file": "src/components/Card/index.ts",
      "symbol": "CardFooter",
      "line": 1
    },
    {
      "type": "remove-export",
      "file": "src/providers/trpc-provider/index.tsx",
      "symbol": "TRPCProvider",
      "line": 12
    },
    {
      "type": "remove-export",
      "file": "src/server/jobs/queue.ts",
      "symbol": "enqueueJobDelayed",
      "line": 61
    },
    {
      "type": "remove-export",
      "file": "src/server/jobs/queue.ts",
      "symbol": "sweepStuckProcessingJobs",
      "line": 206
    },
    {
      "type": "remove-export",
      "file": "src/server/jobs/queue.ts",
      "symbol": "getDeadLetterJobs",
      "line": 276
    },
    {
      "type": "remove-dependency",
      "package": "@trpc/react-query"
    }
  ],
  "summary": {
    "total_changes": 6,
    "exports_removed": 5,
    "dependencies_removed": 1
  }
}

See also