# ESLint plugin

> Lint rules for the code that AI coding agents write, for ESLint with or without gspot.

`@gspothq/eslint-plugin` adds lint rules for code that AI coding agents often write. They flag files and functions that only forward a call, exports that only rename a value, and imports through index files. They also flag comments mixed into import blocks and private environment variables read in client code.

The [gspot CLI](https://www.npmjs.com/package/@gspothq/cli) sets this plugin up for you. Install it yourself only when you run ESLint without gspot.

## Install

You need Node.js 22.12 or newer and ESLint 9.38.0 or newer with a flat config file, such as `eslint.config.mjs`.

| Package manager | Command                                                |
| --------------- | ------------------------------------------------------ |
| npm             | `npm install --save-dev @gspothq/eslint-plugin eslint` |
| pnpm            | `pnpm add --save-dev @gspothq/eslint-plugin eslint`    |
| Yarn            | `yarn add --dev @gspothq/eslint-plugin eslint`         |
| Bun             | `bun add --dev @gspothq/eslint-plugin eslint`          |

## Use

Add a plugin config to `eslint.config.mjs`. `recommended` turns on `gspot/no-client-env`; `all` turns on every lint rule except `gspot/require-server-only`.

```javascript
import gspot from '@gspothq/eslint-plugin';


export default [gspot.configs.all];
```

A finding looks like this:

```text
src/orders.js
  15:14  error  getOrderTotal only renames orderTotal. Export the source value directly instead of an alias  gspot/no-alias-exports
```

Turn on `gspot/require-server-only` for the files that hold server code:

```javascript
import gspot from '@gspothq/eslint-plugin';


export default [{ files: ['src/server/**/*.js'], plugins: { gspot }, rules: { 'gspot/require-server-only': 'error' } }];
```

`gspot/import-boundaries` reads its folders relative to the working folder of ESLint. To use another root, set `settings: { gspot: { root: import.meta.dirname } }`.

## Rules

Each rule page gives the options, defaults, and an example.

| Rule                                                                               | Configs that turn it on | What it finds                                                                                                                            |
| ---------------------------------------------------------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| [`gspot/import-boundaries`](/reference/eslint-plugin/import-boundaries/)           | `all`                   | Finds relative imports that leave the nearest boundary folder.                                                                           |
| [`gspot/no-alias-exports`](/reference/eslint-plugin/no-alias-exports/)             | `all`                   | Finds an exported constant that only renames another value.                                                                              |
| [`gspot/no-client-env`](/reference/eslint-plugin/no-client-env/)                   | `recommended, all`      | Finds private environment reads in client modules, including process.env, Bun.env, Deno.env, and import.meta.env.                        |
| [`gspot/no-comments-in-imports`](/reference/eslint-plugin/no-comments-in-imports/) | `all`                   | Reports comments within or immediately after an import block.                                                                            |
| [`gspot/no-index-imports`](/reference/eslint-plugin/no-index-imports/)             | `all`                   | Finds an import that names an index file instead of the module that declares the value, including module paths in Vitest and Jest mocks. |
| [`gspot/no-trivial-files`](/reference/eslint-plugin/no-trivial-files/)             | `all`                   | Reports files containing only forwarding, aliases, re-exports, or trivial functions.                                                     |
| [`gspot/no-trivial-functions`](/reference/eslint-plugin/no-trivial-functions/)     | `all`                   | Reports named functions with two statements or fewer at the default limit.                                                               |
| [`gspot/require-server-only`](/reference/eslint-plugin/require-server-only/)       | None                    | Checks that a selected server module imports "server-only" or declares "use server".                                                     |

## TypeScript

Install `@typescript-eslint/parser` and TypeScript 4.8.4 or newer and older than 6.1.0, then select your TypeScript files:

```javascript
import gspot from '@gspothq/eslint-plugin';
import tsParser from '@typescript-eslint/parser';


export default [
    {
        ...gspot.configs.all,
        files: ['**/*.ts', '**/*.tsx'],
        languageOptions: { parser: tsParser, parserOptions: { projectService: true } },
    },
];
```

`gspot/no-trivial-functions` uses the type information from `projectService` to skip a method that an interface or a base class declares.
