Skip to main content
Version: 7.1.0

Oxlint integration

Oxlint is a Rust-based linter built on the oxc toolchain, offering large performance gains over ESLint. Since Oxlint implements "nearly all ESLint v9+ APIs" through its JS plugins feature, it can load eslint-plugin-boundaries directly.

This guide shows how to configure the plugin under Oxlint.

Working example

See the Oxlint integration example in the repository for a complete, runnable setup.

Compatibility​

eslint-plugin-boundaries works under Oxlint's jsPlugins because it only relies on standard ESLint rule APIs, and needs neither of the two things Oxlint's JS plugins currently don't support:

  • No custom parser — the plugin works on the AST that ESLint (or Oxlint, through its compatible API) already provides.
  • No type-aware linting — classification and dependency checks are purely structural (file paths and import specifiers), not based on TypeScript types.
No shared module graph

Oxlint builds its own internal module graph for multi-file analysis (used by rules like import/no-cycle). eslint-plugin-boundaries does not use that graph — like under ESLint, it resolves each import itself through the import/resolver setting (see below). This means it won't benefit from Oxlint's internal resolver cache, but it also means its behavior is consistent with how it works under ESLint.

Setup​

Install Oxlint, the plugin, and a resolver for your path aliases:

npm install --save-dev oxlint eslint-plugin-boundaries eslint-import-resolver-typescript

Create an .oxlintrc.json file (or an oxlint.config.ts file — Oxlint supports both, see its configuration docs):

.oxlintrc.json
{
"jsPlugins": ["eslint-plugin-boundaries"],
"settings": {
"boundaries/include": ["src/**/*.ts"],
"boundaries/elements": [
{ "type": "helper", "pattern": "src/helpers/*" },
{ "type": "component", "pattern": "src/components/*" },
{ "type": "module", "pattern": "src/modules/*" }
],
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
},
"node": true
}
},
"rules": {
"boundaries/no-unknown-dependencies": "error",
"boundaries/dependencies": ["error", {
"default": "disallow",
"policies": [
{
"from": { "element": { "type": "component" } },
"allow": { "to": { "element": { "type": "helper" } } }
},
{
"from": { "element": { "type": "module" } },
"allow": { "to": { "element": { "type": ["component", "helper"] } } }
}
]
}]
}
}

Then run Oxlint as usual:

npx oxlint
Scoping which files are analyzed

Set boundaries/include (and, if needed, boundaries/ignore) so only your source files are matched against element patterns. Without it, config files that Oxlint also lints as plain JavaScript (like a .cjs config file) can be reported as belonging to an unknown element by boundaries/no-unknown-files, since they don't match any of your descriptor patterns.

Findings and troubleshooting​

These are the concrete issues found both in community reports and while building and running the example above.

The import/resolver setting is required​

This is, by far, the most common source of problems (it was the root cause of the boundaries(no-unknown) error flood reported in the community).

eslint-plugin-boundaries doesn't resolve imports itself — like under ESLint, it delegates to the resolver chain configured in import/resolver. Oxlint activates no resolver by default (only its own internal import plugin, unrelated to import/resolver, has an implicit resolver). If you don't configure import/resolver, resolution falls back to plain Node.js path resolution, which cannot resolve extension-less TypeScript imports or tsconfig.json path aliases. In that case:

  • A relative import that fails to resolve (e.g. ../../helpers/format-message) is classified as pointing to an unknown element, and boundaries/no-unknown-dependencies reports it — if that rule is enabled.
  • A tsconfig.json path-alias import (e.g. @helpers/format-message) that fails to resolve looks like a bare module specifier, so it is silently reclassified as external (unresolvableAlias, see boundaries/flag-as-external) — it does not raise no-unknown-dependencies, and by default the dependencies rule only evaluates local dependencies, so it silently skips boundary checks entirely instead of erroring.

Configuring import/resolver (as shown above) fixes both cases. See Custom Resolvers and TypeScript Support for the full resolver reference, and Debugging to inspect how each import is classified — debug mode works the same way under Oxlint:

ESLINT_PLUGIN_BOUNDARIES_DEBUG=1 oxlint

Referencing the plugin: package name matters​

jsPlugins entries accept either a bare specifier string or an explicit alias object:

"jsPlugins": ["eslint-plugin-boundaries"]
"jsPlugins": [{ "name": "boundaries", "specifier": "eslint-plugin-boundaries" }]

Oxlint derives the rule namespace (boundaries in boundaries/dependencies) from the plugin's own package.json name field, not from the specifier text. This matters because the plugin is published under two names:

  • eslint-plugin-boundaries — its package.json name matches the specifier, so the bare string form works out of the box: Oxlint strips the eslint-plugin- prefix and registers the boundaries namespace.
  • @boundaries/eslint-plugin — the scoped name doesn't have an eslint-plugin- prefix to strip, so the bare string form fails with Plugin 'boundaries' not found. Use the explicit alias form ({ "name": "boundaries", "specifier": "@boundaries/eslint-plugin" }) instead.

IDE vs. CLI differences​

If linting works from the command line but not from an editor extension, it's usually because the extension runs Oxlint from a different working directory than your terminal. Set boundaries/root-path explicitly rather than relying on the process's current working directory, similar to the advice in Monorepo Setup.

Using the oxc resolver​

eslint-import-resolver-oxc wraps oxc's own resolver and can be used as an import/resolver entry instead of eslint-import-resolver-typescript:

"import/resolver": {
"oxc": {
"tsconfig": {
"configFile": "./tsconfig.json",
"references": "auto"
}
}
}

This resolves imports through oxc's own resolver instead of the TypeScript compiler, which can be faster on large projects. See .oxlintrc.oxc.json in the example for this variant.

Migrating from ESLint​

@oxlint/migrate converts an existing ESLint flat config to Oxlint automatically, and by default retains unsupported plugins — like eslint-plugin-boundaries — through jsPlugins. Your boundaries/* settings and rules carry over unchanged; only double-check the import/resolver setting made it into the generated config, per the finding above.

Further Reading​