Introduction to Oxfmt and Oxlint vs Biome
Explore Oxfmt and Oxlint - two high-performance Rust tools and compare their architecture with Biome
In the modern JavaScript/TypeScript world, we’re witnessing the rise of high-performance Rust tools. While Biome ↗ has established itself as an all-in-one toolchain, Oxc ↗ takes a different approach with specialized tools: Oxfmt (formatter) and Oxlint (linter). This article introduces these two tools and compares their architecture with Biome.
What is Oxfmt?#
Oxfmt (/oʊ-ɛks-fɔːr-mæt/) is a high-performance formatter for the JavaScript ecosystem, built on the Oxc compiler stack. It’s designed to deliver full compatibility with Prettier while dramatically improving performance.
Key Features of Oxfmt#
Multi-language Support#
Oxfmt supports many file formats, with some handled by the native Rust engine and others delegated to the bundled Prettier:
Native formats (run entirely in Rust):
- JavaScript/JSX:
.js,.jsx,.mjs,.cjs - TypeScript/TSX:
.ts,.tsx,.mts,.cts,.d.ts - JSON/JSONC/JSON5:
.json,.jsonc,.json5 - CSS/SCSS/Less:
.css,.scss,.less - GraphQL:
.graphql,.gql - TOML:
.toml - YAML:
.yml,.yaml
Delegated formats (use bundled Prettier):
- HTML, Angular, Vue, Svelte
- Markdown, MDX
- Handlebars, MJML
Built-in Features#
Oxfmt includes features that typically require external Prettier plugins:
- Import sorting: Sort imports with configurable options
- Tailwind CSS class sorting: Automatic Tailwind class sorting (compatible with
prettier-plugin-tailwindcss) - package.json field sorting: Automatic package.json field organization
- Embedded formatting: Format code embedded in template literals (CSS-in-JS, GraphQL, etc.)
Performance#
According to benchmarks, Oxfmt is:
- ~30x faster than Prettier
- 2x faster than Biome
Prettier Compatibility#
Oxfmt currently passes 100% of Prettier’s JavaScript and TypeScript conformance tests. When migrating from recent Prettier versions, formatting differences should not occur.
Oxfmt Architecture#
Oxfmt uses a three-stage formatting system:
graph LR
AST[AST from Parser] --> IRGen[IR Generation]
IRGen --> IR[FormatElement IR]
IR --> Transform[IR Transformation]
Transform --> sort_imports[sort_imports]
sort_imports --> tailwind_sort[Tailwind Sort]
tailwind_sort --> Printer[Printing]
Printer --> Output[Formatted Text]
- IR Generation: AST traversal using
Formattrait - IR Transformation: Apply transformations like
sort_importsand Tailwind sorting - Printing: Printer consumes IR and renders final output
[!NOTE] Oxfmt formatter core is ported from Biome’s
biome_formattercrate, but with completely language-agnostic design.
What is Oxlint?#
Oxlint (/oʊ-ɛks-lɪnt/) is a high-performance linter for JavaScript and TypeScript built on the Oxc compiler stack. It’s designed as a drop-in ESLint replacement with superior performance.
Key Features of Oxlint#
Broad Rule Coverage#
Oxlint includes 870+ built-in rules covering the most popular linter plugins:
- ESLint core rules: Basic JavaScript rules
- TypeScript rules: Including type-aware rules
- Popular plugins: React, Jest, Vitest, Import, Unicorn, jsx-a11y
- Custom JS plugins: Compatible with ESLint plugin ecosystem
Type-aware Linting#
Oxlint uses the native Go port of the TypeScript compiler (tsgo aka TypeScript 7), providing:
- Full TypeScript compatibility
- Same type system behavior as TypeScript
- Type-aware linting aligned with TypeScript semantics
Multi-file Analysis#
Oxlint supports multi-file analysis as a first-class capability:
- Builds project-wide module graph
- Shares parsing and resolution across rules
- Improves checks that depend on cross-file imports
- Avoids the performance cliff often seen with rules like
import/no-cyclein ESLint
Performance#
Oxlint is built for large repositories and CI environments:
- 50-100x faster than ESLint
- Architecture removes structural bottlenecks limiting ESLint performance
- Multi-threaded file processing
Oxlint Architecture#
Oxlint uses parallel execution architecture with dual branch strategy:
graph TB
CLI[CLI Interface] --> LintRunner[LintRunner]
LintRunner --> LintService[LintService]
LintService --> Runtime[Runtime]
Runtime --> process_source[process_source]
process_source --> Parser[Parser]
Parser --> AST[AST]
AST --> LintContext[LintContext]
LintContext --> Linter[Linter]
Linter --> execute_rules[execute_rules]
execute_rules --> strategy1[Strategy 1: nodes → rules]
execute_rules --> strategy2[Strategy 2: rules → nodes]
strategy1 --> RULE_BUCKETS[RULE_BUCKETS]
strategy2 --> RULE_BUCKETS
LintService --> DiagnosticService[DiagnosticService]
DiagnosticService --> Output[Output]
Key Components#
- LintService: Orchestrates linting with parallel execution
- Runtime: Manages paths and file discovery
- LintContext: Contains
Semanticanalysis context - Linter: Core engine executing rules on AST
- Rule Trait: Defines hooks for rule implementation
Dual Branch Strategy#
- Small files (<200k nodes): Iterate (nodes → rules)
- Large files (≥200k nodes): Iterate (rules → nodes) with RULE_BUCKETS
- This avoids CPU cache thrashing on large files
Architecture Comparison with Biome#
1. Design Philosophy#
| Feature | Oxfmt/Oxlint | Biome |
|---|---|---|
| Approach | Specialized tools | All-in-one toolchain |
| Integration | Separate, can be used independently | Integrated formatter + linter |
| Deployment | Traditional CLI | Daemon process for IDE |
| Configuration | Separate config files | Unified biome.json |
2. Formatter Architecture#
| Feature | Oxfmt | Biome |
|---|---|---|
| Stages | 3 stages (IR Gen + Transform + Printing) | 2 stages (Lowering + Printing) |
| IR Design | FormatElement in oxc_formatter_core | FormatElement in biome_formatter |
| Transformations | sort_imports, Tailwind sorting, package.json sort | Minimal built-in transforms |
| Prettier Compatibility | 100% test pass, built-in compatibility | Prettier-inspired but different output |
| Language Support | Native Rust + delegated Prettier | Native Rust implementation |
3. Linter Architecture#
| Feature | Oxlint | Biome |
|---|---|---|
| Rule Count | 870+ built-in rules | Fewer rules, focus on core |
| Type-aware Linting | Tsgo (TypeScript 7 Go port) | Built-in TypeScript support |
| Multi-file Analysis | First-class feature, module graph | Limited support |
| Parallel Execution | Dual branch strategy | Via WorkspaceServer |
| Plugin System | JS plugins (alpha) for ESLint compatibility | Native plugin architecture |
4. Performance#
| Feature | Oxfmt/Oxlint | Biome |
|---|---|---|
| Formatter Speed | 30x faster than Prettier, 2x faster than Biome | 10-20x faster than Prettier |
| Linter Speed | 50-100x faster than ESLint | Similar to Oxlint |
| Memory | Arena allocator, zero-copy | Rowan-based infrastructure |
| Startup | Traditional CLI, fast startup | Daemon process, slower initial start |
5. Migration Path#
| Feature | Oxfmt/Oxlint | Biome |
|---|---|---|
| From Prettier | Direct migration, 100% compatibility | Requires adjustment to different output |
| From ESLint | Drop-in replacement, 870+ rules | Requires rule configuration changes |
| Config Migration | --migrate=prettier, --migrate=biome | Manual config conversion |
| Tooling Integration | Prettier-compatible CLI | Custom Biome CLI |
When to Use Which?#
Choose Oxfmt + Oxlint when#
- You want maximum performance for CI/CD
- Need Prettier compatibility without changing output
- Want separate tools for formatter and linter
- Migrating from ESLint + Prettier with minimum disruption
- Need Tailwind CSS integration built-in
- Want type-aware linting with accurate TypeScript semantics
Choose Biome when#
- You want a unified toolchain in one package
- Need multi-language support (CSS, HTML, GraphQL) native
- Want daemon process for better IDE integration
- Team wants single configuration file
- Don’t need absolute Prettier compatibility
Usage Examples#
Oxfmt#
# Install
npm install -D oxfmt
# Format files
oxfmt src/
# Check formatting
oxfmt --check src/
# Init config
oxfmt --init
# Migrate from Prettier
oxfmt --migrate=prettier
# Migrate from Biome
oxfmt --migrate=biomebashOxlint#
# Install
npm install -D oxlint
# Lint files
oxlint src/
# Type-aware linting
oxlint --tsconfig tsconfig.json src/
# Multi-file analysis
oxlint --enable-import-plugin src/bashBiome#
# Install
npm install -D @biomejs/biome
# Format and lint
biome check src/
# Format only
biome format src/
# Lint only
biome lint src/
# Watch mode
biome check --watch .bashConclusion#
Oxfmt and Oxlint represent the specialized tools approach with maximum performance and Prettier/ESLint compatibility, while Biome provides a unified toolchain with integrated experience.
The choice between the two ecosystems depends on project priorities: performance & compatibility vs integration & simplicity, separate tools vs unified toolchain, existing ecosystem compatibility vs new toolchain adoption.
Both represent the future of JavaScript/TypeScript tooling with high Rust performance, but serve different use cases in the development workflow.