---
id: "packages/eslint-config/local-additions"
title: "Local additions"
description: "Where your repository adds its own ignores and rules, what the shared standard allows, and how a local rule reports."
url: "/packages/eslint-config/local-additions"
locale: "en"
revision: "f351ffe3b2f97d1a"
---

# Local additions

A preset is the shared baseline. What only your repository needs goes in **your own**
`eslint.config.mjs`, after the preset, never in the package copy. A change to the package copy is a
defect: the next transfer stops on it.

## A trailing block

Spread the preset first, then add your ignores and rules in blocks after it. A later block wins
over an earlier one:

```js
// eslint.config.mjs
import {config} from '@workspace/eslint-config/base';

/** @type {import("eslint").Linter.Config[]} */
export default [
  ...config,
  {
    ignores: ['node_modules/**', 'dist/**', 'coverage/**'],
  },
  // This service writes to its log, never to the console.
  {
    files: ['src/**/*.ts'],
    rules: {
      'no-console': 'error',
    },
  },
];
```

## A local rule reports a warning too

`only-warn` applies to your blocks as well. The `'error'` above is reported as a warning:

```text
  4:5  warning  Unexpected console statement  no-console

✖ 1 problem (0 errors, 1 warning)
```

A local rule therefore never fails a run on its own; it counts towards the threshold like every
other warning. The package offers no way to make one rule fail a run by itself. If your repository
needs that, it is a check of its own, outside this configuration.

## What the shared standard allows

The development standard (`docs/standards/CONFIG_STANDARDS.md` § 3 in your copy of the standards)
sets the limits. In short:

| Allowed | Not allowed |
| --- | --- |
| your own `ignores` | switching off the em-dash or the `catch`-naming convention |
| stricter rules, in a trailing block | disabling `only-warn` |
| rules for your own tools, in a trailing block | raising the threshold of one package above 100 |
| a narrow, scoped exception with its reason | editing the package copy |

An exception to these limits is a decision your repository records in its own
`docs/DECISIONS.md`, never a silent local variant. A rule that would serve every repository is
proposed to the maintainer of Foundation instead.

The package's own reference lists common additions (`docs/API.md`, section *Consumer-side rule
additions*, in your copy) and two more limits: do not switch the convention rules off per
repository, and do not re-enable an `@eslint-react` hooks rule, because `eslint-plugin-react-hooks`
is the one hooks authority and a second rule reports the same finding twice.

## One exception in the code

For a single, deliberate exception, disable the rule on the line, with the reason after `--`:

```ts
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- the plugin API is untyped
export function register(plugin: any): void {
```

The reason names what makes this case different, not "intentional" or "false positive". In order
of preference: fix the code, correct the configuration, a scoped override, and only then a line
exception. Never switch a rule off everywhere for one case.

## Environment variables without Turbo

`turbo/no-undeclared-env-vars` reports every environment variable a file reads that `turbo.json`
does not declare. In a repository with Turbo, declare the variable in `turbo.json`.

A repository **without** a `turbo.json` gets a warning for every variable a file reads:

```text
  4:17  warning  API_TOKEN is not listed as a dependency in turbo.json  turbo/no-undeclared-env-vars
```

The shared standard does not yet say how such a repository handles the rule. Until it does, these
warnings count towards your threshold, and switching the rule off, even for some files, is a
decision your repository records with its reason.
