Skip to content

Fix: Oxlint Not Working — .oxlintrc.json Config, Rule Mapping, TypeScript, and ESLint Coexistence

FixDevs ·

Quick Answer

How to fix Oxlint errors — .oxlintrc.json not loaded, rules not matching ESLint output, TypeScript files not linted, plugin-react/typescript wiring, IDE extension setup, and running alongside ESLint.

The Error

You install Oxlint and the config file is silently ignored:

$ oxlint
# Uses defaults, ignores your .oxlintrc.json with custom rules.

Or rules you turned off keep firing:

// .oxlintrc.json
{
  "rules": {
    "no-unused-vars": "off"
  }
}
$ oxlint
src/util.ts:5:7
 no-unused-vars: 'x' is declared but never used

Or TypeScript-specific files give wrong results:

$ oxlint src/
# Only lints .js files, skips .ts entirely.

Or you can’t tell what rules differ between Oxlint and ESLint:

ESLint passes. Oxlint fails on the same file.

Why This Happens

Oxlint is a Rust-based linter from the Oxc project. It’s positioned as a fast, drop-in subset of ESLint — it implements the most popular ESLint rules natively in Rust, but with these caveats:

  • Not every ESLint rule exists. Oxlint has hundreds of rules but not all of ESLint’s 300+ plugins. Missing rules don’t error — they just don’t run.
  • Config syntax is its own. .oxlintrc.json is similar to .eslintrc.json but not identical. ESLint flat config (eslint.config.js) isn’t directly compatible.
  • Plugin namespacing differs. Oxlint groups rules by plugin (typescript, react, jest, etc.) but uses its own internal names. @typescript-eslint/no-unused-vars becomes typescript/no-unused-vars.
  • Designed to run alongside ESLint, not replace it. The recommended workflow is Oxlint as a fast first pass + ESLint for rules Oxlint doesn’t support (yet).

Fix 1: Place .oxlintrc.json in the Right Location

Oxlint looks for .oxlintrc.json (or .oxlintrc) in the directory you run from and walks up:

// .oxlintrc.json — at project root
{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "rules": {
    "no-unused-vars": "off",
    "no-console": "warn",
    "typescript/no-explicit-any": "error"
  },
  "ignorePatterns": [
    "dist/**",
    "node_modules/**"
  ],
  "env": {
    "browser": true,
    "node": true,
    "es2024": true
  }
}

Verify Oxlint picks up the config:

oxlint --print-config

This prints the merged config. If your custom rules don’t appear, the file isn’t being loaded — check the filename (must be .oxlintrc.json, not oxlintrc.json) and that you’re running from a directory under it.

Pro Tip: Pin the schema reference via $schema for editor autocomplete. The schema lives in node_modules/oxlint/configuration_schema.json after install.

Fix 2: Use Oxlint’s Plugin-Prefixed Rule Names

Oxlint groups rules by plugin. To target plugin rules:

{
  "plugins": ["typescript", "react", "jest", "unicorn"],
  "rules": {
    "typescript/no-explicit-any": "error",
    "typescript/no-unused-vars": "off",
    "react/jsx-key": "error",
    "react/no-array-index-key": "warn",
    "jest/no-disabled-tests": "warn",
    "unicorn/prefer-set-has": "error"
  }
}

Without "plugins" listing, plugin rules don’t run — even if you reference them in rules. The plugins enable the rule set; rules overrides severity.

For ESLint users migrating, the mapping is mostly:

ESLint ruleOxlint rule
@typescript-eslint/no-explicit-anytypescript/no-explicit-any
react-hooks/rules-of-hooksreact/rules-of-hooks
import/no-cycleimport/no-cycle
jest/no-disabled-testsjest/no-disabled-tests

The prefix follows the plugin’s “short name.” Run oxlint --help to see the available flags for listing rules in your installed version — recent releases support a flag to print the full rules table.

Common Mistake: Copying ESLint config verbatim. @typescript-eslint/* doesn’t work — drop the @typescript-eslint/ prefix and use typescript/.

Fix 3: Lint TypeScript Explicitly

Oxlint auto-detects .ts, .tsx, .cts, .mts if you pass a directory:

oxlint src/      # Lints all .js, .ts, .jsx, .tsx files

If you pass --ext flags:

oxlint --ext .ts,.tsx src/

Without the right extension list, Oxlint silently skips files.

For TS-specific rules (the typescript/* namespace), Oxlint doesn’t need type information for most rules — it works on the AST alone. A handful of rules that do need types (e.g. type-aware unused checks) are explicitly marked in the docs.

{
  "plugins": ["typescript"],
  "rules": {
    "typescript/no-explicit-any": "error",
    "typescript/consistent-type-imports": "warn",
    "typescript/no-non-null-assertion": "warn"
  }
}

Fix 4: Categories Pre-Configured Sets

Oxlint exposes rule categories you can opt into wholesale:

{
  "categories": {
    "correctness": "error",
    "suspicious": "warn",
    "perf": "warn",
    "pedantic": "off",
    "style": "off",
    "restriction": "off"
  }
}

Or via CLI:

oxlint -W perf -W suspicious src/

correctness is on by default. The other categories opt-in based on how strict you want to be:

  • correctness — likely bugs (unused vars, unreachable code, no-debugger).
  • suspicious — code that’s probably wrong but not certainly.
  • perf — performance smells (for-each on large arrays, etc.).
  • pedantic — stricter style/safety guidance.
  • style — pure formatting/style.
  • restriction — bans on specific patterns (no-console, no-debugger).

For a balanced default, enable correctness + suspicious + perf. Add pedantic once the easier ones are clean.

Fix 5: Run Alongside ESLint, Not Instead

The most pragmatic adoption pattern: Oxlint runs first (catches the common issues fast), then ESLint for plugin rules Oxlint hasn’t ported:

{
  "scripts": {
    "lint": "oxlint && eslint .",
    "lint:fast": "oxlint",
    "lint:full": "eslint ."
  }
}

In eslint.config.js, exclude rules that Oxlint already covers to avoid double-reporting:

import oxlint from "eslint-plugin-oxlint";

export default [
  // ... your other configs
  // This must be the last config in the chain.
  ...oxlint.configs["flat/recommended"],
];

eslint-plugin-oxlint disables ESLint rules that Oxlint already implements — your ESLint pass becomes the “rules Oxlint doesn’t support yet” pass.

Pro Tip: Run Oxlint in pre-commit hooks and CI’s first job; run ESLint in a separate (slower) CI job. Oxlint catches 90% of issues in milliseconds.

Fix 6: IDE Integration

For VS Code:

# Install the Oxc extension from the marketplace:
# "Oxc" by oxc.rs

The extension uses Oxlint’s LSP for in-editor lints. Configure in .vscode/settings.json:

{
  "oxc.enable": true,
  "oxc.lint.run": "onType",  // or "onSave"
  "oxc.path": "./node_modules/.bin/oxlint"
}

For JetBrains IDEs: there’s an Oxc plugin under development; until then, run Oxlint via a file watcher.

For Neovim: use nvim-lspconfig with the Oxc LSP:

require("lspconfig").oxc.setup({})

Common Mistake: Running both ESLint and Oxlint extensions in the IDE at full strength. You’ll see duplicate squiggles. Disable rules Oxlint covers in your ESLint config (see Fix 5).

Fix 7: Ignore Files

Oxlint supports ignorePatterns in .oxlintrc.json and a separate .oxlintignore:

{
  "ignorePatterns": [
    "dist/**",
    "build/**",
    "**/*.generated.ts",
    "vendor/**"
  ]
}

Patterns use gitignore-style globs. For more complex ignore logic:

# .oxlintignore
dist/
build/
coverage/
**/*.min.js
**/*.generated.*

Oxlint also respects .gitignore by default (don’t lint what git ignores). If you need to lint something .gitignored, override via the CLI:

oxlint --no-ignore <file>

Fix 8: Performance Tuning

Oxlint is fast by default. For monorepos with hundreds of thousands of files:

oxlint --threads 8 src/

--threads defaults to the CPU count. Manually capping it helps when CI machines have ulimit issues.

For caching across CI runs (Oxlint doesn’t natively cache yet — but you can scope):

# Only lint files changed since main:
oxlint $(git diff --name-only origin/main...HEAD | grep -E '\.(ts|tsx|js|jsx)$')

Pro Tip: Oxlint typically runs 50-100x faster than ESLint on the same files. If your Oxlint run still feels slow, you’re probably linting too many files — check ignorePatterns.

Still Not Working?

A few less-obvious failures:

  • Rule severity says "warn" but CI fails. Some tools (oxlint --deny-warnings or --max-warnings 0) escalate warnings to failures. Check your CI command.
  • .oxlintrc.json has comments and fails to parse. Standard JSON doesn’t allow comments. Use .oxlintrc.json with no comments, or .oxlintrc.jsonc if your version supports JSONC.
  • Auto-fix not working for some rules. Only a subset of rules are auto-fixable. Use oxlint --fix to apply the fixable ones; the unfixable ones still need manual edits.
  • Disabling a rule per-line with // eslint-disable-line doesn’t work. Oxlint uses its own directive: // oxlint-disable-next-line rule-name. Or use ESLint-compatible directives (Oxlint reads // eslint-disable-next-line too as of recent versions).
  • Plugin not recognized. Check Oxlint’s release notes — plugin support is being added incrementally. A rule from eslint-plugin-import may or may not be in your Oxlint version.
  • Different output between local and CI. Different Oxlint versions. Pin in package.json: "oxlint": "0.10.0" (exact), not ^0.10.0.
  • Lint fails on JSX without React import. Oxlint’s react/react-in-jsx-scope defaults assume classic JSX runtime. Disable it for projects on the automatic runtime: "react/react-in-jsx-scope": "off".
  • Globals not recognized. globals in config or /* global Foo */ directives. Add browser/node globals via env:
{
  "env": {
    "browser": true,
    "node": true
  },
  "globals": {
    "MY_CUSTOM_GLOBAL": "readonly"
  }
}

For related linting and tooling issues, see Biome not working, ESLint config not working, ESLint parsing error unexpected token, and ESLint no-unused-vars false positive.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles