Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ Set up, write, or review Rstest tests and configuration, including environments,
npx skills add rstackjs/agent-skills --skill migrate-to-rslint
```

Migrate ESLint or other lint tools to Rslint. Use when replacing ESLint flat config, lint scripts, VS Code ESLint settings, inline directives, rules, presets, plugins, or lint dependencies with Rslint equivalents.
Migrate ESLint flat config or Oxlint to Rslint, preserving rule options, file scopes, and plugins while updating lint scripts, editor settings, and inline directives.

## Storybook skills

Expand Down
2 changes: 2 additions & 0 deletions scripts/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ llms
modernjs
mktemp
napi
oxlint
oxlintrc
pacman
pluggable
prebundle
Expand Down
35 changes: 24 additions & 11 deletions skills/migrate-to-rslint/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: migrate-to-rslint
description: Migrate ESLint or other linters to Rslint. Use when asked to replace ESLint flat config, lint scripts, VS Code ESLint settings, inline directives, rules, presets, plugins, or lint dependencies with Rslint equivalents.
description: Migrate ESLint flat config or Oxlint to Rslint, preserving rule options, file scopes, and plugins while updating lint scripts, editor settings, and inline directives.
---

<!-- cspell:words Rslint rslint -->
Expand All @@ -14,29 +14,42 @@ Migrate lint tooling to Rslint with minimal behavior changes and clear validatio
## Supported source linters

- ESLint flat config
- Oxlint

## Migration principles (must follow)

1. **Official docs first**: treat Rslint docs as source of truth for CLI, config, inline directives, VS Code settings, rules, and presets.
1. **Official docs first**: use Rslint docs for CLI, config, inline directives, VS Code settings, rules, and presets. Check capabilities against the installed version; historical migration gaps and workarounds are not permanent limitations.
2. **Smallest-change-first**: migrate package, command, config, and editor wiring before changing source files.
3. **Preserve lint intent**: keep supported rule severities/options where Rslint supports them; call out unsupported rules/plugins instead of silently dropping behavior.
4. **Do not rewrite inline directives by default**: Rslint supports `eslint-disable` and `rslint-disable`; replace prefixes only when the user asks.
5. **Validate before cleanup**: keep old linter dependencies/config until the Rslint command passes for the migrated scope, then remove obsolete linter-only artifacts.
4. **Preserve inline suppression intent**: preserve which directives take effect, their rule targets, and their scope. Keep compatible prefixes unless the user requests renaming; translate source-only syntax and account for disabled directive compatibility in the source-specific guide.
5. **Validate before cleanup**: switch lint entry points to Rslint and validate the migrated scope before removing obsolete source-linter artifacts. Report unsupported-rule coverage differences without treating them as a blocker or requiring separate approval.

## Workflow

1. **Detect source linter**
- ESLint flat config: `eslint.config.*`, `eslint` dependency, or package scripts that run `eslint`.
- Oxlint: `.oxlintrc.json`, `.oxlintrc.jsonc`, `oxlint.config.*`, `oxlint` dependency, or commands that run `oxlint`.
- Record installed versions, commands, working directories, environment switches, and the scope being migrated. Include shared configs, nested configs, and root fallback behavior within that scope.
- If the source linter is not covered by a reference yet, inventory the current behavior and explain that no dedicated migration reference exists.

2. **Apply source-specific migration guide**
- ESLint flat config: `references/eslint-flat-config.md`
2. **Prepare Rslint and apply the source-specific guide**
- Select and install the intended `@rslint/core` version with the repository's package manager before checking its rules, config, and plugin APIs. Respect existing version constraints and retain the source linter for validation.
- ESLint flat config: [references/eslint-flat-config.md](references/eslint-flat-config.md)
- Oxlint: [references/oxlint.md](references/oxlint.md)
- For community or local JS plugins from either source, also read [references/eslint-plugins.md](references/eslint-plugins.md).

3. **Validate behavior**
3. **Update lint entry points**
- Use a supported `rslint.config.*` format. Keep source plugin dependencies required by the translated config.
- Update package scripts, CI, hooks, and staged-file commands in the migrated scope. Use the [Rslint CLI reference](https://rslint.rs/guide/cli) to translate flags while preserving working directories, file arguments, warning thresholds, and environment switches.
- Update existing editor integration using the [Rslint VS Code guide](https://rslint.rs/guide/vscode-extension). Keep unrelated editor tools and settings.

4. **Validate behavior**
- Run the migrated lint command.
- Check effective rules/options, file coverage, suppressions, and plugin execution against the source inventory. A successful exit alone does not establish equivalent behavior.
- For enabled source rules without a validated native or compatible JS-plugin replacement, omit unsupported target keys and record the rule names, affected file scope, and lost coverage for the final report. Continue the migration with the supported rules.
- If the project had a fix command, run the migrated fix command only when appropriate for the task.
- Resolve config, rule, and editor-setting issues before removing legacy files.
- Resolve target config-loading errors, invalid options for supported rules, command failures, and editor-integration errors before cleanup.

4. **Cleanup and summarize**
- Remove obsolete linter dependencies/config after Rslint is green.
- Summarize changed files, migrated presets/plugins, unsupported gaps, and remaining manual follow-ups.
5. **Cleanup and summarize**
- Confirm all lint entry points in the migrated scope use Rslint, then remove obsolete source-linter commands, configuration, and dependencies after validation.
- Summarize the completed switchover and validation, naming any omitted rules/plugins, affected scopes, and coverage or behavior changes.
16 changes: 9 additions & 7 deletions skills/migrate-to-rslint/references/eslint-flat-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Use this reference when the source project uses `eslint.config.*`.
- Rslint configuration: https://rslint.rs/config/
- Rslint ignores and `.gitignore`: https://rslint.rs/config/ignoring-files
- Rslint rules and presets: https://rslint.rs/config/rules-and-presets
- Rslint TypeScript project settings: https://rslint.rs/config/language-options
- Rslint ESLint plugin compatibility: https://rslint.rs/guide/eslint-plugins
- Rslint inline directives: https://rslint.rs/guide/inline-directives
- Rslint VS Code extension: https://rslint.rs/guide/vscode-extension
- `jiti`: https://npmjs.com/package/jiti
Expand Down Expand Up @@ -39,7 +41,7 @@ Do not delete the ESLint config or dependencies until the migrated Rslint comman

## Step 1: replace linter package dependencies

Install Rslint:
If Rslint was not already installed in the main workflow, install it with the intended version constraints:

```bash
pnpm add -D @rslint/core
Expand Down Expand Up @@ -95,7 +97,7 @@ Use only Rslint-supported CLI flags. Supported flags include `--init`, `--config

Do not copy ESLint-only flags blindly. For example, remove or re-evaluate flags such as `--ext`, `--cache`, `--cache-location`, `--resolve-plugins-relative-to`, and `--report-unused-disable-directives` unless the Rslint CLI docs provide an equivalent.

If the old lint command relied on type-aware TypeScript linting, validate the migrated command with `--type-check` or preserve the project's existing Rslint type-checking setup.
If the old lint command relied on type-aware TypeScript rules, preserve its project selection through `languageOptions.parserOptions.project` or `projectService: true`, using the installed Rslint version's supported settings. These modes are alternatives. `--type-check` additionally reports TypeScript compiler diagnostics; do not add it merely to enable type-aware lint rules.

## Step 3: rename and translate config file

Expand All @@ -110,7 +112,7 @@ Recommended mapping:
| `eslint.config.ts` | `rslint.config.ts` |
| `eslint.config.mts` | `rslint.config.mts` |

Rslint uses flat config arrays, so the shape is close to ESLint flat config. Import built-in helpers and presets from `@rslint/core`:
Rslint uses flat config arrays, so the shape is close to ESLint flat config. Import built-in helpers and presets from `@rslint/core`. The following illustrates available imports; include only presets that match the source configuration's intent:

```ts
import {
Expand Down Expand Up @@ -168,14 +170,14 @@ Rslint aligns its JavaScript recommended preset with ESLint's `js.configs.recomm
For rules:

- Keep rule severities and options when Rslint supports the rule.
- If Rslint reports an unknown rule, remove it from the Rslint config and list it as an unsupported migration gap.
- Do not keep installing ESLint plugins in an attempt to make Rslint load them.
- Check unknown rules against the installed native rule catalog and any registered JS plugin. Record unresolved rules as migration gaps; do not silently disable them to make lint pass.
- For community or local JS plugins, follow [ESLint-compatible JS plugins](eslint-plugins.md). Retain packages still needed by those plugins.
- For built-in plugin presets, remove the old plugin dependency after validation if it is no longer used elsewhere.

For ignores:

- Rslint automatically reads `.gitignore` files and treats those patterns as global ignores.
- Remove `ignores` entries that only duplicate `.gitignore` patterns.
- Remove duplicate `ignores` entries only after confirming that the relevant `.gitignore` is read for that invocation and config boundary. Nested configs do not automatically inherit ancestor `.gitignore` files outside their Git scope.
- Keep lint-specific ignores that are not in `.gitignore`, such as source fixtures, generated checked-in files, or deliberate lint exclusions.
- Remember that a config entry containing only `ignores` is a global ignore and can block nested config discovery in ignored directories.

Expand Down Expand Up @@ -260,7 +262,7 @@ Resolve validation failures in this order:
4. Type-aware linting behavior.
5. Autofix differences.

After validation passes:
Complete the main workflow's [behavior validation](../SKILL.md#workflow), including the source inventory comparison, before cleanup. After validation passes:

- Remove obsolete ESLint config files.
- Remove obsolete ESLint dependencies that are not used elsewhere.
Expand Down
37 changes: 37 additions & 0 deletions skills/migrate-to-rslint/references/eslint-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# ESLint-compatible JS plugins

Use this reference when the source config loads community or local JS plugins. Oxlint-specific `createOnce` adaptation is covered in [the Oxlint guide](oxlint.md#step-4-adapt-js-plugins).

Check the installed Rslint version against the official [plugin configuration](https://rslint.rs/config/plugins) and [ESLint API compatibility](https://rslint.rs/guide/eslint-plugins) references.

## Preserve plugin identity and configuration

- Record each module, configured namespace, enabled rules, options, settings, file scope, and environment-dependent wrapper. A loaded module or an explicitly disabled rule is not an enabled rule.
- Reuse the plugin implementation when supported. Keep its package and runtime dependencies resolvable from the migrated config.
- Register native namespaces with a `plugins` array and JS plugin objects with a `plugins` object in separate entries. Keep their original scope and precedence.
- Preserve custom aliases. If an alias conflicts with a Rslint built-in namespace, choose a distinct alias and update its rule keys and directive references together; do not merge unrelated rules by name.

For example, separate native and JS plugin registration while retaining the same file scope:

```js
import customPlugin from './lint/custom-plugin.js';

export default [
{
files: ['src/**/*.ts'],
plugins: ['@typescript-eslint'],
rules: { '@typescript-eslint/no-explicit-any': 'warn' },
},
{
files: ['src/**/*.ts'],
plugins: { custom: customPlugin },
rules: { 'custom/project-rule': 'error' },
},
];
```

## Check the APIs used by enabled rules

Confirm that the target version supports the plugin's selectors, context APIs, and fix behavior. In particular, inspect uses of parser services, custom parsers/processors, and code-path listeners against the compatibility reference. Loading a plugin successfully does not prove that its rules execute.

Use a representative known violation to confirm execution, including any environment switch that enables or disables a wrapper. Preserve rule logic; report an API gap when the existing implementation cannot run. Return to the calling source-specific guide and finish its remaining steps before continuing with the main workflow.
Loading
Loading