wiki / raw / nkzw-oxlint-config-2026

@nkzw/oxlint-config (v2.0.0, 2026-08-27)

updated 2026-08-28

Original source: https://github.com/nkzw-tech/oxlint-config SHA256: 6fef6bb53023a562273386212f029671683a42ef1ecf7fe51c9f3229b4e4f5b4

@nkzw/oxlint-config (v2.0.0, 2026-08-27)

README.md

@nkzw/oxlint-config

Opinionated Oxlint config with sensible defaults.

Installation & Usage

With Oxlint v1.46+:

npm install -D @nkzw/oxlint-config @nkzw/eslint-plugin eslint-plugin-no-only-tests eslint-plugin-perfectionist eslint-plugin-react-hooks eslint-plugin-unused-imports

[!NOTE] Due to a limitation in Oxlint’s configuration resolver, you have to directly install the JS plugins for now.

In your oxlint.config.ts:

import nkzw from '@nkzw/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({
  extends: [nkzw],
});

Then run pnpm oxlint or npm oxlint.

Philosophy & Principles

Use this configuration if these principles resonate with you:

  • Error, Never Warn: Warnings are noise and get ignored. Either it’s an issue, or it isn’t. This config forces developers to fix problems or explicitly disable the rule with a comment.
  • Strict, Consistent Code Style: When multiple approaches exist, this configuration enforces the strictest, most consistent code style, preferring modern language features and best practices.
  • Prevent Bugs: Problematic patterns such as instanceof are not allowed, forcing developers to choose more robust patterns. Debug-only code such as console.log or test.only are disallowed to avoid unintended logging in production or accidental CI failures.
  • Fast: Slow rules are avoided. For example, TypeScript’s noUnusedLocals check is preferred over no-unused-vars.
  • Don’t get in the way: Subjective or overly opinionated rules (e.g. style preferences) are disabled. Autofixable rules are preferred to reduce friction and save time.

Included Plugins & Rules

This configuration consists of the most useful and least annoying rules from the following ESlint/Oxlint plugins:

Suggestions

This configuration is meant to be used with:

Alternatives

If you are using ESLint, check out @nkzw/eslint-config.

index.js (complete rule configuration)

import { defineConfig } from 'oxlint';

export default defineConfig({
  categories: {
    correctness: 'off',
  },
  env: {
    browser: true,
    builtin: true,
    es2024: true,
    node: true,
  },
  jsPlugins: [
    '@nkzw/eslint-plugin',
    'eslint-plugin-no-only-tests',
    'eslint-plugin-perfectionist',
  ],
  overrides: [
    {
      files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
      rules: {
        'constructor-super': 'off',
        'getter-return': 'off',
        'no-class-assign': 'off',
        'no-const-assign': 'off',
        'no-dupe-class-members': 'off',
        'no-dupe-keys': 'off',
        'no-func-assign': 'off',
        'no-import-assign': 'off',
        'no-new-native-nonconstructor': 'off',
        'no-obj-calls': 'off',
        'no-redeclare': 'off',
        'no-setter-return': 'off',
        'no-this-before-super': 'off',
        'no-undef': 'off',
        'no-unreachable': 'off',
        'no-unsafe-negation': 'off',
        'no-with': 'off',
        'prefer-rest-params': 'error',
        'prefer-spread': 'error',
      },
    },
    {
      files: [
        'server/scripts/**/*.tsx',
        'server/src/app.tsx',
        'server/src/index.tsx',
        'server/src/prisma/seed.tsx',
        'server/src/worker.tsx',
      ],
      rules: {
        'no-console': 'off',
      },
    },
    {
      files: ['server/**/*.tsx'],
      rules: {
        'react/rules-of-hooks': 'off',
      },
    },
  ],
  plugins: ['typescript', 'import', 'oxc', 'react', 'unicorn'],
  rules: {
    '@nkzw/ensure-relay-types': 'error',
    '@nkzw/no-instanceof': 'error',
    '@nkzw/require-use-effect-arguments': 'error',
    '@typescript-eslint/array-type': [
      'error',
      {
        default: 'generic',
      },
    ],
    '@typescript-eslint/no-duplicate-enum-values': 'error',
    '@typescript-eslint/no-empty-object-type': 'error',
    '@typescript-eslint/no-explicit-any': 'error',
    '@typescript-eslint/no-extra-non-null-assertion': 'error',
    '@typescript-eslint/no-misused-new': 'error',
    '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
    '@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
    '@typescript-eslint/no-require-imports': 'error',
    '@typescript-eslint/no-unnecessary-parameter-property-assignment': 'error',
    '@typescript-eslint/no-unnecessary-type-constraint': 'error',
    '@typescript-eslint/no-unsafe-declaration-merging': 'error',
    '@typescript-eslint/no-unsafe-function-type': 'error',
    '@typescript-eslint/no-wrapper-object-types': 'error',
    '@typescript-eslint/prefer-as-const': 'error',
    '@typescript-eslint/prefer-namespace-keyword': 'error',
    '@typescript-eslint/triple-slash-reference': 'error',
    'array-callback-return': 'error',
    'constructor-super': 'error',
    curly: 'error',
    eqeqeq: [
      'error',
      'always',
      {
        null: 'ignore',
      },
    ],
    'for-direction': 'error',
    'getter-return': 'error',
    'import-x/export': 'error',
    'import-x/no-namespace': 'error',
    'no-array-constructor': 'error',
    'no-async-promise-executor': 'error',
    'no-case-declarations': 'error',
    'no-class-assign': 'error',
    'no-compare-neg-zero': 'error',
    'no-cond-assign': 'error',
    'no-console': 'error',
    'no-const-assign': 'error',
    'no-constant-binary-expression': 'error',
    'no-constant-condition': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-delete-var': 'error',
    'no-dupe-class-members': 'error',
    'no-dupe-else-if': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-empty': 'error',
    'no-empty-character-class': 'error',
    'no-empty-pattern': 'error',
    'no-empty-static-block': 'error',
    'no-ex-assign': 'error',
    'no-extra-bind': 'error',
    'no-extra-boolean-cast': 'error',
    'no-fallthrough': 'error',
    'no-func-assign': 'error',
    'no-global-assign': 'error',
    'no-implied-eval': 'error',
    'no-import-assign': 'error',
    'no-invalid-regexp': 'error',
    'no-irregular-whitespace': 'error',
    'no-loss-of-precision': 'error',
    'no-misleading-character-class': 'error',
    'no-new-native-nonconstructor': 'error',
    'no-new-wrappers': 'error',
    'no-nonoctal-decimal-escape': 'error',
    'no-obj-calls': 'error',
    'no-only-tests/no-only-tests': 'error',
    'no-prototype-builtins': 'error',
    'no-redeclare': 'error',
    'no-regex-spaces': 'error',
    'no-self-assign': 'error',
    'no-self-compare': 'error',
    'no-setter-return': 'error',
    'no-shadow-restricted-names': 'error',
    'no-sparse-arrays': 'error',
    'no-this-before-super': 'error',
    'no-throw-literal': 'error',
    'no-undef': 'error',
    'no-unexpected-multiline': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'no-unsafe-negation': 'error',
    'no-unsafe-optional-chaining': 'error',
    'no-unused-expressions': 'error',
    'no-unused-labels': 'error',
    'no-unused-private-class-members': 'error',
    'no-unused-vars': [
      'error',
      {
        args: 'none',
        fix: {
          imports: 'safe-fix',
          variables: 'off',
        },
        varsIgnorePattern: '^_',
      },
    ],
    'no-useless-backreference': 'error',
    'no-useless-catch': 'error',
    'no-useless-escape': 'error',
    'no-useless-rename': 'error',
    'no-var': 'error',
    'no-warning-comments': [
      'error',
      {
        terms: ['@nocommit'],
      },
    ],
    'no-with': 'error',
    'object-shorthand': 'error',
    'oxc/approx-constant': 'error',
    'oxc/bad-bitwise-operator': 'error',
    'oxc/bad-char-at-comparison': 'error',
    'oxc/bad-comparison-sequence': 'error',
    'oxc/bad-min-max-func': 'error',
    'oxc/bad-object-literal-comparison': 'error',
    'oxc/bad-replace-all-arg': 'error',
    'oxc/const-comparisons': 'error',
    'oxc/double-comparisons': 'error',
    'oxc/misrefactored-assign-op': 'error',
    'oxc/missing-throw': 'error',
    'oxc/number-arg-out-of-range': 'error',
    'oxc/uninvoked-array-callback': 'error',
    'perfectionist/sort-enums': [
      'error',
      {
        partitionByComment: true,
        sortByValue: 'always',
      },
    ],
    'perfectionist/sort-heritage-clauses': 'error',
    'perfectionist/sort-interfaces': 'error',
    'perfectionist/sort-jsx-props': 'error',
    'perfectionist/sort-object-types': 'error',
    'perfectionist/sort-objects': [
      'error',
      {
        partitionByComment: true,
      },
    ],
    'prefer-arrow-callback': [
      'error',
      {
        allowNamedFunctions: true,
      },
    ],
    'prefer-const': 'error',
    'prefer-object-has-own': 'error',
    'preserve-caught-error': 'error',
    'react/button-has-type': 'error',
    'react/checked-requires-onchange-or-readonly': 'error',
    'react/display-name': 'error',
    'react/error-boundaries': 'error',
    'react/exhaustive-deps': 'error',
    'react/globals': 'error',
    'react/immutability': 'error',
    'react/incompatible-library': 'error',
    'react/jsx-key': 'error',
    'react/jsx-no-comment-textnodes': 'error',
    'react/jsx-no-duplicate-props': 'error',
    'react/jsx-no-script-url': 'error',
    'react/jsx-no-target-blank': 'error',
    'react/jsx-no-undef': 'error',
    'react/jsx-props-no-spread-multi': 'error',
    'react/no-children-prop': 'error',
    'react/no-danger-with-children': 'error',
    'react/no-direct-mutation-state': 'error',
    'react/no-find-dom-node': 'error',
    'react/no-is-mounted': 'error',
    'react/no-render-return-value': 'error',
    'react/no-string-refs': 'error',
    'react/no-unescaped-entities': 'error',
    'react/no-unknown-property': 'error',
    'react/preserve-manual-memoization': 'error',
    'react/purity': 'error',
    'react/refs': 'error',
    'react/require-render-return': 'error',
    'react/rules-of-hooks': 'error',
    'react/set-state-in-effect': 'error',
    'react/set-state-in-render': 'error',
    'react/static-components': 'error',
    'react/unsupported-syntax': 'error',
    'react/use-memo': 'error',
    'react/void-dom-elements-no-children': 'error',
    'require-yield': 'error',
    'unicorn/catch-error-name': 'error',
    'unicorn/consistent-empty-array-spread': 'error',
    'unicorn/consistent-function-scoping': 'error',
    'unicorn/no-abusive-eslint-disable': 'error',
    'unicorn/no-hex-escape': 'error',
    'unicorn/no-invalid-fetch-options': 'error',
    'unicorn/no-magic-array-flat-depth': 'error',
    'unicorn/no-typeof-undefined': 'error',
    'unicorn/no-unnecessary-slice-end': 'error',
    'unicorn/no-useless-promise-resolve-reject': 'error',
    'unicorn/no-useless-spread': 'error',
    'unicorn/numeric-separators-style': 'error',
    'unicorn/prefer-array-flat-map': 'error',
    'unicorn/prefer-array-index-of': 'error',
    'unicorn/prefer-array-some': 'error',
    'unicorn/prefer-at': 'error',
    'unicorn/prefer-dom-node-append': 'error',
    'unicorn/prefer-import-meta-properties': 'error',
    'unicorn/prefer-native-coercion-functions': 'error',
    'unicorn/prefer-node-protocol': 'error',
    'unicorn/prefer-number-properties': 'error',
    'unicorn/prefer-optional-catch-binding': 'error',
    'unicorn/prefer-set-size': 'error',
    'unicorn/prefer-single-call': 'error',
    'unicorn/prefer-string-raw': 'error',
    'unicorn/prefer-string-replace-all': 'error',
    'unicorn/prefer-string-slice': 'error',
    'unicorn/prefer-structured-clone': 'error',
    'unicorn/prefer-top-level-await': 'error',
    'unicorn/text-encoding-identifier-case': 'error',
    'use-isnan': 'error',
    'valid-typeof': 'error',
  },
});