Skip to content
Fallow home
All docs pages

Inline suppression

Keep fallow quiet about a false positive, a library export, or an intentional exception, without turning off a rule. Use fallow-ignore comments, JSDoc visibility tags (@public, @internal, @beta, @alpha), and @expected-unused.

Inline suppression removes one finding from the report and keeps the rule on for the rest of the codebase. Use it for a false positive or an intentional exception. You add a comment or a JSDoc tag next to the code.

For broad patterns, use config-level rules. Keep inline suppression for single exceptions. For library exports that other projects use, add JSDoc visibility tags (@public, @internal, @beta, @alpha) instead of suppression comments.

JSDoc visibility tags

Fallow never reports an export with a JSDoc visibility tag as unused. It recognizes @public, @internal, @beta, and @alpha. Use these tags for library APIs that external projects use, and for exports that you keep for a specific audience. These exports have no references in your repo, but they are part of your public API.

/** @public */
export function createClient() {
  // Not imported anywhere in this repo, but consumed by users of the library
}

/**
 * Configuration options for the client.
 * @public
 */
export interface ClientOptions {
  baseUrl: string;
  timeout?: number;
}

/** @internal */
export function resetState() {
  // Used by sibling packages in the monorepo, not public API
}

/** @beta */
export function experimentalFeature() {
  // Available to early adopters, not yet stable
}

/** @alpha */
export function unstableApi() {
  // Early-stage API, subject to breaking changes
}

/** @api public */
export type UserId = string; // TSDoc @api convention also supported

The tags work with all export types: named, default, classes, interfaces, enums, type aliases, and multi-specifier exports (export { foo, bar }).

On a decorated class, put the JSDoc block before the first decorator, as TypeScript does. The block then applies to the export. This is also true for @deprecated.

/** @public */
@Component({ selector: "app-card" })
export class CardComponent {}

A JSDoc block between a decorator and export does not apply to the export. A block before an earlier, unrelated statement does not apply either.

Fallow recognizes only /** */ JSDoc block comments. Line comments (// @public) and regular block comments (/* @public */) have no effect.

@expected-unused JSDoc tag

To mark an export as intentionally unused, add /** @expected-unused */. Fallow checks this tag for staleness, which it does not do for visibility tags (@public, @internal). If another module imports the export later, fallow reports the tag as a stale suppression.

/** @expected-unused */
export const deprecatedHelper = () => {
  // Intentionally kept but not used anywhere
};

Use @expected-unused when you want to:

  • Suppress an unused export finding.
  • Get a finding when the export is used again (through the stale-suppressions rule).

The stale-suppressions rule (default: warn) sets the severity of stale @expected-unused tags. For details, see dead code explained.

Comment syntax

// Suppress all issues on the next line
// fallow-ignore-next-line
export const keepThis = 1;

// Suppress a specific issue type
// fallow-ignore-next-line unused-export
export const keepThisToo = 2;

// Suppress all issues in the entire file
// fallow-ignore-file

// Suppress a specific issue type file-wide
// fallow-ignore-file unused-export

Suppressing complexity findings

To remove one function from the complexity report of fallow health, suppress complexity on it. The comment suppresses the cyclomatic and the cognitive metric together.

// fallow-ignore-next-line complexity
function* parseCsv(text) {
  // intentionally complex parser, not worth refactoring
  // ...
}

function processRow(row) {
  // this function is NOT suppressed, still appears in health output
  // ...
}

A file-level suppression removes all functions in the file from the complexity findings. File health scores do not change:

// fallow-ignore-file complexity

Reference

CommentScope
// fallow-ignore-next-lineAll issues on the next line
// fallow-ignore-next-line <type>One issue type on the next line
// fallow-ignore-next-line <type>, <type>Multiple issue types on the next line (separated by commas or spaces)
// fallow-ignore-fileAll issues in the file
// fallow-ignore-file <type>One issue type in the file

Multi-kind markers and typos

A marker can list more than one token. A token may not match a known issue kind, for example because of a typo or because a newer fallow release renamed the kind. The recognized tokens then still apply, and fallow reports each unknown token as a stale-suppression finding.

When a known kind is within edit distance 2, the finding includes a "Did you mean ...?" hint. An upgrade across a rename therefore never breaks the whole marker without a message.

// Recognized + unknown on the same marker:
// fallow-ignore-next-line unused-export, complexity-typo
export const foo = 1;
// `unused-export` still suppresses `foo`; `complexity-typo` surfaces as a stale
// suppression so you can fix the typo or drop the unknown token.

In JSON output, the additive origin.kind_known field on stale_suppressions[].origin tells an unknown-kind token apart from a known token that is stale. The field is present and false only for an unknown kind. It is absent when fallow recognizes the kind.

Documenting suppressions with a reason

A reason tells the next reader why a suppression exists. Add -- <reason> at the end of any suppression comment or @expected-unused tag:

// fallow-ignore-next-line unused-export -- public compatibility export
export const legacyHelper = () => {};

// fallow-ignore-file -- generated route map

/** @expected-unused -- kept for the v3 migration */
export const oldApi = () => {};

By default, the reason is optional. Fallow records it in the suppression hygiene output. To require a reason on every suppression, enable the opt-in require-suppression-reason rule (default off):

{ "rules": { "require-suppression-reason": "warn" } }

With the rule at warn (or error to fail CI), fallow reports each fallow-ignore-* comment or @expected-unused tag without a -- <reason> as a missing-suppression-reason finding. You can then find the suppressions that have no reason and add one. For the rule reference, see Rules & Severity.

Issue type tokens

Use these tokens in suppression comments. The Scope column shows where each token works: line level (// fallow-ignore-next-line), file level (// fallow-ignore-file), or both.

TokenIssueScope
unused-fileUnused filefile
unused-exportUnused exportboth
unused-typeUnused type exportboth
private-type-leakExported signature that references a private typeboth
unused-enum-memberUnused enum memberboth
unused-class-memberUnused class memberboth
unused-store-memberUnused Pinia store memberboth
unresolved-importUnresolved importboth
duplicate-exportDuplicate export. A line-level marker has no effect, and fallow reports it as a stale suppressionfile
code-duplicationCode duplicationboth
circular-dependencyCircular dependencyboth
re-export-cycleRe-export cycle. Put the marker on any file in the cyclefile
package-cycleOne import or re-export statement between workspace packages. Each statement counts on its own, also when two statements in one file import the same module. The package cycle goes away when every import on one hop is suppressedboth
boundary-violationBoundary violation. Covers all boundary findings: import direction, zone coverage, and forbidden calls. Fallow also accepts the aliases boundary-call-violation, boundary-call-violations, and boundary-callsboth
policy-violation:<pack>/<rule-id>One rule-pack policy violation. Bare policy-violation covers every rule-pack rule on the line or in the fileboth
invalid-client-exportServer-only or route-config export from a "use client" fileboth
mixed-client-server-barrelBarrel that re-exports client and server-only modulesboth
misplaced-directive"use client" or "use server" directive that is not in the leading positionboth
route-collisionNext.js App Router route files that resolve to the same URLfile
dynamic-segment-name-conflictSibling Next.js dynamic segments with different slug namesfile
unused-server-actionUnused Next.js Server Actionboth
unprovided-injectinject() or getContext() key that nothing providesboth
unrendered-componentComponent that no code rendersboth
unused-component-propUnused component propboth
unused-component-emitUnused Vue component emitboth
unused-component-inputUnused Angular component inputboth
unused-component-outputUnused Angular component outputboth
unused-svelte-eventUnused Svelte eventboth
unused-load-data-keyUnused SvelteKit load() data keyboth
prop-drillingProp drilling chainboth
thin-wrapperThin wrapper componentboth
duplicate-prop-shapeDuplicate prop shapeboth
complexityFunction above the complexity thresholdboth
coverage-gapsFile that no test reaches through the import graphfile
css-token-drift, css-duplicate-block, css-selector-complexity, css-dead-surface, css-broken-referenceStyling findingsboth
feature-flagDetected feature flag patternboth
security-sinkSecurity sink candidateboth
security-client-server-leakClient-server secret leak candidatefile
unused-catalog-entryUnused pnpm catalog entry. Works only as a # fallow-ignore-next-line unused-catalog-entry YAML comment on the line directly above the entry in pnpm-workspace.yamlline

Dependency findings (unused-dependencies, unused-dev-dependencies, unused-optional-dependencies, unlisted-dependencies, type-only-dependencies, test-only-dependencies, dev-dependencies-in-production) belong to package.json. A comment in a source file does not suppress them. Use ignoreDependencies for a package, or set the rule severity. For catalog and override findings, use ignoreCatalogReferences and ignoreDependencyOverrides.

Tokens grouped by command

fallow dead-code (dead code, dependency hygiene, and framework findings): unused-file, unused-export, unused-type, private-type-leak, unused-enum-member, unused-class-member, unused-store-member, unresolved-import, duplicate-export, circular-dependency, re-export-cycle, package-cycle, boundary-violation, policy-violation, policy-violation:<pack>/<rule-id>, the client and server directive tokens, the Next.js route tokens, the component tokens, prop-drilling, thin-wrapper, duplicate-prop-shape, unused-catalog-entry

fallow health (complexity, coverage, and styling with --css): complexity, coverage-gaps, the css-* tokens

fallow dupes (code duplication): code-duplication

fallow flags (feature flag detection): feature-flag

fallow security (security candidates): security-sink, security-client-server-leak

You can use circular-dependency and circular-dependencies in every place that takes a rule slug: inline directives, config rules, and overrides[].rules. The singular form is the standard form for inline directives. The plural form is the standard form for the rules config. Both forms work in both places.

When to use suppression

For broad patterns, use the config (rules, ignoreExports). Use inline suppression for:

  • Individual false positives
  • Temporary suppression during migration

Do not suppress an issue that repeats across the codebase. If a pattern affects many files, configure it at the project level.

Config-level vs inline suppression

// src/components/Button.tsx
// fallow-ignore-next-line unused-export
export const Button = () => { /* ... */ };

// src/components/Input.tsx
// fallow-ignore-next-line unused-export
export const Input = () => { /* ... */ };

// src/components/Modal.tsx
// fallow-ignore-next-line unused-export
export const Modal = () => { /* ... */ };

// Repeated across dozens of component files...

See also