Skip to content

ADR-0013: Migrate to Oxlint and Oxfmt ​

Last Updated: 2026-03-15 Status: Active Context: Decksmith


Context ​

ADR-0004 established ESLint + Prettier as the code quality toolchain. Both tools have been the industry standard for years, but the Rust-based tooling ecosystem matured significantly in 2025–2026:

  • Oxfmt (beta, February 2026): A Prettier-compatible formatter written in Rust. Claims 100% formatting parity with Prettier for JS/TS, runs ~30x faster. Official migration CLI provided. Already adopted by Turborepo, Vue.js core, and Sentry.
  • Oxlint (1.0 stable, 2026): A Rust-based linter with 695+ rules. Natively supports the rule sets we use: unicorn, import/no-cycle, react, jsx-a11y. As of March 11, 2026, a JS Plugins Alpha enables running standard ESLint v9-compatible plugins without modification — any gap in native rule coverage can be filled with a JS plugin.
  • tsgolint (alpha): Type-aware linting via Oxlint's --type-aware flag. Covers 43–59 of typescript-eslint's type-aware rules. JS plugins fill any remaining gap in coverage from strictTypeChecked.

The project is still pre-feature (Phase 0 infrastructure), making this the ideal moment to migrate before the codebase grows.

Current Decision ​

Replace Prettier with Oxfmt and ESLint with Oxlint across the entire monorepo.

Migration will use the official CLIs:

  1. pnpm oxfmt --migrate=prettier to convert .prettierrc.json → .oxfmtrc.jsonc
  2. npx @oxlint/migrate --type-aware to convert eslint.config.js files → .oxlintrc.json

The existing packages/config/eslint/ directory is replaced with packages/config/oxlint/.

Rationale ​

This decision aligns with Decksmith's core values:

Deterministic behavior: Oxfmt guarantees identical formatting output to Prettier on JS/TS, so no reformatting churn during migration. The --migrate=prettier flag reads the existing config and produces equivalent output.

Maintainability: Rust-based tools are significantly faster (30x formatter, ~10–20x linter). In a Turborepo monorepo with many packages, this directly reduces developer feedback loop and CI time.

Clarity over cleverness: Both tools have explicit config files (.oxfmtrc.jsonc, .oxlintrc.json) with a clear structure. The migration CLIs produce readable, auditable output.

No Biome: Biome was evaluated and rejected for the same reasons documented in ADR-0004 (smaller ecosystem, fewer rules, migration risk). Oxlint and Oxfmt each specialize in one task, following Unix philosophy — they are not attempting to be an all-in-one tool. This also means they can be updated independently.

Trade-offs ​

Benefits:

  • ~30x faster formatting; significantly faster linting — reduces CI time and editor feedback latency
  • Official migration CLIs handle the conversion automatically; minimal manual work
  • import/no-cycle, unicorn, react, jsx-a11y all natively supported — no plugin gaps for our current rule set
  • JS Plugins Alpha means any ESLint plugin can fill future gaps — not locked out of the ecosystem
  • Type-aware rules via tsgolint cover the most critical subset of strictTypeChecked
  • Smaller node_modules surface: removes eslint, prettier, typescript-eslint, eslint-plugin-*, eslint-config-prettier, eslint-plugin-prettier

Costs:

  • tsgolint is alpha — not all strictTypeChecked rules are covered yet (43–59 of the full set)
  • JS Plugins Alpha introduces a new dependency model (JS plugins in an otherwise Rust tool)
  • Team must learn new config file formats (.oxfmtrc.jsonc, .oxlintrc.json)
  • Oxfmt is still in beta; API may change before 1.0

Risks:

  • tsgolint rule gaps: Some type-aware rules from typescript-eslint/strictTypeChecked may not be enforced. Mitigation: audit the migrated config against the original ESLint config; add JS plugins for critical missing rules; document any intentionally dropped rules in Evolution History.
  • Oxfmt beta instability: If Oxfmt introduces a breaking config change before 1.0, we need to update .oxfmtrc.jsonc. Mitigation: pin the Oxfmt version in pnpm-workspace.yaml catalog; only update after reviewing the changelog.
  • Editor integration: Oxlint and Oxfmt VSCode extensions exist but may be less mature than the ESLint and Prettier extensions. Mitigation: document setup in CLAUDE.md or a developer guide.

Evolution History ​

2026-03-15: Initial decision ​

  • Decided to migrate from ESLint + Prettier to Oxlint + Oxfmt
  • Key driver: Oxfmt beta reached Prettier parity with official migration CLI; Oxlint 1.0 + JS Plugins Alpha covers all rule sets used in packages/config/eslint/base.js
  • Timing: pre-feature phase makes this the lowest-friction migration window
  • Biome reconsidered and rejected for the same reasons as ADR-0004 — single-task tools preferred
  • tsgolint alpha coverage gap accepted as acceptable risk given JS plugin escape hatch
  • Supersedes the tooling choice in ADR-0004 (Prettier + ESLint); ADR-0004 remains active for all other formatting standards (semi, quotes, printWidth, etc.)

References ​

Built with VitePress