@clipboard-health/oxlint-config

中文文档
5.1.8发布于 2026/11/05MITTypeScriptCommonJS近 30 天下载 3.8万

Shared Oxlint configuration for Clipboard Health repositories.

原始使用文档
文档目录11 节
  1. Table of contents
  2. Install
  3. Usage
  4. TypeScript config
  5. JSON config
  6. Fast runs
  7. Strict presets
  8. Categories
  9. What is shared
  10. Switch fallback policy
  11. Intentionally disabled rules

@clipboard-health/oxlint-config

Shared Oxlint configuration for Clipboard Health repositories.

Table of contents

Install

npm install @clipboard-health/oxlint-config

The config package includes @clipboard-health/oxlint-plugin for presets that use Clipboard Health custom rules.

Repositories using the frontend preset must also install oxlint-plugin-react-doctor >= 0.9.12.

Requires oxlint >= 1.68.0: the config references rules that older oxlint versions do not register, which fails config parsing outright.

Usage

Use the package's TypeScript helper when a repo needs additive composition. Oxlint's built-in extends is useful for simple inheritance, but it does not let a repo safely append shared plugins, overrides, and similar array fields without re-specifying the shared values.

TypeScript config

Create an oxlint.config.ts in your repo root:

import {
  base,
  createOxlintConfig,
  customRules,
  typeAware,
  vitest,
} from "@clipboard-health/oxlint-config";
import { defineConfig } from "oxlint";

export default defineConfig(
  createOxlintConfig({
    localConfig: {
      categories: {
        correctness: "error",
        nursery: "off",
        pedantic: "error",
        perf: "error",
        restriction: "error",
        style: "off",
        suspicious: "error",
      },
      ignorePatterns: [".agents", "coverage/", "node_modules/"],
      options: {
        denyWarnings: true,
        typeAware: true,
        typeCheck: true,
      },
      rules: {
        "vitest/require-test-timeout": "off",
      },
      settings: {
        node: {
          version: ">=24.14.1",
        },
      },
    },
    presets: [base, customRules, typeAware, vitest],
  }),
);

Available presets:

  • base
  • contractFixtures
  • customRules
  • fast (see Fast runs)
  • frontend
  • react
  • jest
  • strict and strictTypeAware (opt in; see Strict presets)
  • typeAware
  • vitest

Merge behavior:

  • plugins, jsPlugins, overrides, and ignorePatterns append in order
  • rules, settings, options, categories, env, and globals merge left-to-right
  • localConfig always wins over preset values when keys conflict

For React applications, compose the standalone frontend policy with the repository's test runner:

import { createOxlintConfig, frontend, typeAware, vitest } from "@clipboard-health/oxlint-config";
import { defineConfig } from "oxlint";

export default defineConfig(
  createOxlintConfig({
    localConfig: {
      ignorePatterns: ["coverage/"],
    },
    presets: [frontend, typeAware, vitest],
  }),
);

Keep repository architecture rules, import restrictions, and additional JavaScript plugins in localConfig.

base is the organization-wide general JavaScript and TypeScript policy. frontend is the standalone frontend application policy, including React, accessibility, and browser-facing JavaScript rules. typeAware contains rules that require Oxlint's --type-aware mode, and vitest adds the complete Vitest policy. Keep repository-specific exceptions in localConfig.

frontend registers the built-in react, jsx-a11y, import, oxc, typescript, and unicorn plugins. typeAware registers typescript, including when composed with another plugin preset without base.

[!IMPORTANT] Upgrading from versions that omitted these plugin registrations can expose existing lint violations. Run normal and type-aware lint when upgrading, and allow enough CI runner memory for the newly active type-aware analysis. Existing repo-local registrations can remain.

JSON config

Create an .oxlintrc.json in your repo root:

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "extends": ["./node_modules/@clipboard-health/oxlint-config/src/base.json"],
  "categories": {
    "correctness": "error",
    "nursery": "off",
    "pedantic": "error",
    "perf": "error",
    "restriction": "error",
    "style": "off",
    "suspicious": "error"
  },
  "ignorePatterns": [".agents", "coverage/", "node_modules/"],
  "options": {
    "denyWarnings": true,
    "reportUnusedDisableDirectives": "error",
    "typeAware": true,
    "typeCheck": true
  },
  "settings": {
    "node": {
      "version": ">=24.14.1"
    }
  }
}

Use JSON only when simple inheritance is enough. JSON extends still works for shared presets, but repo-local array fields like plugins and overrides will not get the additive merge behavior provided by createOxlintConfig.

For repos using Vitest, extend from vitest.json instead of base.json to include the vitest plugin and rules:

{
  "extends": ["./node_modules/@clipboard-health/oxlint-config/src/vitest.json"]
}

Override shared rules as needed:

{
  "extends": ["./node_modules/@clipboard-health/oxlint-config/src/base.json"],
  "rules": {
    "no-console": "off"
  }
}

Fast runs

base and frontend enable reportUnusedDisableDirectives: "error", which flags oxlint-disable and eslint-disable comments that no longer suppress anything. The default config is therefore the slow one. The option is only accurate on the full, type-aware run: without type information, typescript/* rules cannot fire, so their directives look unused. The fast preset extends the default by setting the option to "off" for quick non-type-aware local and editor runs.

Configoptions.reportUnusedDisableDirectivesUse for
default (base or frontend)"error"The full type-aware lint run and CI
default + fast"off"Quick non-type-aware local and editor runs

fast sets nothing else, so the two configs are otherwise identical. Compose it last in presets; localConfig still wins if a repository sets the option itself.

A repository keeps its rules in oxlint.config.ts and derives the fast config from it, so there is one place to edit rules:

// oxlint.config.ts
import { base, createOxlintConfig, typeAware } from "@clipboard-health/oxlint-config";
import { defineConfig } from "oxlint";

export default defineConfig(
  createOxlintConfig({
    presets: [base, typeAware],
  }),
);
// oxlint.config.fast.ts
import { fast } from "@clipboard-health/oxlint-config";
import { defineConfig } from "oxlint";

import defaultConfig from "./oxlint.config.ts";

export default defineConfig({ extends: [defaultConfig], ...fast });
{
  "scripts": {
    "lint": "oxlint --type-aware --type-check",
    "lint:fast": "oxlint --config oxlint.config.fast.ts"
  }
}

lint loads oxlint.config.ts and runs the type-aware rules with unused-directive reporting. lint:fast selects the fast config and omits --type-aware, so the typeAware preset's rules do not run. Keep typeAware and typeCheck out of the config options and on the lint command line, as above, so the fast config does not need to override them.

The JSON extends entry point base.json includes the option; set options.reportUnusedDisableDirectives to "off" after extending it for a fast config.

Strict presets

These rules catch real bugs but fire often in legacy code, so they are opt-in. Adopt them per repository: add the presets, then suppress existing violations inline in the same change so new code meets the bar.

PresetRuleCatches
strict@clipboard-health/no-ambiguous-positional-parametersTwo or more positional parameters where two share a type (callers can swap them) or one is a boolean (unreadable at call sites). A function with a single parameter is exempt, and so are test files.
strictTypeAwaretypescript/strict-boolean-expressionsTruthiness checks on numbers and enums, where 0 reads as missing. Strings stay allowed: treating "" as missing is usually intended.
presets: [base, customRules, strict, typeAware, strictTypeAware, vitest],

Give each suppression a reason: // oxlint-disable-next-line <rule> -- <reason>.

Categories

This config is tuned for agent-written code: enforce rules that prevent bugs or help agents work faster, ignore rules that only encode human style preferences. Categories are applied as a denylist (enable the category, then disable individual rules that are noise) rather than an allowlist, so new bug-catching rules in a category are adopted automatically as oxlint ships them.

CategorySettingWhy
correctness, suspicious, perferrorLikely bugs and performance problems.
restrictionerrorCarries high-value guardrails: typescript/no-explicit-any, typescript/no-non-null-assertion, no-var, unicorn/no-abusive-eslint-disable.
pedanticerrorCarries eqeqeq, the typescript/no-unsafe-* family, typescript/no-misused-promises, typescript/switch-exhaustiveness-check, array-callback-return.
styleoffIdiomatic/consistency rules with no bug-prevention value. Rules kept are opted back in explicitly: deliberate consistency picks (curly, no-else-return) plus bug/security rules oxlint files under style (no-new-func, guard-for-in, import/no-mutable-exports).
nurseryoffRules still under development; too unstable for agent-written code.

style and nursery are off, not denylisted, because their future rules are noise rather than signal — there is nothing worth adopting automatically. Every style rule kept is therefore listed explicitly in base.json.

What is shared

The package includes:

  • base.json: the backwards-compatible JSON preset for simple extends usage
  • vitest.json: extends base.json with the vitest plugin and rules for JSON extends usage
  • base preset: shared plugins, rules, and overrides exported for TypeScript composition
  • frontend preset: shared frontend JavaScript, React Doctor, React, and JSX accessibility policy
  • typeAware preset: rules that require Oxlint's type-aware execution mode
  • react, jest, vitest presets: additive plugin presets for common repo types
  • contractFixtures preset: warning-level enforcement that MSW, Playwright, and exported mock fixtures are parsed by producer-owned contract response schemas
  • customRules preset: registers the ESLint-independent Clipboard plugin and reproduces the shared controller, module, contract, cross-contract-import, and contract-package-test enforcement scopes. Set rule options, such as the controller rule's forbidTsRestHandler, with a local override
  • createOxlintConfig: helper for composing presets with repo-local config

Switch fallback policy

typescript/switch-exhaustiveness-check remains an error with considerDefaultExhaustiveForUnions: true. An explicit default defines the policy for unmatched values: rejecting them, returning an optional result, or applying a fallback can all be intentional. This also permits defaults for legacy values that runtime data contains but TypeScript does not represent. The rule still reports omitted union members when a switch has no default.

This is a deliberate tradeoff: adding a union or enum member does not trigger a diagnostic at a switch that already has a default. Repositories or closed dispatchers that need every new member reviewed can opt into considerDefaultExhaustiveForUnions: false with a local rule override. Keep runtime fallbacks where their contracts need them; do not introduce throws merely to satisfy a lint check. An explicit default does not prove that its business policy is correct.

Requiring repeated empty labels before a fallback conflicts with unicorn/no-useless-switch-case and makes complexity count those labels as extra paths. Both guards remain enabled. See the upstream option documentation for the stricter future-member behavior. Upgrade to a published package release before removing a consumer's local rule disable.

Intentionally disabled rules

base.json cannot hold comments, so the reasoning for non-obvious "off" entries lives here (audited against clipboard-health on oxlint 1.60, 2026-06-11):

  • no-throw-literal (TypeScript files only): typescript/only-throw-error replaces this syntax-only rule and uses types to recognize Error values. The base rule can reject deferred Error values held in typed variables. The upstream replacement guidance requires disabling the base rule to avoid incorrect diagnostics. The override covers .ts, .tsx, .mts, and .cts; JavaScript retains no-throw-literal, and TypeScript retains only-throw-error for real non-Error throws. Run type-aware lint in CI. After upgrading to a published release with this override, consumers can remove a repository-wide no-throw-literal: off; an explicit matching local file override can opt back into the syntax-only rule.
  • typescript/strict-void-return: TypeScript deliberately permits a value-returning function where a void callback is expected, because the caller discards the result. This supports ordinary forEach callbacks that call Set.add, Map.set, or Array.push, and callback APIs that return a synchronous handle. The rule rejects those valid uses; its allowReturnAny option only relaxes any returns. Keep no-misused-promises and no-floating-promises enabled for async misuse. TypeScript still rejects a value returned from a function explicitly declared to return void.
  • typescript/no-unnecessary-template-expression: simplifying string expressions inside template literals is a style preference. Explicit string normalization and string-enum formatting are allowed. Keep restrict-template-expressions and no-base-to-string enabled to detect unsafe interpolation instead.
  • typescript/no-unnecessary-type-conversion: removing Number, String, Boolean, or .toString() conversions based on a declared type is a style preference. At boundaries where runtime data does not match its declared type, removal can change the value or its type. Explicit coercion is allowed; it does not replace runtime schema validation or the unsafe-operation guards.
  • typescript/no-unnecessary-boolean-literal-compare: comparisons such as value === true, value === false, and value !== false can encode an explicit boundary policy even when a static type says boolean. At runtime, feature-flag providers and persisted records can still supply non-boolean, missing, or nullable values; simplifying these comparisons changes how those values are handled. Keep the comparisons intact and turn off this redundancy diagnostic in both shared presets. The tradeoff is losing the warning for comparisons over validated booleans; other type-aware correctness and unsafe-operation rules remain enabled.
  • typescript/no-useless-default-assignment: a required static type does not prove that runtime data contains the field. Removing an initializer can change the value when database records, API responses, feature flags, or session payloads are incomplete. Keep these runtime defaults; this rule only signals a default that appears unreachable by its type. Disabling it accepts losing that redundant-code signal in validated code so defensive defaults remain available at unvalidated boundaries. The compiler and other type-aware correctness and unsafe-operation rules remain enabled.
  • no-extra-boolean-cast: Boolean(value) in a condition makes numeric and enum truthiness explicit. Removing it is runtime-equivalent for an ordinary condition, but reintroduces the typescript/strict-boolean-expressions diagnostic because that rule rejects implicit numeric or enum truthiness. Treating the explicit conversion as redundant style conflicts with that type-aware policy; keep the strict boolean guard and leave this stylistic rule off in both the base and standalone frontend presets.
  • typescript/no-invalid-void-type: valid completion APIs use generic calls such as Promise.withResolvers<void>() and http.get<void>(). Even with allowInGenericTypeArguments: true, the rule rejects call-expression type arguments; this restriction is inherited from typescript-eslint, rather than an Oxlint port difference. Changing these APIs to undefined can change their public signatures: a void resolver permits resolve() without an argument. Keep the other TypeScript correctness and unsafe-operation guards enabled.
  • typescript/consistent-return: optional lookups and filtered callbacks legitimately mix bare returns with value returns; the rule also reports catch paths that call a declared never helper. Its treatUndefinedAsUnspecified option changes how explicit undefined is classified, rather than recognizing these contracts. Upstream recommends TypeScript's noImplicitReturns compiler option instead. Enable that option and run compiler checks in CI; strict alone does not enable it. Repositories without that compiler guard must keep an explicit local "typescript/consistent-return": "error" until they adopt a replacement. array-callback-return remains enabled for missing callback results. Existing suppressed return-type errors and ambiguous fallthrough contracts remain code debt.
  • typescript/no-unsafe-enum-comparison: named constants such as HTTP statuses are compared with wire numbers and serialized strings. The shared TypeScript guidance also prefers const objects over enums. This rule instead requires matching nominal enum types, rejecting those boundary comparisons and input validation. Disabling it also permits matching raw enum literals: it does not enforce using a named member in that case. The compiler still rejects incompatible distinct enums and out-of-range literals; it does not replace every check this rule can make. Repositories that require nominal enum identity can explicitly set this rule to "error" in localConfig.rules. The upstream guidance describes this tradeoff; the rule has no configuration option for scalar-boundary comparisons. Other enum guards, including duplicate-value detection, remain enabled.
  • typescript/consistent-type-imports: oxlint's port is not emitDecoratorMetadata-aware (even type-aware with the flag in the tsconfig chain), so it flags NestJS constructor-injected classes as type-only. Applying its fix converts DI tokens to import type, which SWC erases from design:paramtypes metadata, breaking injection at runtime. Do not enable in NestJS repos until oxlint matches typescript-eslint's decorator handling.
  • jest/no-confusing-set-timeout (jest preset): false-positive explosion — when a jest setup file calls jest.setTimeout, the rule flags spec files that contain no setTimeout call at all (265k diagnostics across 764 clean files). The vitest preset carries no jest/* keys at all: under oxlint ≥1.68 with only the vitest plugin enabled, jest/* config keys are silently ignored, and jest-plugin-only rules (such as this one and jest/prefer-ending-with-an-expect) cannot fire — vitest/no-confusing-set-timeout is not a registered rule name, so an "off" entry for it fails config parsing.
  • import/no-named-as-default / import/no-named-as-default-member: low signal; they flag legitimate default-export import patterns far more often than real mistakes (870 hits, ~0 bugs).
  • vitest/no-conditional-in-test (vitest preset): the rule treats every conditional inside a test, including nested mock callbacks and table-driven input construction, as a violation. Stateful fakes, concurrency barriers, and conditional fixture properties need branches without weakening the assertions. The rule has no option to distinguish these cases; extracting the same branches into helpers only hides them from its test-ancestor heuristic. Keep vitest/expect-expect, vitest/valid-expect, and vitest/require-to-throw-message enabled to check assertions.
  • prefer-destructuring: style preference with no bug-prevention value; not worth the churn as an agent guardrail.

The following were turned off after an audit of 13 consumer repos (repo-local "off" entries, inline disable comments, and a run of the plain base + vitest presets on 7 repos, 2026-10-14):

  • no-await-in-loop: sequential awaits are usually intentional (rate limits, Mongo sessions, ordering). The rule pushes agents toward Promise.all, which can cause concurrency bugs. It had 1,007 inline disables across 9 repos.
  • node/no-process-env: off locally in 8 of 13 repos. Repos that centralize configuration can turn it back on.
  • oxc/no-map-spread: a micro-optimization. Its suggested fix mutates with Object.assign.
  • unicorn/consistent-function-scoping: moving closures to module scope often makes code harder to read.
  • unicorn/no-useless-undefined: conflicts with TypeScript signatures that need an explicit undefined.
  • Stylistic, in the restriction category: no-plusplus, typescript/explicit-member-accessibility, typescript/no-import-type-side-effects, unicorn/import-style.

The same audit removed the explicit opt-ins for typescript/array-type and unicorn/filename-case. They are style rules, so the style category now keeps them off.

When adopting the callback and coercion defaults, first upgrade to a published release containing them, then remove redundant local off entries for typescript/strict-void-return, typescript/no-unnecessary-template-expression, and typescript/no-unnecessary-type-conversion. Repositories that require these stricter conventions can opt back in with local error overrides. Keep no-misused-promises and no-floating-promises enabled: allowing discarded synchronous results does not permit unhandled async failures. Keep restrict-template-expressions and no-base-to-string enabled for unsafe interpolation.

The test-file override in base.json disables the typescript/no-unsafe-* family, unbound-method, no-non-null-assertion, and restrict-template-expressions for test files: mocks, expect.any, and createMock make these rules ~90% noise in tests (mirrors the long-standing eslint-config override), while keeping them enforceable for production code. The JSON Vitest preset extends base.json, but the exported TypeScript vitest preset loader reads only its plugins and rules. The exported preset therefore carries the same typescript/unbound-method: off rule for the base test-file globs. A later localConfig can still turn the rule back on for selected tests.

版本与发布记录

@clipboard-health/oxlint-config 共发布 138 个版本,首次发布于 2026/04/09;过去 12 个月发布了 138 个版本。

版本发布日期距今
5.1.8latest2026/11/054 天前
5.1.72026/11/054 天前
5.1.62026/11/055 天前
5.1.52026/11/045 天前
5.1.42026/11/045 天前
5.1.32026/11/036 天前

关于 @clipboard-health/oxlint-config 的常见问题

@clipboard-health/oxlint-config 是什么?

Shared Oxlint configuration for Clipboard Health repositories.

如何安装 @clipboard-health/oxlint-config?

在项目目录运行 npm install @clipboard-health/oxlint-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:oxlint(>=1.68.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@clipboard-health/oxlint-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@clipboard-health/oxlint-config 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@clipboard-health/oxlint-config 可以商用吗?

@clipboard-health/oxlint-config 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@clipboard-health/oxlint-config 的下载量有多少?

根据 npm 官方下载统计,@clipboard-health/oxlint-config 在 2026/10/10 – 2026/11/08 这 30 天内被下载 38,208 次,日均约 1,274 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@clipboard-health/oxlint-config 还在维护吗?

最新版本 5.1.8 发布于 2026/11/05(4 天前);至今共发布 138 个版本,其中过去 12 个月发布了 138 个;首次发布于 2026/04/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。