> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fallow.tools/llms.txt
> Use this file to discover all available pages before exploring further.

# Adopt Fallow in an existing repo

> Bring an existing TypeScript or JavaScript codebase to a clean Fallow policy, then keep new changes clean with fallow audit. Drive the cleanup with an AI agent.

This guide is for repositories that already have backlog: unused code, duplicates, complexity hotspots, and existing exceptions.

By the end of this guide you will have:

* a repo-level Fallow policy encoded in config
* dead code fixed or intentionally modeled
* duplication at or below your chosen threshold
* complex functions refactored or consciously widened with a written justification
* `fallow audit` enforcing the same policy on changed files

## Repo clean vs PR clean

These are different goals. Both matter. Do them in order.

<CardGroup cols={2}>
  <Card title="Repo clean (this guide)" icon="broom">
    Full-repo analysis to understand and clean the whole codebase.
    Use `fallow`, `fallow dead-code`, `fallow dupes`, and `fallow health`.
  </Card>

  <Card title="PR clean" icon="shield-check" href="/cli/audit">
    Changed-files gate that enforces the policy on every PR.
    Use `fallow audit` after the repo is clean.
  </Card>
</CardGroup>

Start with repo clean. Then turn on PR clean.

## Before you start

<CardGroup cols={2}>
  <Card title="Coming from knip?" icon="right-left" href="/migration/from-knip">
    Run `fallow migrate` first to port your knip config, then follow this guide.
  </Card>

  <Card title="Large monorepo?" icon="folder-tree" href="/configuration/workspaces">
    Apply this flow per workspace package. Use `fallow --workspace <name>` and a shared root config.
  </Card>
</CardGroup>

## 1. First run: get the whole picture

From your project root:

```bash theme={null}
npx fallow
```

Then the focused commands you will use during cleanup:

```bash theme={null}
npx fallow dead-code          # Cleanup candidates
npx fallow dupes              # Repeated logic
npx fallow health             # Complexity and refactor targets
```

If you do not yet have a config file:

```bash theme={null}
fallow init
```

`fallow init` auto-detects your project structure (package manager, workspaces, frameworks) and generates a tailored starting config. It also adds `.fallow/` to your `.gitignore`.

## 2. Decide the project policy before triage

Do not start by suppressing findings one by one. That path turns into an ever-growing list of inline exceptions and no coherent policy.

<Info>
  Not the policy owner? Run section 3 first on a branch, then bring the findings into the policy discussion. Fallow output is a good forcing function for the "what do we actually care about" conversation.
</Info>

First decide, as a team:

* what counts as a real entry point (workers, scripts, route files, dynamically loaded modules)
* which files are generated or out of scope
* which packages are public APIs that ship exports outside the repo
* which dependencies are runtime-provided or intentionally retained
* which health thresholds you actually want to enforce
* whether duplication should warn or fail

A reasonable starting point:

```jsonc theme={null}
{
  "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
  "ignorePatterns": ["**/*.generated.ts", "**/*.d.ts"],
  "rules": {
    "unresolved-imports": "error",
    "unlisted-dependencies": "error",
    "unused-exports": "warn"
  }
}
```

Rules you do not list inherit their defaults. Health thresholds default to `maxCyclomatic: 20` and `maxCognitive: 15`; override in a `health` block only when your repo's realistic baseline differs.

<Tip>
  Use `warn` during rollout when you need visibility without blocking CI. Promote rules to `error` as the backlog shrinks. See the [rules reference](/configuration/rules) for every issue type and severity.
</Tip>

## 3. Work findings in the right order

Use this order for most existing repos. Each step removes noise that would otherwise distort the next step.

<Steps>
  <Step title="Fix unresolved imports and unlisted dependencies">
    High confidence, low debate. These are real bugs waiting to happen and should be cleared first.

    ```bash theme={null}
    npx fallow dead-code --unresolved-imports
    npx fallow dead-code --unlisted-deps
    ```
  </Step>

  <Step title="Delete unused files">
    Unreachable files are usually safe cleanup. Use `fallow list --entry-points` to sanity-check reachability before deleting anything you are unsure about.

    ```bash theme={null}
    npx fallow dead-code --unused-files
    npx fallow list --entry-points
    ```
  </Step>

  <Step title="Remove unused dependencies">
    Remove dead packages early. This reduces noise in later steps and speeds up installs.

    ```bash theme={null}
    npx fallow dead-code --unused-deps
    ```
  </Step>

  <Step title="Clean up unused exports, types, enum members, and class members">
    Usually the biggest category. Fix real dead code. Model intentional API surface with visibility tags or config instead of suppressing it. Hand this step to an agent using the [prompt in section 8](#8-clean-up-with-an-agent): the findings are mechanical but the decisions (delete vs. mark `@public` vs. add to `entry`) benefit from code-aware judgement.

    ```bash theme={null}
    npx fallow dead-code --unused-exports --unused-types
    ```

    Add `--unused-enum-members` and `--unused-class-members` when you want to focus on those categories explicitly. See the [`fallow dead-code` reference](/cli/dead-code) for every filter flag.
  </Step>

  <Step title="Consolidate duplication">
    Merge repeated logic into shared helpers. Only ignore generated or template-heavy files when the duplication is genuinely intentional.

    ```bash theme={null}
    npx fallow dupes
    npx fallow dupes --mode semantic   # also catch renamed-variable clones
    ```
  </Step>

  <Step title="Split health hotspots">
    `fallow health` output includes Hotspots and Targets sections that rank the worst offenders. Use those to prioritize. Do not bike-shed every file above the mean.

    ```bash theme={null}
    npx fallow health
    ```
  </Step>
</Steps>

## 4. Match the reason to the right mechanism

Do not default to inline suppression. Pick the mechanism that matches the reason.

### External or public API

Exports consumed outside the repo (published libraries, SDKs, public packages).

Prefer, in order:

* `@public`, `@internal`, `@beta`, `@alpha` JSDoc visibility tags on the export
* [`publicPackages`](/configuration/overview#publicpackages) as the coarse switch for "this whole package is external API"
* [`ignoreExports`](/configuration/overview#ignoreexports) only when file-level or export-level exceptions cannot be expressed any other way

`publicPackages` and visibility tags are complementary, not alternatives: `publicPackages` marks the package as externally consumed; `@public`/`@internal` tags distinguish public API from internal helpers that happen to be exported for cross-file use.

### Framework or runtime-discovered entry points

Files your framework or runtime invokes but no other module imports directly (workers, CLI scripts, route files, plugin modules).

Prefer, in order:

* built-in plugin detection (Next.js, Vite, NestJS, Remotion, and [dozens more](/frameworks/built-in) are handled out of the box)
* [`entry`](/configuration/overview#entry) for project-specific entry globs
* [`dynamicallyLoaded`](/configuration/overview#dynamicallyloaded) for code pulled in through reflection, manifests, or dynamic imports
* `fallow list --entry-points` to inspect what Fallow already considers reachable

### Generated or vendored files

Files produced by a build step, code generator, or vendored third-party bundle.

Prefer:

* [`ignorePatterns`](/configuration/overview#ignorepatterns) to exclude them from analysis entirely
* `health.ignore` when the noise is health-only and dead-code analysis should still run
* duplication configuration for clone-heavy generated code

### Runtime-provided or intentionally retained dependencies

Packages installed for runtime usage only (no static import), CLI tools, or peer dependencies.

Prefer:

* [`ignoreDependencies`](/configuration/overview#ignoredependencies) with the exact package names

### One-off intentional unused export

An export you want to keep around deliberately (compatibility shims, future API).

Prefer:

* `/** @expected-unused */` on the export

<Tip>
  `@expected-unused` is self-cleaning. Unlike inline `fallow-ignore` comments, Fallow tracks the tag for staleness: the moment the export becomes imported, the tag is reported as a stale suppression so you can remove it. Use it liberally for shims and future API surface.
</Tip>

### One-off false positive

A specific site where Fallow is wrong and no config rule captures the reason cleanly.

Prefer:

* `// fallow-ignore-next-line <issue>` on the line above
* `// fallow-ignore-file <issue>` only when the whole file is truly exceptional

### Repo-wide policy change

The project genuinely has a different standard for a whole category.

Prefer:

* `rules`, `health`, duplication thresholds, or `overrides` blocks

Do this only when it reflects a real team policy, not to hide a few ugly hotspots.

<Info>
  See [suppression](/configuration/suppression) for the full decision tree and examples, and [configuration overview](/configuration/overview) for every key.
</Info>

## 5. Keep exceptions narrow and reviewable

Narrow exceptions are an asset. Broad exceptions are a debt.

Good:

* a single `@public` export on a library entry point
* one `ignoreDependencies` entry for a runtime-provided package
* one `entry` pattern for worker scripts
* one file-level generated-code ignore with a comment explaining why

Bad:

* broad `ignorePatterns` that silently exclude half the repo
* repeated inline suppressions that could be one config rule
* raising global `health.maxCyclomatic` to hide a handful of hotspots (acceptable only when the new threshold reflects a thought-through project standard with written justification)

If you cannot explain an exception in one sentence, it is probably the wrong mechanism.

## 6. Define done

Work in two stages. Most teams ship `fallow audit` at the end of stage 1 and finish stage 2 over the following weeks.

### Stage 1: good enough to ship `fallow audit`

* the chosen policy is encoded in config, not accumulated in scattered suppressions
* unresolved imports and unlisted dependencies are cleared
* blatant dead code (unused files, unused dependencies) is removed
* `fallow audit` is wired into CI and passes for new changes against the default branch

### Stage 2: ideal state

* no functions above your chosen health thresholds, either by refactoring or by consciously widening the threshold with written justification
* duplication at or below the chosen threshold
* stale suppressions gone or consciously accepted

## 7. Turn on PR enforcement

Once stage 1 is done, add the PR gate:

```bash theme={null}
npx fallow audit
```

`fallow audit` runs dead code, duplication, and complexity analysis scoped to changed files, then returns a `pass`, `warn`, or `fail` verdict. See the [`fallow audit` reference](/cli/audit) for flags and CI recipes.

### Pick one rollout strategy

<Tabs>
  <Tab title="Option A: warn-everywhere">
    Best for smaller teams. CI never blocks; fixes land under social pressure.

    ```jsonc theme={null}
    {
      "rules": {
        "unused-exports": "warn",
        "unused-files": "warn",
        "unused-dependencies": "warn"
      }
    }
    ```

    Risk: warn-only gates become warning-forever gates. Set a calendar reminder to promote rules to `error` after the first clean month.
  </Tab>

  <Tab title="Option B: error + baselines">
    Best for larger orgs. CI blocks on new issues; pre-existing debt on touched files is baselined.

    ```bash theme={null}
    # Save baselines once on the default branch
    fallow dead-code --save-baseline fallow-baselines/dead-code.json
    fallow health    --save-baseline fallow-baselines/health.json
    fallow dupes     --save-baseline fallow-baselines/dupes.json

    # Audit only new issues on PRs
    fallow audit \
      --dead-code-baseline fallow-baselines/dead-code.json \
      --health-baseline    fallow-baselines/health.json \
      --dupes-baseline     fallow-baselines/dupes.json
    ```

    Store committed baselines outside `.fallow/` (which `fallow init` adds to `.gitignore` for machine-local cache). `fallow-baselines/` is the recommended default. Commit the baseline files so every PR compares against the same snapshot, and regenerate on a schedule (quarterly, or per release) rather than per merge, otherwise teams silently absorb new debt every time CI runs.
  </Tab>

  <Tab title="Option C: local agent gate">
    Best when Claude Code is the main pusher. Add a project-level `PreToolUse` hook that intercepts `git commit` and `git push`, runs `fallow audit --format json --quiet --explain`, and blocks only on `verdict: "fail"`. Claude receives the raw audit JSON on stderr, fixes the findings, and retries the command.

    Pair this with Option A or B, not instead of them. This is a local reinforcement layer. Keep CI on `fallow audit` so human pushes and non-Claude workflows are still covered.

    Runtime errors (no base ref yet, first commit in an empty repo, config errors) fail open so new repos do not get stuck.

    See [Claude Code hooks](/integrations/claude-hooks) for the full recipe, or generate the files with:

    ```bash theme={null}
    fallow hooks install --target agent
    ```
  </Tab>
</Tabs>

You can also configure baselines in `.fallowrc.json` and run `fallow audit` with no flags:

```jsonc theme={null}
{
  "audit": {
    "deadCodeBaseline": "fallow-baselines/dead-code.json",
    "healthBaseline":   "fallow-baselines/health.json",
    "dupesBaseline":    "fallow-baselines/dupes.json"
  }
}
```

<Warning>
  Baselines are a debt ledger, not a steady state. If the baseline file only grows, the policy is not being enforced.
</Warning>

## 8. Clean up with an agent

Fallow finds the problems. An AI agent (Claude Code, Cursor, Codex, Windsurf, any shell-capable coding assistant) is the right tool to fix them: edits are mechanical but decisions ("delete this export" vs. "mark it `@public`" vs. "add it to `entry`") benefit from code-aware judgement.

Three levels of integration, pick whichever your agent supports:

<CardGroup cols={3}>
  <Card title="Skills (best)" icon="wand-magic-sparkles" href="/integrations/agent-skills">
    Install `fallow-skills` for Claude Code, Cursor, Windsurf, or any Agent Skills compatible agent. Once installed, the skill works offline; the agent does not need to fetch docs URLs during use.
  </Card>

  <Card title="MCP" icon="robot" href="/integrations/mcp">
    Structured tool calling with JSON output and `_meta` explanations. Works alongside skills.
  </Card>

  <Card title="Plain shell" icon="terminal">
    Any agent that can run a shell command can drive Fallow. Use the copy-paste prompt below.
  </Card>
</CardGroup>

<Accordion title="Copy-paste adoption prompt (for agents without skills or MCP)">
  Paste this prompt into your agent. It is self-contained: the agent does not need to fetch this page to follow it.

  ```text theme={null}
  Adopt Fallow in this repository.

  Goal:
  - use full-repo analysis first (`fallow`, `fallow dead-code`, `fallow dupes`, `fallow health`), not `fallow audit`
  - fix real dead code, duplication, and complexity issues in code
  - model intentional exceptions with the narrowest correct mechanism
  - end with no functions above the repo's chosen health thresholds, or a consciously widened threshold with written justification
  - then set up `fallow audit` as a PR gate

  Process:
  1. Run `npx fallow`, then `npx fallow dead-code`, `npx fallow dupes`, and `npx fallow health`. Use `--format json` if you want structured output.
  2. If no config exists, run `fallow init` and create a minimal repo policy.
  3. Fix high-confidence issues first:
     - unresolved imports
     - unlisted dependencies
     - unused files (sanity-check with `fallow list --entry-points`)
     - unused dependencies
  4. For each remaining finding, choose one path:
     - fix it in code (preferred)
     - model it in config
     - add a narrow inline exception only if it is truly one-off
  5. Match reasons to mechanisms:
     - external API: `@public` / `@internal` / `@beta` / `@alpha`, or `publicPackages`
     - runtime or framework entry point: `entry`, `dynamicallyLoaded`, plugin-aware config
     - generated code: `ignorePatterns`, `health.ignore`
     - intentionally retained dependency: `ignoreDependencies`
     - intentional unused export: `@expected-unused` (preferred over inline comments because it self-cleans)
     - one-off false positive: `fallow-ignore-next-line`
     - repo-wide policy: `rules`, `health`, duplication settings, `overrides`
  6. Prefer config-level modeling over repeated suppression.
  7. Keep every exception narrow and explain why it exists in a commit message.
  8. Re-run Fallow after each batch until the repo is clean under the chosen policy.
  9. Only after repo cleanup, run `npx fallow audit` and wire it into CI.

  At the end, report:
  - code changes
  - config changes
  - exceptions added and why
  - anything left
  - the final commands and outputs that show the repo is clean
  ```
</Accordion>

## Next steps

<CardGroup cols={2}>
  <Card title="fallow audit" icon="shield-check" href="/cli/audit">
    Enforce the policy on changed files in CI.
  </Card>

  <Card title="Configuration overview" icon="gear" href="/configuration/overview">
    Every config key, with examples.
  </Card>

  <Card title="Suppression" icon="comment-slash" href="/configuration/suppression">
    Visibility tags, inline comments, and when to use each.
  </Card>

  <Card title="Agent Skills" icon="wand-magic-sparkles" href="/integrations/agent-skills">
    Install `fallow-skills` for agent-driven adoption.
  </Card>
</CardGroup>
