Contents
Oxlint + Oxfmt let you turn coding conventions into automated checks and reduce linting and formatting time. In a monorepo migration reported by REALITY, check time fell from 9.29 seconds to 2.95 seconds while preserving import grouping and custom Tailwind CSS class ordering.
Key Points#
- Choose tools by checking coverage of the repository’s rules and formatting differences.
- Use formatting and safe autofixes for mechanical conventions, and lint errors with clear remedies for prohibited patterns.
- Separate formatting, lint fixes, and tooling changes into commits that are easy to review.
- Review autofixes and run both type checks and tests before merging.
Choose Based on Compatibility#
REALITY evaluated Biome and Oxc in a monorepo built with pnpm workspaces and Turborepo, containing React applications and a shared design system. Class sorting was a key requirement because the repository used Tailwind CSS v4 utilities defined with @theme.
Biome reproduced the basic formatting almost exactly, changing only one of roughly 460 files. Import sorting changed 85 files, and Tailwind class sorting changed 71 files. In this evaluation, Biome’s class sorter did not read the project’s stylesheet, changing the placement of custom utilities.
Oxfmt reproduced the basic formatting tested without differences and supported both the required import grouping and stylesheet-aware Tailwind sorting. These results apply to a specific repository. Whichever tool you choose, verify these four points:
- Formatting differences in representative files.
- Import grouping, blank lines, and side-effect imports.
- Custom Tailwind utilities inside helpers such as
cn()andcva(). - Support for every ESLint rule you currently rely on.
Configure Shared Checks#
Place .oxlintrc.json and .oxfmtrc.json at the repository root. REALITY replaced per-package linting and formatting tasks with a single repository-wide run of each tool, reducing direct tooling dependencies from 14 to three: oxlint, oxfmt, and oxlint-tsgolint.
The reported scripts were:
{
"scripts": {
"lint": "oxlint --type-aware --deny-warnings",
"format": "oxfmt",
"format:check": "oxfmt --check"
}
}Configure Oxfmt’s sortImports to preserve existing grouping, adding a separate side_effect group where needed. For Tailwind sorting, point sortTailwindcss.stylesheet to the design system’s stylesheet and include class-building functions such as cn and cva. Verify that your pinned version supports each setting.
Encode Conventions in Code#
Use the simplest enforcement mechanism that serves each convention’s purpose. Handle import order and Tailwind class order through formatting, and import restrictions through lint rules. Keep decisions that require context, such as when to use function declarations instead of arrow functions, in documentation.
Lint errors should explain both the reason and the replacement. If an application requires a locale-aware navigation wrapper, a useful import restriction message would be: “Use Link from @/i18n/navigation. Importing directly from next/link bypasses this application’s locale handling.” This gives both developers and coding agents the information they need to fix the issue.
Make exceptions explicit and narrow. If you prohibit default exports, use file-pattern overrides to exempt framework files that require them. Comment on disabled rules to explain why they are disabled and under what conditions they should be enabled. Do not force a convention into an unsuitable rule. REALITY decided against adopting a rule restricting function syntax because it produced 174 violations beyond the intended scope.
Migrate in Four Commits#
Keep the migration easy to review.
1. Add Oxlint, Oxfmt, and their configuration while retaining the existing tools. 2. Format the entire repository in a dedicated commit. 3. Apply lint fixes in a separate commit and review the changes for each rule. 4. Switch the scripts and CI, then remove obsolete dependencies and tasks.
During REALITY’s lint-fix stage, 224 files were updated to use import type. Separating these changes from formatting made their purpose easier to follow. Check the details, too. Import sorting initially removed blank lines after side-effect imports, requiring adjustments to the grouping.
Measure the migrated setup under comparable conditions. REALITY disabled Turborepo’s cache for the original setup and used the median of five runs after one warm-up run. Total times were 9.29 seconds for ESLint + Prettier, 2.69 seconds for Biome, and 2.95 seconds for Oxlint + Oxfmt. Each command included about 1.1 seconds of pnpm startup time, and rule coverage differed, so these figures represent the entire workflow rather than an isolated engine benchmark.
Review Fixes and Rule Coverage#
Autofixes can change meaning. REALITY reported that fixes for type imports and duplicate imports interfered with each other, removing a required value import. Another fix changed toHaveBeenCalled() to toHaveBeenCalledWith(), replacing “was called” with “was called with no arguments.” Type checking cannot detect this assertion change. Review fixes and run type checks and tests.
Check rule support individually. This migration dropped the environment variable rule from eslint-plugin-turbo because no equivalent rule was available. Category-level enabling also left rules-of-hooks disabled in the configuration tested. Pin tool versions and review formatting differences when upgrading. Prettier compatibility does not guarantee identical output in every situation.
Agent hooks that run frequently also need attention. A fix that removes unused imports may delete an import before a later edit adds its usage. Add related imports and their usages in a single edit, or run fixes after the changes are complete.
Next Steps#
Create a migration branch, run the candidate tools on your repository, and review formatting differences and unsupported rules before changing CI.
Source: https://zenn.dev/reality_tech/articles/oxc-monorepo-20261006
Contents
