eslint-plugin-import-x: the fork that dropped the TypeScript dependency
`eslint-plugin-import-x` is a fork of `eslint-plugin-import` that aims to provide a more performant and more lightweight version of the original plugin.
At a glance
- What is it?
- eslint-plugin-import-x is a TypeScript rewrite of eslint-plugin-import that swaps tsconfig-paths and the full typescript package for get-tsconfig and a Rust resolver, cutting its dependency count from 117 to 16. It is aimed at teams on flat config who want import and export linting that understands the exports field.
- Who is it for?
- eslint-plugin-import-x is worth adopting for a TypeScript codebase that lints with flat config and that has been held back by the exports field or by the size of the original plugin's dependency tree. It is the wrong choice if you are still on legacy eslintrc configuration with no plan to migrate, if you depend on other plugins that import from eslint-plugin-import directly, or if you need the original plugin's support matrix for very old Node versions.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A fork driven by two blockers in the original plugin
eslint-plugin-import-x started as a fork of eslint-plugin-import, and the documentation is direct about why. Many problems the project wanted to fix could not be fixed without API changes, and the original plugin refused to accept breaking changes for them. The fork existed to unblock that work.
One concrete blocker was the `exports` feature in package.json. The project documentation states that eslint-plugin-import refuses to support it, and that its maintainer locked the feature request issue to prevent further discussion. eslint-plugin-import-x provides first-party support for `exports` today, and the documentation says that support will become the default in the next major version, v5. The same reasoning applies to a set of long-running issues listed in the documentation that could not be closed without API changes.
The documentation also notes that eslint-plugin-import has since stated it would accept breaking changes, but that nothing was happening at the time of writing, with a linked pull request as evidence. The fork's premise therefore rested on the upstream project not moving.
A second, smaller rename matters for anyone who followed the project early. The plugin was originally published as `eslint-plugin-i` and is now `eslint-plugin-import-x`, and the rules keep the `import-x/` prefix even though the package name changed.
The audience is TypeScript shops with flat config. The package is written in TypeScript, ships as an ES module with a CommonJS build alongside it, and the primary language of the repository is TypeScript.
get-tsconfig and a Rust resolver replace the TypeScript path
The performance claim rests on two concrete substitutions, both described in the project documentation.
The first is configuration loading. eslint-plugin-import uses tsconfig-paths plus the typescript package itself to load tsconfig files, while eslint-plugin-import-x uses the single package get-tsconfig instead. The documentation describes this as much faster and cleaner, and it is the change that removes the heavy TypeScript dependency from the resolution path. For a plugin whose whole job is reading your project layout, not running the TypeScript compiler, that is a sensible cut.
The second is module resolution itself. The original plugin uses the `resolve` package, which does not support the `exports` field in package.json, while eslint-plugin-import-x builds on a Rust based resolver named unrs-resolver, described as feature rich and more performant. This is also what makes the `exports` support possible, so the two changes are connected rather than separate speedups.
The resolver interface has a version dimension. The documentation describes a v3 resolver interface that shares a single `resolver` instance by default across resolving chains, so that caching and memoization work out of the box. Two resolver entry points are documented, `import-x/resolver-next` and `import-x/resolver`, and the settings section lists both, so you choose between them in configuration.
The result is a plugin that resolves modules without booting a TypeScript program. That is the single change most likely to be noticed in a large monorepo, where the original plugin's cost multiplied across every file.
Sixteen dependencies against 117
The dependency count is the headline number in the project documentation: eslint-plugin-import-x has 16 dependencies compared to 117 for eslint-plugin-import. The stated reason is that the fork does not depend on old and outdated dependencies, which follows from dropping the typescript and tsconfig-paths path.
That number is worth reading carefully rather than as a marketing figure. A dependency count is a proxy for install size, exposure to vulnerable transitive packages, and the odds that an unrelated package update breaks your lint run. A plugin that pulls in the full TypeScript compiler as a runtime dependency inherits every release of that compiler, whether or not you use its types. Removing it removes a whole category of surprise from CI.
The tooling around the package reflects the same approach. The repository uses changesets for releases, with a .changeset directory, and the release script runs clean-pkg-json before publishing. Renovate is enabled for dependency updates, code style is checked with Prettier and linted with ESLint itself, commits follow the Conventional Commits convention, and there is a .nano-staged.js plus simple-git-hooks configuration for staged changes. The package manager is pinned to yarn 4.9.2 through the packageManager field, and a patches directory with the patch-package step in the prepare script suggests the maintainers carry local patches for dependencies they cannot change upstream.
Installing the plugin and pointing ESLint at it
The installation is a single development dependency, as the documentation shows:
# inside your project's working tree
npm install eslint-plugin-import-x --save-devBecause the package is published to npm under that name, the plugin resolves by that name. The rule identifiers, however, use the `import-x/` prefix, so a rule that the original plugin called `import/no-unresolved` is enabled here as `import-x/no-unresolved`. That difference is the part people trip over when they copy a configuration file from an existing project, and it is worth checking line by line if you are migrating a config rather than writing a new one.
The project documentation has separate configuration sections for the two config systems, one for the new `eslint.config.*` flat config and one for the legacy `.eslintrc*` format, and it includes JavaScript and TypeScript examples for each, plus a section on using the plugin as a standalone ESLint plugin and one on the `defineConfig` helper. The documentation also notes a type-checking wrinkle: if you are type-checking your `eslint.config.js` but are not using typescript-eslint, the plugin ships its own type declarations, and there is a section addressing that case.
The repository's own configuration is a useful reference for what a real setup looks like. At the top level there is both an `eslint.config.js` for the project itself and an `.eslintrc.cjs`, which suggests the maintainers keep a legacy file around for tooling that still expects one.
Rules grouped by purpose, settings that tune resolution
The documentation organises the rules into groups rather than listing them alphabetically, and the grouping is more useful than a flat list because it tells you which rules are about correctness and which are about taste.
The helpful warnings group covers the things that are probably mistakes, such as a misspelled file path or an import name that does not exist. The module systems group covers the rules about how modules are declared and resolved, including mixing of module formats. The performance group addresses patterns that cost something at runtime. Static analysis covers what can be checked from the import graph alone. The style guide group is where the formatting preferences live, and it is the group most teams disable wholesale.
Resolution itself is controlled by settings rather than by rules. The documented settings are `import-x/extensions`, `import-x/ignore`, `import-x/core-modules`, `import-x/external-module-folders`, `import-x/parsers`, `import-x/resolver` and `import-x/resolver-next`, `import-x/cache`, and `import-x/internal-regex`. The `import-x/cache` setting is the one that pairs with the shared resolver instance described earlier, and `import-x/ignore` is the setting that controls which paths are skipped during resolution.
The resolvers live in their own directory in the repository, with a README of their own, and the settings keys that select them are the two resolver settings. Since the v3 interface shares one instance by default, a project that configures a custom resolver will feel the difference in lint speed on large dependency trees, which is where resolution cost concentrates.
Version targets, a v5 on the horizon, and the MIT licence
The supported matrix is narrower than the original plugin's and that is deliberate. eslint-plugin-import-x targets Node `^18.18.0 || ^20.9.0 || >=21.1.0` and ESLint `^8.57.0 || ^9.0.0 || ^10.0.0`, while the original plugin targets Node `>=4` and a much longer list of ESLint versions. So this fork does not run on the Node versions that the original still supports, which is a reasonable trade for a package that no longer carries the old dependency tree.
The release line is at 4.x, with v4.17.1 published on 2026-06-28, v4.17.0 a few days earlier on 2026-06-22, and v4.16.2 on 2026-03-11. The repository is not archived and the last push was on 2026-10-11, so work continues between tags. The default branch is master, and releases go through the changesets workflow rather than by hand, with a CHANGELOG.md at the top level.
The v5 horizon matters for planning. The documentation says `exports` support will become the default in v5, and separately that there are remaining issues which could be addressed in that next major version. A major bump for a lint plugin means rule behaviour changes and possible new configuration requirements, so a team on 4.x should expect to spend time on the upgrade rather than bumping a patch version.
The licence is MIT, the same permissive grant the original plugin uses, so adopting the fork does not introduce a licensing question that the original did not already raise. The package is funded through Open Collective, and the repository links a Sponsors and Backers section.
Where the fork is the wrong tool
The first limitation is migration cost, which the project does not pretend away. Rule names carry the `import-x/` prefix, so every rule reference in an existing config needs to change, and the settings keys are prefixed the same way. A large configuration is a large diff, and a large diff in lint configuration is where mistakes hide, because a rule name that no longer resolves is silently ignored by ESLint rather than failing loudly. The documentation's separate sections for flat config and legacy config are a further sign that the two paths are not identical.
The second limitation is the ecosystem around the original plugin. The rule set is a fork, so most rules behave the same, but anything that reaches into eslint-plugin-import internals, or a shared config that names `import/` rules, needs attention. The same applies to documentation, tutorials and internal runbooks that reference the original rule names.
The third is the support matrix. If your team still has to support Node 14 or an old ESLint, this fork is not available to you, and the documentation makes that explicit. The flip side is that the fork also does not carry the original plugin's compatibility work, so there is no option to keep the old matrix by staying on the old package.
A last practical point is about what the fork does not do. The documentation says the authors have not resolved all the issues yet, and that some of that work could happen in v5. So a team expecting parity with the original plus every open upstream issue should not expect that today.
The alternative is not a different plugin but the upstream one. The choice is between the original eslint-plugin-import, which keeps the larger dependency tree and the `resolve` based resolver, and this fork, which drops the TypeScript path, adds a Rust resolver, supports `exports` and is on a modern Node and ESLint matrix. If your project is already modern, on flat config, and blocked on `exports`, the fork is the better fit. If you are on an old stack, or your lint configuration is entangled with other plugins, staying put is less work than the migration, and the upstream project is the one to evaluate.
Editorial conclusion
eslint-plugin-import-x is worth adopting for a TypeScript codebase that lints with flat config and that has been held back by the exports field or by the size of the original plugin's dependency tree. It is the wrong choice if you are still on legacy eslintrc configuration with no plan to migrate, if you depend on other plugins that import from eslint-plugin-import directly, or if you need the original plugin's support matrix for very old Node versions. Before switching, read the differences list against the original plugin, confirm your resolvers and settings keys use the import-x prefix, and expect the v5 release, where exports support becomes the default, to require a config review.
Frequently asked questions
How do I install eslint-plugin-import-x?
The project documentation gives a single command to run inside your project's working tree: `npm install eslint-plugin-import-x --save-dev`. The package is published to npm under that name, while the rule identifiers use the `import-x/` prefix.
What is the difference between eslint-plugin-import-x and eslint-plugin-import?
The fork uses get-tsconfig instead of tsconfig-paths plus typescript to load tsconfig files, and a Rust based resolver named unrs-resolver instead of resolve, which is what gives it support for the exports field. It also has 16 dependencies against 117 for the original.
Which Node and ESLint versions does eslint-plugin-import-x support?
It targets Node `^18.18.0 || ^20.9.0 || >=21.1.0` and ESLint `^8.57.0 || ^9.0.0 || ^10.0.0`, a narrower range than the original plugin, which targets Node `>=4` and older ESLint releases.
How do I configure the resolver in eslint-plugin-import-x?
The documented settings include `import-x/resolver` and `import-x/resolver-next`, and the resolvers have their own directory and README in the repository. The v3 resolver interface shares a single resolver instance across resolving chains by default, which allows caching and memoization.
Will upgrading to version 5 of eslint-plugin-import-x change how my config behaves?
Yes. The project documentation states that first-party support for the exports feature will become the default in the next major version, v5, and that remaining issues could be addressed there, so a major upgrade is expected to require a config review.
What licence is eslint-plugin-import-x published under?
It is published under the MIT licence, with the licence file at the top of the repository. The package is funded through Open Collective.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/un-ts-eslint-plugin-import-x)Was this useful?