---
id: "packages/eslint-config/getting-started"
title: "Getting started"
description: "Receive eslint-config in a new or an existing repository, wire a preset, and read your first lint run."
url: "/packages/eslint-config/getting-started"
locale: "en"
revision: "e4cd989088978671"
---

# Getting started

These steps were carried out in a new, empty pnpm workspace outside every source repository, with
a bundle composed in Foundation and nothing else: no path to Foundation and no other source.

## A new repository

## Prepare your repository

A pnpm workspace with `packages/*`, Node.js 26, and byte-exact checkouts for transferred packages
and the applier:

```yaml
# pnpm-workspace.yaml
packages:
  - packages/*
  - apps/*
```

```text
# .gitattributes
packages/** -text
.rps/** -text
tools/rps/** -text
```

Keep the applier (`rps-apply.mjs` and `rps-contract.mjs`) under `tools/rps/`. Every bundle carries
a reference copy of both under `tooling/`; see [Receiving packages](/receiving-packages).

## Receive the package

Ask the maintainer of Foundation for a bundle. `eslint-config` can be requested on its own, as an
owner:

```bash
# In Foundation, by its maintainer
pnpm rps:transfer bundle --owners eslint-config --channel development --out <bundle-folder>
```

Then, in your repository:

```bash
node tools/rps/rps-apply.mjs plan --bundle <bundle-folder> --development
node tools/rps/rps-apply.mjs apply --bundle <bundle-folder> --expect-plan <digest> --development
```

The package now sits in `packages/eslint-config`. Do not edit it there.

## Declare and install

Declare the package once, in the root `package.json`. Every workspace below the root resolves it
from there:

```json
{
  "devDependencies": {
    "@workspace/eslint-config": "workspace:*"
  }
}
```

Each package or app that runs lint declares its own `eslint` and `typescript`:

```json
{
  "devDependencies": {
    "eslint": "^10.12.0",
    "typescript": "^6.0.3"
  }
}
```

The plugins the presets load come with the package as its own dependencies. Install, then check
that the root resolves the managed copy:

```bash
pnpm install
node tools/rps/rps-apply.mjs verify-install --from .
```

The output must list `@workspace/eslint-config` as `current`. Run it from the folder that declares
the package: from an app that does not declare it, it lists nothing and checks nothing.

## Choose a preset

In the `eslint.config.mjs` of each package or app, spread the preset that fits its own source files
([Presets](/packages/eslint-config/presets)) and add your ignores after it:

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

/** @type {import("eslint").Linter.Config[]} */
export default [
  ...config,
  {
    ignores: ['node_modules/**', 'dist/**'],
  },
];
```

## Add the lint script

The threshold sits in the script, in every package and app that lints:

```json
{
  "scripts": {
    "lint": "eslint . --max-warnings 100"
  }
}
```

## Run it and read the count

```bash
pnpm --filter <package> lint
```

No output means no findings. Otherwise the last line counts them, for example
`✖ 5 problems (0 errors, 5 warnings)`, and the run still passes. See
[Checks and troubleshooting](/packages/eslint-config/checks) for what fails a run.

## An existing repository

Start from the situation your repository is in:

| Your repository | What to do |
| --- | --- |
| has no managed packages and no `packages/eslint-config` | the steps above |
| has its own copy at `packages/eslint-config`, not managed | see [Replacing your own copy](#replacing-your-own-copy) below |
| already receives packages from Foundation by managed transfer | add `--owners eslint-config` to the request of your **whole** set, so the update keeps every package you have (see [Updating](/receiving-packages#updating)) |
| receives managed packages from another source repository | your repository has one provenance record from one source, so it cannot take `eslint-config` from Foundation separately. Ask the maintainer how your whole set moves to Foundation |
| has its own ESLint configuration, without this package | receive the package, replace your configuration by a preset plus a trailing block for what is truly your own ([Local additions](/packages/eslint-config/local-additions)) |

### Replacing your own copy

The applier never writes over a folder it does not manage. With your own copy in place, the plan
stops:

```text
1 conflict(s); no operation is planned and nothing will change:
  RPS-E5 UNMANAGED_TARGET packages/eslint-config: exists and is not managed
```

1. See how your copy differs from the bundle, without changing anything:

   ```bash
   node tools/rps/rps-apply.mjs reconcile --bundle <bundle-folder>
   ```
2. Move your copy out of `packages/`, to a place outside the workspace, and keep it until the new
   copy works.
3. Plan and apply the bundle, then install and verify, as in steps 2 and 3 above.
4. A local change your copy carried is not taken over. If it is useful beyond your repository,
   propose it to the maintainer of Foundation; otherwise it belongs in your own configuration as a
   [local addition](/packages/eslint-config/local-additions).

### After switching

Run lint in every workspace and compare the counts with those before. New warnings that the shared
presets raise are work of your repository. Do not raise the threshold to make a run pass.
