<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>The Oxidation Compiler Blog</title>
        <link>https://oxc.rs</link>
        <description></description>
        <lastBuildDate>Mon, 18 May 2026 06:03:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>© 2026 VoidZero Inc. and Oxc contributors.</copyright>
        <item>
            <title><![CDATA[Oxlint General Availability]]></title>
            <link>https://oxc.rs/blog/2023-12-12-announcing-oxlint</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2023-12-12-announcing-oxlint</guid>
            <pubDate>Tue, 12 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the initial General Availability release of Oxlint.</strong> For the latest stable release with significantly more features and improvements, see the <a href="/blog/2025-06-10-oxlint-stable.html">Oxlint v1.0 Stable announcement</a>.</p>
</Alert>
<p>We are thrilled to announce that oxlint is now generally available!
This milestone signifies our team's ability to promptly address and triage issues.</p>
<p>Oxlint is a JavaScript linter designed to catch erroneous or useless code without requiring any configurations by default.</p>
<h2 id="how-to-use" tabindex="-1">How to Use <a class="header-anchor" href="#how-to-use" aria-label="Permalink to “How to Use”">&#8203;</a></h2>
<p>At this stage, oxlint is <strong>not intended to fully replace ESLint</strong>; it serves as an enhancement when ESLint's slowness becomes a bottleneck in your workflow.</p>
<p>For faster feedback loops, we recommend running oxlint before ESLint in your lint-staged or CI setup, considering it only takes a few seconds to run on large codebases.</p>
<p>To test oxlint in your JavaScript / TypeScript codebase, simply execute the following command at the root directory of your repository:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>deno</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">deno</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> npm:oxlint@latest</span></span></code></pre>
</div></td></tr></tbody></table>
<p>Alternatively, refer to the <a href="/docs/guide/usage/linter.html">installation guide</a> for detailed instructions.</p>
<h2 id="design" tabindex="-1">Design <a class="header-anchor" href="#design" aria-label="Permalink to “Design”">&#8203;</a></h2>
<h3 id="_50-100-times-faster-than-eslint" tabindex="-1">50-100 Times Faster than ESLint <a class="header-anchor" href="#_50-100-times-faster-than-eslint" aria-label="Permalink to “50-100 Times Faster than ESLint”">&#8203;</a></h3>
<p>In real-world scenarios, Shopify reported that their 75 CI minutes ESLint run is now only 10 seconds.</p>
<p>From Jason Miller, Shopify DX and creator of Preact:</p>
<blockquote>
<p>oxlint has been a massive win for us at Shopify. Our previous linting setup took 75 minutes to run, so we were fanning it out across 40+ workers in CI.</p>
<p>By comparison, oxlint takes around 10 seconds to lint the same codebase on a single worker, and the output is easier to interpret.</p>
<p>We even caught a few bugs that were hidden or skipped by our old setup when we migrated!</p>
</blockquote>
<p>The majority of the performance gains stem from Oxlint being purposefully designed for performance, utilizing Rust and parallel processing as key factors.</p>
<h3 id="lint-for-correctness" tabindex="-1">Lint for Correctness <a class="header-anchor" href="#lint-for-correctness" aria-label="Permalink to “Lint for Correctness”">&#8203;</a></h3>
<p>Oxlint defaults to identifying erroneous, redundant, or confusing code — prioritizing correctness over unnecessary nitpicking rules (categorized as <code>perf</code>, <code>suspicious</code>, <code>pedantic</code>, or <code>style</code>), which are disabled by default.</p>
<h3 id="ease-of-use" tabindex="-1">Ease of Use <a class="header-anchor" href="#ease-of-use" aria-label="Permalink to “Ease of Use”">&#8203;</a></h3>
<p>Setting up new JavaScript / TypeScript codebases is becoming increasingly complex.
There's a high likelihood of encountering compatibility issues among your tools, potentially resulting in hours of wasted time.</p>
<p>That's why we designed oxlint to be zero-config out of the box; even Node.js is not a requirement.
Most adjustments can be made through the command-line, and reading from an ESLint configuration file is currently in progress.</p>
<h3 id="enhanced-diagnostics" tabindex="-1">Enhanced Diagnostics <a class="header-anchor" href="#enhanced-diagnostics" aria-label="Permalink to “Enhanced Diagnostics”">&#8203;</a></h3>
<p>Understanding linter messages can be challenging.
Oxlint aims to simplify this by pinpointing root causes and providing helpful messages — eliminating the need for lengthy rule documentation reading, saving valuable time.</p>
<p>Running <code>oxlint -D perf</code> in the <a href="https://github.com/microsoft/vscode" target="_blank" rel="noreferrer">vscode repository</a>:</p>
<img width="100%" src="https://github.com/oxc-project/oxc/assets/1430279/094a3b24-0433-42ae-aad2-48a7dec2b985" >
<h3 id="consolidated-rules" tabindex="-1">Consolidated Rules <a class="header-anchor" href="#consolidated-rules" aria-label="Permalink to “Consolidated Rules”">&#8203;</a></h3>
<p>Oxlint does not provide a plugin system yet, but we are actively consolidating rules from popular plugins like TypeScript, React, Jest, Unicorn, JSX-a11y and Import.</p>
<p>We recognize the importance of plugins in the JavaScript ecosystem and are also investigating a DSL-based plugin system.</p>
<p>However, you might appreciate a standalone linter — no need to manage a list of plugin dependencies,
navigate through <a href="https://github.com/antfu/eslint-ts-patch" target="_blank" rel="noreferrer">compatibility issues</a>,
or <a href="https://github.com/import-js/eslint-plugin-import/pull/2504#issuecomment-1191057877" target="_blank" rel="noreferrer">resort to forked plugins due to version constraints</a>.</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the initial General Availability release of Oxlint.</strong> For the latest stable release with significantly more features and improvements, see the <a href="/blog/2025-06-10-oxlint-stable.html">Oxlint v1.0 Stable announcement</a>.</p>
</Alert>
<p>We are thrilled to announce that oxlint is now generally available!
This milestone signifies our team's ability to promptly address and triage issues.</p>
<p>Oxlint is a JavaScript linter designed to catch erroneous or useless code without requiring any configurations by default.</p>
<h2 id="how-to-use" tabindex="-1">How to Use <a class="header-anchor" href="#how-to-use" aria-label="Permalink to “How to Use”">&#8203;</a></h2>
<p>At this stage, oxlint is <strong>not intended to fully replace ESLint</strong>; it serves as an enhancement when ESLint's slowness becomes a bottleneck in your workflow.</p>
<p>For faster feedback loops, we recommend running oxlint before ESLint in your lint-staged or CI setup, considering it only takes a few seconds to run on large codebases.</p>
<p>To test oxlint in your JavaScript / TypeScript codebase, simply execute the following command at the root directory of your repository:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>deno</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">deno</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> npm:oxlint@latest</span></span></code></pre>
</div></td></tr></tbody></table>
<p>Alternatively, refer to the <a href="/docs/guide/usage/linter.html">installation guide</a> for detailed instructions.</p>
<h2 id="design" tabindex="-1">Design <a class="header-anchor" href="#design" aria-label="Permalink to “Design”">&#8203;</a></h2>
<h3 id="_50-100-times-faster-than-eslint" tabindex="-1">50-100 Times Faster than ESLint <a class="header-anchor" href="#_50-100-times-faster-than-eslint" aria-label="Permalink to “50-100 Times Faster than ESLint”">&#8203;</a></h3>
<p>In real-world scenarios, Shopify reported that their 75 CI minutes ESLint run is now only 10 seconds.</p>
<p>From Jason Miller, Shopify DX and creator of Preact:</p>
<blockquote>
<p>oxlint has been a massive win for us at Shopify. Our previous linting setup took 75 minutes to run, so we were fanning it out across 40+ workers in CI.</p>
<p>By comparison, oxlint takes around 10 seconds to lint the same codebase on a single worker, and the output is easier to interpret.</p>
<p>We even caught a few bugs that were hidden or skipped by our old setup when we migrated!</p>
</blockquote>
<p>The majority of the performance gains stem from Oxlint being purposefully designed for performance, utilizing Rust and parallel processing as key factors.</p>
<h3 id="lint-for-correctness" tabindex="-1">Lint for Correctness <a class="header-anchor" href="#lint-for-correctness" aria-label="Permalink to “Lint for Correctness”">&#8203;</a></h3>
<p>Oxlint defaults to identifying erroneous, redundant, or confusing code — prioritizing correctness over unnecessary nitpicking rules (categorized as <code>perf</code>, <code>suspicious</code>, <code>pedantic</code>, or <code>style</code>), which are disabled by default.</p>
<h3 id="ease-of-use" tabindex="-1">Ease of Use <a class="header-anchor" href="#ease-of-use" aria-label="Permalink to “Ease of Use”">&#8203;</a></h3>
<p>Setting up new JavaScript / TypeScript codebases is becoming increasingly complex.
There's a high likelihood of encountering compatibility issues among your tools, potentially resulting in hours of wasted time.</p>
<p>That's why we designed oxlint to be zero-config out of the box; even Node.js is not a requirement.
Most adjustments can be made through the command-line, and reading from an ESLint configuration file is currently in progress.</p>
<h3 id="enhanced-diagnostics" tabindex="-1">Enhanced Diagnostics <a class="header-anchor" href="#enhanced-diagnostics" aria-label="Permalink to “Enhanced Diagnostics”">&#8203;</a></h3>
<p>Understanding linter messages can be challenging.
Oxlint aims to simplify this by pinpointing root causes and providing helpful messages — eliminating the need for lengthy rule documentation reading, saving valuable time.</p>
<p>Running <code>oxlint -D perf</code> in the <a href="https://github.com/microsoft/vscode" target="_blank" rel="noreferrer">vscode repository</a>:</p>
<img width="100%" src="https://github.com/oxc-project/oxc/assets/1430279/094a3b24-0433-42ae-aad2-48a7dec2b985" >
<h3 id="consolidated-rules" tabindex="-1">Consolidated Rules <a class="header-anchor" href="#consolidated-rules" aria-label="Permalink to “Consolidated Rules”">&#8203;</a></h3>
<p>Oxlint does not provide a plugin system yet, but we are actively consolidating rules from popular plugins like TypeScript, React, Jest, Unicorn, JSX-a11y and Import.</p>
<p>We recognize the importance of plugins in the JavaScript ecosystem and are also investigating a DSL-based plugin system.</p>
<p>However, you might appreciate a standalone linter — no need to manage a list of plugin dependencies,
navigate through <a href="https://github.com/antfu/eslint-ts-patch" target="_blank" rel="noreferrer">compatibility issues</a>,
or <a href="https://github.com/import-js/eslint-plugin-import/pull/2504#issuecomment-1191057877" target="_blank" rel="noreferrer">resort to forked plugins due to version constraints</a>.</p>
<hr>
<p>Happy linting and have a joyful holiday season!</p>
<p>To get started, follow the <a href="/docs/guide/usage/linter.html">installation guide</a>,
learn more about the <a href="/docs/guide/introduction.html">oxc project</a>,
or discuss on <a href="https://news.ycombinator.com/item?id=38652887" target="_blank" rel="noreferrer">Hacker News</a>.</p>
]]></content:encoded>
            <author>Boshen</author>
        </item>
        <item>
            <title><![CDATA[Oxlint Import Plugin Alpha]]></title>
            <link>https://oxc.rs/blog/2024-05-04-import-plugin-alpha</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2024-05-04-import-plugin-alpha</guid>
            <pubDate>Sat, 04 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><p>We are excited to announce an alpha release for <code>oxlint --import-plugin</code>, a port of <a href="https://npmx.dev/package/eslint-plugin-import" target="_blank" rel="noreferrer"><code>eslint-plugin-import</code></a>.</p>
<p>This port aims to resolve all known issues associated with <code>eslint-plugin-import</code>:</p>
<ul>
<li>Performance - execution time exceeding one minute when certain rules are enabled</li>
<li>Dependency size - 188 dependencies totaling 30M</li>
<li>Backwards compatibility - the necessity to <a href="https://github.com/import-js/eslint-plugin-import/pull/2447#issuecomment-1117384140" target="_blank" rel="noreferrer">support Node.js v4.0.0</a></li>
<li>Dependency compatibility - the need to replace it with <a href="https://npmx.dev/package/eslint-plugin-import-x" target="_blank" rel="noreferrer"><code>eslint-plugin-import-x</code></a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/issues/2948" target="_blank" rel="noreferrer">Upgrading to ESLint v9</a></li>
</ul>
<h2 id="what-s-in-the-release" tabindex="-1">What's in the release? <a class="header-anchor" href="#what-s-in-the-release" aria-label="Permalink to “What's in the release?”">&#8203;</a></h2>
<p>This alpha release is expected to work if your project is in ESM (ECMAScript Modules).</p>
<p>If path aliases (e.g. <code>@/foo</code>) are required through <a href="https://www.typescriptlang.org/tsconfig/#paths" target="_blank" rel="noreferrer">tsconfig.compilerOptions.paths</a>,
the <code>--tsconfig</code> option can be used:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>npx oxlint@latest --tsconfig ./tsconfig.json --import-plugin</span></span></code></pre>
</div><p>The rules that are enabled by default via <code>npx oxlint@latest --import-plugin</code> are:</p>
<ul>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/default.md" target="_blank" rel="noreferrer">default</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/named.md" target="_blank" rel="noreferrer">named</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/namespace.md" target="_blank" rel="noreferrer">namespace</a></li>
</ul>
<p>Rules that can be enabled selectively via <code>npx oxlint@latest --import-plugin -D rule-name</code> are:</p>
<ul>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-named-as-default.md" target="_blank" rel="noreferrer">no-named-as-default</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-named-as-default-member.md" target="_blank" rel="noreferrer">no-named-as-default-member</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-self-import.md" target="_blank" rel="noreferrer">no-self-import</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-duplicates.md" target="_blank" rel="noreferrer">no-duplicates</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-amd.md" target="_blank" rel="noreferrer">no-amd</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-default-export.md" target="_blank" rel="noreferrer">no-default-export</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-cycle.md" target="_blank" rel="noreferrer">no-cycle</a></li>
</ul>
<p>There are also improvements to these rules; for example, the diagnostics for the <code>no-cycle</code> rule have been improved:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span> ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected</span></span>
<span class="line"><span>   ╭─[apps/web/playwright/lib/fixtures.ts:13:42]</span></span>
<span class="line"><span>12 │ import { createPaymentsFixture } from "../fixtures/payments";</span></span>
<span class="line"><span>13 │ import { createBookingPageFixture } from "../fixtures/regularBookings";</span></span>
<span class="line"><span>   ·                                          ─────────────────────────────</span></span>
<span class="line"><span>14 │ import { createRoutingFormsFixture } from "../fixtures/routingForms";</span></span>
<span class="line"><span>   ╰────</span></span>
<span class="line"><span> help: These paths form a cycle:</span></span>
<span class="line"><span>       -> ../fixtures/regularBookings - apps/web/playwright/fixtures/regularBookings.ts</span></span>
<span class="line"><span>       -> ./users - apps/web/playwright/fixtures/users.ts</span></span>
<span class="line"><span>       -> ../lib/testUtils - apps/web/playwright/lib/testUtils.ts</span></span>
<span class="line"><span>       -> ./fixtures - apps/web/playwright/lib/fixtures.ts</span></span></code></pre>
</div><p>This isn't a long list of features,
but due to the complexity of the current state of the ecosystem,
it requires a lot of effort to implement these rules and ensure they work correctly.</p>
<p>Over the past six months, we have worked in our spare time and successfully completed all the prerequisites for the <code>--import-plugin</code> to work:</p>
<ul>
<li>a <a href="https://github.com/oxc-project/oxc-resolver" target="_blank" rel="noreferrer">resolver</a> for module resolution</li>
<li>a small <a href="https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/service.rs" target="_blank" rel="noreferrer">&quot;runtime&quot;</a> to maximize processing dependent files in parallel</li>
<li>a <a href="https://github.com/oxc-project/oxc/blob/main/crates/oxc_syntax/src/module_record.rs" target="_blank" rel="noreferrer"><code>ModuleRecord</code></a> data structure for storing import / export information, and its respective <a href="https://github.com/oxc-project/oxc/blob/main/crates/oxc_semantic/src/module_record/builder.rs" target="_blank" rel="noreferrer">builder</a></li>
</ul>
<h2 id="how-can-i-help" tabindex="-1">How can I help? <a class="header-anchor" href="#how-can-i-help" aria-label="Permalink to “How can I help?”">&#8203;</a></h2>
<p>If you are a project maintainer (a.k.a. configuration engineer) and lack the time or energy to keep ESLint and all its plugins updated,
you may follow <a href="https://github.com/brooooooklyn" target="_blank" rel="noreferrer">@brooooooklyn</a>'s lead and <a href="https://github.com/napi-rs/napi-rs/pull/2032" target="_blank" rel="noreferrer">replace ESLint with oxlint in all his projects</a>.</p>
<p>If you are an open-source enthusiast and are willing to help out, come talk to us on <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">discord</a>, check out the <a href="https://github.com/oxc-project/oxc/issues/481" target="_blank" rel="noreferrer">linter product plan and progress issue</a>, or help by <a href="https://github.com/oxc-project/oxc/issues/3161" target="_blank" rel="noreferrer">proposing new rules</a> that were deferred.</p>
<p>If you are an engineering manager, or are willing to migrate your project to oxlint (with 330 rules and growing) to keep your infrastructure costs down,
you may consider <a href="https://github.com/sponsors/Boshen" target="_blank" rel="noreferrer">sponsoring</a> so we can prioritize your project.</p>
<p>Please remember <code>oxlint</code> is currently community driven, I believe that with enough resources, we can make <code>--import-plugin</code> generally available in the next few months.</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><p>We are excited to announce an alpha release for <code>oxlint --import-plugin</code>, a port of <a href="https://npmx.dev/package/eslint-plugin-import" target="_blank" rel="noreferrer"><code>eslint-plugin-import</code></a>.</p>
<p>This port aims to resolve all known issues associated with <code>eslint-plugin-import</code>:</p>
<ul>
<li>Performance - execution time exceeding one minute when certain rules are enabled</li>
<li>Dependency size - 188 dependencies totaling 30M</li>
<li>Backwards compatibility - the necessity to <a href="https://github.com/import-js/eslint-plugin-import/pull/2447#issuecomment-1117384140" target="_blank" rel="noreferrer">support Node.js v4.0.0</a></li>
<li>Dependency compatibility - the need to replace it with <a href="https://npmx.dev/package/eslint-plugin-import-x" target="_blank" rel="noreferrer"><code>eslint-plugin-import-x</code></a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/issues/2948" target="_blank" rel="noreferrer">Upgrading to ESLint v9</a></li>
</ul>
<h2 id="what-s-in-the-release" tabindex="-1">What's in the release? <a class="header-anchor" href="#what-s-in-the-release" aria-label="Permalink to “What's in the release?”">&#8203;</a></h2>
<p>This alpha release is expected to work if your project is in ESM (ECMAScript Modules).</p>
<p>If path aliases (e.g. <code>@/foo</code>) are required through <a href="https://www.typescriptlang.org/tsconfig/#paths" target="_blank" rel="noreferrer">tsconfig.compilerOptions.paths</a>,
the <code>--tsconfig</code> option can be used:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>npx oxlint@latest --tsconfig ./tsconfig.json --import-plugin</span></span></code></pre>
</div><p>The rules that are enabled by default via <code>npx oxlint@latest --import-plugin</code> are:</p>
<ul>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/default.md" target="_blank" rel="noreferrer">default</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/named.md" target="_blank" rel="noreferrer">named</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/namespace.md" target="_blank" rel="noreferrer">namespace</a></li>
</ul>
<p>Rules that can be enabled selectively via <code>npx oxlint@latest --import-plugin -D rule-name</code> are:</p>
<ul>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-named-as-default.md" target="_blank" rel="noreferrer">no-named-as-default</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-named-as-default-member.md" target="_blank" rel="noreferrer">no-named-as-default-member</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-self-import.md" target="_blank" rel="noreferrer">no-self-import</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-duplicates.md" target="_blank" rel="noreferrer">no-duplicates</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-amd.md" target="_blank" rel="noreferrer">no-amd</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-default-export.md" target="_blank" rel="noreferrer">no-default-export</a></li>
<li><a href="https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-cycle.md" target="_blank" rel="noreferrer">no-cycle</a></li>
</ul>
<p>There are also improvements to these rules; for example, the diagnostics for the <code>no-cycle</code> rule have been improved:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span> ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected</span></span>
<span class="line"><span>   ╭─[apps/web/playwright/lib/fixtures.ts:13:42]</span></span>
<span class="line"><span>12 │ import { createPaymentsFixture } from "../fixtures/payments";</span></span>
<span class="line"><span>13 │ import { createBookingPageFixture } from "../fixtures/regularBookings";</span></span>
<span class="line"><span>   ·                                          ─────────────────────────────</span></span>
<span class="line"><span>14 │ import { createRoutingFormsFixture } from "../fixtures/routingForms";</span></span>
<span class="line"><span>   ╰────</span></span>
<span class="line"><span> help: These paths form a cycle:</span></span>
<span class="line"><span>       -> ../fixtures/regularBookings - apps/web/playwright/fixtures/regularBookings.ts</span></span>
<span class="line"><span>       -> ./users - apps/web/playwright/fixtures/users.ts</span></span>
<span class="line"><span>       -> ../lib/testUtils - apps/web/playwright/lib/testUtils.ts</span></span>
<span class="line"><span>       -> ./fixtures - apps/web/playwright/lib/fixtures.ts</span></span></code></pre>
</div><p>This isn't a long list of features,
but due to the complexity of the current state of the ecosystem,
it requires a lot of effort to implement these rules and ensure they work correctly.</p>
<p>Over the past six months, we have worked in our spare time and successfully completed all the prerequisites for the <code>--import-plugin</code> to work:</p>
<ul>
<li>a <a href="https://github.com/oxc-project/oxc-resolver" target="_blank" rel="noreferrer">resolver</a> for module resolution</li>
<li>a small <a href="https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/service.rs" target="_blank" rel="noreferrer">&quot;runtime&quot;</a> to maximize processing dependent files in parallel</li>
<li>a <a href="https://github.com/oxc-project/oxc/blob/main/crates/oxc_syntax/src/module_record.rs" target="_blank" rel="noreferrer"><code>ModuleRecord</code></a> data structure for storing import / export information, and its respective <a href="https://github.com/oxc-project/oxc/blob/main/crates/oxc_semantic/src/module_record/builder.rs" target="_blank" rel="noreferrer">builder</a></li>
</ul>
<h2 id="how-can-i-help" tabindex="-1">How can I help? <a class="header-anchor" href="#how-can-i-help" aria-label="Permalink to “How can I help?”">&#8203;</a></h2>
<p>If you are a project maintainer (a.k.a. configuration engineer) and lack the time or energy to keep ESLint and all its plugins updated,
you may follow <a href="https://github.com/brooooooklyn" target="_blank" rel="noreferrer">@brooooooklyn</a>'s lead and <a href="https://github.com/napi-rs/napi-rs/pull/2032" target="_blank" rel="noreferrer">replace ESLint with oxlint in all his projects</a>.</p>
<p>If you are an open-source enthusiast and are willing to help out, come talk to us on <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">discord</a>, check out the <a href="https://github.com/oxc-project/oxc/issues/481" target="_blank" rel="noreferrer">linter product plan and progress issue</a>, or help by <a href="https://github.com/oxc-project/oxc/issues/3161" target="_blank" rel="noreferrer">proposing new rules</a> that were deferred.</p>
<p>If you are an engineering manager, or are willing to migrate your project to oxlint (with 330 rules and growing) to keep your infrastructure costs down,
you may consider <a href="https://github.com/sponsors/Boshen" target="_blank" rel="noreferrer">sponsoring</a> so we can prioritize your project.</p>
<p>Please remember <code>oxlint</code> is currently community driven, I believe that with enough resources, we can make <code>--import-plugin</code> generally available in the next few months.</p>
<hr>
<p>To start using <code>oxlint</code>, follow the <a href="/docs/guide/usage/linter.html">installation guide</a> or learn more about the <a href="/docs/guide/introduction.html">oxc project</a>.</p>
]]></content:encoded>
            <author>Boshen</author>
        </item>
        <item>
            <title><![CDATA[Oxc Transformer Alpha]]></title>
            <link>https://oxc.rs/blog/2024-09-29-transformer-alpha</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2024-09-29-transformer-alpha</guid>
            <pubDate>Sun, 29 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><br />
<p>We are excited to announce an alpha release for Oxc transform (a.k.a transpile).</p>
<p>This release contains three major features:</p>
<ol>
<li>Transforming TypeScript to ESNext.</li>
<li>Transforming React JSX to ESNext, with built-in React Refresh.</li>
<li><a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations" target="_blank" rel="noreferrer">TypeScript Isolated Declarations DTS Emit</a> without using the TypeScript compiler.</li>
</ol>
<p>In this alpha stage, we recommend to experiment with these features to speed up build times.</p>
<p><a href="https://github.com/oxc-project/bench-transformer" target="_blank" rel="noreferrer">Our benchmark</a> shows:</p>
<ul>
<li>Transform: Oxc is 3x - 5x faster than SWC, uses 20% less memory, and has smaller package size (2 MB vs SWC's 37 MB).</li>
<li>Transform: Oxc is 20x - 50x faster than Babel, uses 70% less memory, and is 19 MB smaller, with only 2 npm packages to install vs Babel's 170.</li>
<li>React development + React Refresh: Oxc is 5x faster than SWC, 50x faster than Babel.</li>
<li>TS isolated declarations <code>.d.ts</code> emit: Oxc is 40x faster than TSC on typical files, 20x faster on larger files.</li>
</ul>
<h2 id="usage-examples" tabindex="-1">Usage Examples <a class="header-anchor" href="#usage-examples" aria-label="Permalink to “Usage Examples”">&#8203;</a></h2>
<h3 id="oxc-transform-npm-package" tabindex="-1"><a href="https://npmx.dev/package/oxc-transform" target="_blank" rel="noreferrer"><code>oxc-transform</code></a> npm package <a class="header-anchor" href="#oxc-transform-npm-package" aria-label="Permalink to “oxc-transform npm package”">&#8203;</a></h3>
<p>Vue.js is currently <a href="https://github.com/vuejs/core/blob/0895b2624b707ea1e75c41f2e1f75388e7a6f101/scripts/build-types.js#L20" target="_blank" rel="noreferrer">experimenting</a>
the <a href="https://npmx.dev/package/oxc-transform" target="_blank" rel="noreferrer"><code>oxc-transform</code></a> npm package for isolated declarations in its build pipeline:</p>
<div class="language-javascript"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { isolatedDeclaration } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxc-transform"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> dts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isolatedDeclaration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filename, ts);</span></span></code></pre>
</div><p><a href="https://github.com/lukeed" target="_blank" rel="noreferrer">@lukeed</a> and <a href="https://github.com/maraisr" target="_blank" rel="noreferrer">@maraisr</a> are utilizing <code>oxc-transform</code>
for their packages
<a href="https://github.com/lukeed/empathic" target="_blank" rel="noreferrer"><code>empathic</code></a> and <a href="https://github.com/maraisr/dldr" target="_blank" rel="noreferrer"><code>dldr</code></a>
to transform and generate <code>.d.ts</code> <a href="https://github.com/lukeed/empathic/blob/b83a360ff55051590dec19aa913cd12da97fa3f8/scripts/build.ts#L45-L52" target="_blank" rel="noreferrer">in a single step</a>.</p>
<p>The following example demonstrates emitting <code>.js</code> and <code>.d.ts</code> in a single transformation step:</p>
<div class="language-javascript"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { transform } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxc-transform"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> transformed</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> transform</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath, sourceCode, {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  typescript: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    onlyRemoveTypeImports: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    declaration: { stripInternal: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">writeFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"out.js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, transformed.code);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">writeFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"out.d.ts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, transformed.declaration);</span></span></code></pre>
</div><h3 id="unplugin-isolated-decl" tabindex="-1"><a href="https://npmx.dev/package/unplugin-isolated-decl" target="_blank" rel="noreferrer"><code>unplugin-isolated-decl</code></a> <a class="header-anchor" href="#unplugin-isolated-decl" aria-label="Permalink to “unplugin-isolated-decl”">&#8203;</a></h3>
<p><code>vue-macros</code> <a href="https://github.com/vue-macros/vue-macros/blob/4247c7ba9189c630111e058245ce1412c8da9229/tsup.config.ts#L10" target="_blank" rel="noreferrer">uses</a> <code>unplugin-isolated-decl</code> as the integration tool for its esbuild plugin.</p>
<p><a href="https://github.com/sxzz" target="_blank" rel="noreferrer">@sxzz</a> <a href="https://x.com/sanxiaozhizi/status/1821320327231893600" target="_blank" rel="noreferrer">reports</a> their <code>.d.ts</code> generation time is reduced from 76s to 16s.</p>
<h3 id="bazel-build-at-airtable" tabindex="-1">Bazel build at <a href="https://github.com/Airtable" target="_blank" rel="noreferrer">Airtable</a> <a class="header-anchor" href="#bazel-build-at-airtable" aria-label="Permalink to “Bazel build at Airtable”">&#8203;</a></h3>
<p><a href="https://github.com/MichaelMitchell-at" target="_blank" rel="noreferrer">@michaelm</a> from <a href="https://github.com/Airtable" target="_blank" rel="noreferrer">Airtable</a>
is integrating Oxc's isolated declarations <code>.d.ts</code> emit in their CI pipeline within their <a href="https://github.com/aspect-build/rules_ts/pull/697" target="_blank" rel="noreferrer">Bazel build</a>.</p>
<h3 id="rust-oxc-transformer-crate" tabindex="-1">Rust <a href="https://crates.io/crates/oxc_transformer" target="_blank" rel="noreferrer"><code>oxc_transformer</code></a> crate <a class="header-anchor" href="#rust-oxc-transformer-crate" aria-label="Permalink to “Rust oxc_transformer crate”">&#8203;</a></h3>
<p>The <a href="https://rolldown.rs" target="_blank" rel="noreferrer">Rolldown</a> bundler uses the <code>oxc_transformer</code> Rust crate <a href="https://github.com/rolldown/rolldown/blob/3213e8fdb9e25f29295b6ec0d92fcc2ce03ce396/crates/rolldown/src/utils/pre_process_ecma_ast.rs#L67-L75" target="_blank" rel="noreferrer">directly</a>.</p>
<h2 id="benchmark-results" tabindex="-1">Benchmark Results <a class="header-anchor" href="#benchmark-results" aria-label="Permalink to “Benchmark Results”">&#8203;</a></h2>
<p>The benchmark setup is located at <a href="https://github.com/oxc-project/bench-transformer" target="_blank" rel="noreferrer">oxc-project/bench-transformer</a>
and the benchmarks are shown in its <a href="https://github.com/oxc-project/bench-transformer/actions/workflows/ci.yml" target="_blank" rel="noreferrer">GitHub Actions</a>.</p>
<p>(Corrections are welcome for any misconfigurations.)</p>
<p>On <code>ubuntu-latest</code>, an example of different lines of code are measured:</p>
<h3 id="transform" tabindex="-1">Transform <a class="header-anchor" href="#transform" aria-label="Permalink to “Transform”">&#8203;</a></h3>
<p>| Lines  | oxc     | swc           | babel         |
|</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><br />
<p>We are excited to announce an alpha release for Oxc transform (a.k.a transpile).</p>
<p>This release contains three major features:</p>
<ol>
<li>Transforming TypeScript to ESNext.</li>
<li>Transforming React JSX to ESNext, with built-in React Refresh.</li>
<li><a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations" target="_blank" rel="noreferrer">TypeScript Isolated Declarations DTS Emit</a> without using the TypeScript compiler.</li>
</ol>
<p>In this alpha stage, we recommend to experiment with these features to speed up build times.</p>
<p><a href="https://github.com/oxc-project/bench-transformer" target="_blank" rel="noreferrer">Our benchmark</a> shows:</p>
<ul>
<li>Transform: Oxc is 3x - 5x faster than SWC, uses 20% less memory, and has smaller package size (2 MB vs SWC's 37 MB).</li>
<li>Transform: Oxc is 20x - 50x faster than Babel, uses 70% less memory, and is 19 MB smaller, with only 2 npm packages to install vs Babel's 170.</li>
<li>React development + React Refresh: Oxc is 5x faster than SWC, 50x faster than Babel.</li>
<li>TS isolated declarations <code>.d.ts</code> emit: Oxc is 40x faster than TSC on typical files, 20x faster on larger files.</li>
</ul>
<h2 id="usage-examples" tabindex="-1">Usage Examples <a class="header-anchor" href="#usage-examples" aria-label="Permalink to “Usage Examples”">&#8203;</a></h2>
<h3 id="oxc-transform-npm-package" tabindex="-1"><a href="https://npmx.dev/package/oxc-transform" target="_blank" rel="noreferrer"><code>oxc-transform</code></a> npm package <a class="header-anchor" href="#oxc-transform-npm-package" aria-label="Permalink to “oxc-transform npm package”">&#8203;</a></h3>
<p>Vue.js is currently <a href="https://github.com/vuejs/core/blob/0895b2624b707ea1e75c41f2e1f75388e7a6f101/scripts/build-types.js#L20" target="_blank" rel="noreferrer">experimenting</a>
the <a href="https://npmx.dev/package/oxc-transform" target="_blank" rel="noreferrer"><code>oxc-transform</code></a> npm package for isolated declarations in its build pipeline:</p>
<div class="language-javascript"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { isolatedDeclaration } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxc-transform"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> dts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isolatedDeclaration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filename, ts);</span></span></code></pre>
</div><p><a href="https://github.com/lukeed" target="_blank" rel="noreferrer">@lukeed</a> and <a href="https://github.com/maraisr" target="_blank" rel="noreferrer">@maraisr</a> are utilizing <code>oxc-transform</code>
for their packages
<a href="https://github.com/lukeed/empathic" target="_blank" rel="noreferrer"><code>empathic</code></a> and <a href="https://github.com/maraisr/dldr" target="_blank" rel="noreferrer"><code>dldr</code></a>
to transform and generate <code>.d.ts</code> <a href="https://github.com/lukeed/empathic/blob/b83a360ff55051590dec19aa913cd12da97fa3f8/scripts/build.ts#L45-L52" target="_blank" rel="noreferrer">in a single step</a>.</p>
<p>The following example demonstrates emitting <code>.js</code> and <code>.d.ts</code> in a single transformation step:</p>
<div class="language-javascript"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { transform } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxc-transform"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> transformed</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> transform</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath, sourceCode, {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  typescript: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    onlyRemoveTypeImports: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    declaration: { stripInternal: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">writeFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"out.js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, transformed.code);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">writeFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"out.d.ts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, transformed.declaration);</span></span></code></pre>
</div><h3 id="unplugin-isolated-decl" tabindex="-1"><a href="https://npmx.dev/package/unplugin-isolated-decl" target="_blank" rel="noreferrer"><code>unplugin-isolated-decl</code></a> <a class="header-anchor" href="#unplugin-isolated-decl" aria-label="Permalink to “unplugin-isolated-decl”">&#8203;</a></h3>
<p><code>vue-macros</code> <a href="https://github.com/vue-macros/vue-macros/blob/4247c7ba9189c630111e058245ce1412c8da9229/tsup.config.ts#L10" target="_blank" rel="noreferrer">uses</a> <code>unplugin-isolated-decl</code> as the integration tool for its esbuild plugin.</p>
<p><a href="https://github.com/sxzz" target="_blank" rel="noreferrer">@sxzz</a> <a href="https://x.com/sanxiaozhizi/status/1821320327231893600" target="_blank" rel="noreferrer">reports</a> their <code>.d.ts</code> generation time is reduced from 76s to 16s.</p>
<h3 id="bazel-build-at-airtable" tabindex="-1">Bazel build at <a href="https://github.com/Airtable" target="_blank" rel="noreferrer">Airtable</a> <a class="header-anchor" href="#bazel-build-at-airtable" aria-label="Permalink to “Bazel build at Airtable”">&#8203;</a></h3>
<p><a href="https://github.com/MichaelMitchell-at" target="_blank" rel="noreferrer">@michaelm</a> from <a href="https://github.com/Airtable" target="_blank" rel="noreferrer">Airtable</a>
is integrating Oxc's isolated declarations <code>.d.ts</code> emit in their CI pipeline within their <a href="https://github.com/aspect-build/rules_ts/pull/697" target="_blank" rel="noreferrer">Bazel build</a>.</p>
<h3 id="rust-oxc-transformer-crate" tabindex="-1">Rust <a href="https://crates.io/crates/oxc_transformer" target="_blank" rel="noreferrer"><code>oxc_transformer</code></a> crate <a class="header-anchor" href="#rust-oxc-transformer-crate" aria-label="Permalink to “Rust oxc_transformer crate”">&#8203;</a></h3>
<p>The <a href="https://rolldown.rs" target="_blank" rel="noreferrer">Rolldown</a> bundler uses the <code>oxc_transformer</code> Rust crate <a href="https://github.com/rolldown/rolldown/blob/3213e8fdb9e25f29295b6ec0d92fcc2ce03ce396/crates/rolldown/src/utils/pre_process_ecma_ast.rs#L67-L75" target="_blank" rel="noreferrer">directly</a>.</p>
<h2 id="benchmark-results" tabindex="-1">Benchmark Results <a class="header-anchor" href="#benchmark-results" aria-label="Permalink to “Benchmark Results”">&#8203;</a></h2>
<p>The benchmark setup is located at <a href="https://github.com/oxc-project/bench-transformer" target="_blank" rel="noreferrer">oxc-project/bench-transformer</a>
and the benchmarks are shown in its <a href="https://github.com/oxc-project/bench-transformer/actions/workflows/ci.yml" target="_blank" rel="noreferrer">GitHub Actions</a>.</p>
<p>(Corrections are welcome for any misconfigurations.)</p>
<p>On <code>ubuntu-latest</code>, an example of different lines of code are measured:</p>
<h3 id="transform" tabindex="-1">Transform <a class="header-anchor" href="#transform" aria-label="Permalink to “Transform”">&#8203;</a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Lines</th>
<th>oxc</th>
<th>swc</th>
<th>babel</th>
</tr>
</thead>
<tbody>
<tr>
<td>~100</td>
<td>0.14 ms</td>
<td>0.7 ms (5x)</td>
<td>11.5 ms (82x)</td>
</tr>
<tr>
<td>~1000</td>
<td>0.9 ms</td>
<td>5.7 ms (6.3x)</td>
<td>38.7 ms (43x)</td>
</tr>
<tr>
<td>~10000</td>
<td>14.9 ms</td>
<td>35.9 ms(2.4x)</td>
<td>492 ms (33x)</td>
</tr>
</tbody>
</table>
<h3 id="isolated-declarations" tabindex="-1">Isolated Declarations <a class="header-anchor" href="#isolated-declarations" aria-label="Permalink to “Isolated Declarations”">&#8203;</a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Lines</th>
<th>oxc</th>
<th>tsc</th>
</tr>
</thead>
<tbody>
<tr>
<td>~100</td>
<td>0.1 ms</td>
<td>23.1 ms (231x)</td>
</tr>
<tr>
<td>~1000</td>
<td>3.1 ms</td>
<td>26.8 ms (8.6x)</td>
</tr>
<tr>
<td>~10000</td>
<td>3.5 ms</td>
<td>115.2 ms (33x)</td>
</tr>
</tbody>
</table>
<h2 id="package-size" tabindex="-1">Package size <a class="header-anchor" href="#package-size" aria-label="Permalink to “Package size”">&#8203;</a></h2>
<p>Oxc downloads only 2 npm packages, a total of 2 MB.</p>
<table tabindex="0">
<thead>
<tr>
<th>Package</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@oxc-transform/binding-darwin-arm64</code></td>
<td><a href="https://npmx.dev/package/@oxc-transform/binding-darwin-arm64" target="_blank" rel="noreferrer">2.0 MB</a></td>
</tr>
<tr>
<td><code>@swc/core-darwin-arm64</code></td>
<td><a href="https://npmx.dev/package/@swc/core-darwin-arm64" target="_blank" rel="noreferrer">37.5 MB</a></td>
</tr>
<tr>
<td><code>@babel/core</code> + <code>@babel/preset-env</code> + <code>@babel/preset-react</code> + <code>@babel/preset-typescript</code></td>
<td><a href="https://npmx.dev/package/@babel/core" target="_blank" rel="noreferrer">21 MB and 170 packages</a></td>
</tr>
</tbody>
</table>
<h2 id="memory-usage" tabindex="-1">Memory Usage <a class="header-anchor" href="#memory-usage" aria-label="Permalink to “Memory Usage”">&#8203;</a></h2>
<p>Oxc uses less memory.</p>
<p>Memory usage transforming <code>parser.ts</code> (10777 lines) - measured using <code>/usr/bin/time -alh node</code>:</p>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th>Max RSS</th>
</tr>
</thead>
<tbody>
<tr>
<td>oxc</td>
<td>51 MB</td>
</tr>
<tr>
<td>swc</td>
<td>67 MB</td>
</tr>
<tr>
<td>babel</td>
<td>172 MB</td>
</tr>
</tbody>
</table>
<h2 id="next-release" tabindex="-1">Next Release <a class="header-anchor" href="#next-release" aria-label="Permalink to “Next Release”">&#8203;</a></h2>
<p>Our next release will include target lowering to ES6 and <code>@babel/plugin-transform-modules-commonjs</code>.</p>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>Thank you <a href="https://github.com/dunqing" target="_blank" rel="noreferrer">@Dunqing</a> and <a href="https://github.com/overlookmotel" target="_blank" rel="noreferrer">@overlookmotel</a> for all the hard work involved in this release.</p>
<p>Thank you <a href="https://snyder.tech" target="_blank" rel="noreferrer">snyder.tech</a>, <a href="https://schoolhouse.world" target="_blank" rel="noreferrer">schoolhouse.world</a>, <a href="https://github.com/lukeed" target="_blank" rel="noreferrer">@lukeed</a> and <a href="https://github.com/maraisr" target="_blank" rel="noreferrer">@maraisr</a> for the generous <a href="https://github.com/sponsors/boshen" target="_blank" rel="noreferrer">sponsorship</a>.</p>
]]></content:encoded>
            <author>Boshen</author>
            <author>Dunqing</author>
            <author>overlookmotel</author>
        </item>
        <item>
            <title><![CDATA[Oxlint v0.10 Migration Guide]]></title>
            <link>https://oxc.rs/blog/2024-10-18-oxlint-v0.10-release</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2024-10-18-oxlint-v0.10-release</guid>
            <pubDate>Fri, 18 Oct 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This migration guide is for an older version of Oxlint.</strong> For information about the latest stable v1.0 release, see the <a href="/blog/2025-06-10-oxlint-stable.html">Oxlint v1.0 Stable announcement</a>.</p>
</Alert>
<p>Oxlint v0.10.0 is here! This release includes several exciting features,
including many improvements to configuration files.</p>
<h2 id="new-features" tabindex="-1">New Features <a class="header-anchor" href="#new-features" aria-label="Permalink to “New Features”">&#8203;</a></h2>
<!-- todo: other features -->
<h3 id="new-rules" tabindex="-1">New Rules <a class="header-anchor" href="#new-rules" aria-label="Permalink to “New Rules”">&#8203;</a></h3>
<p>This release includes the following new rules:</p>
<ul>
<li><code>promise/no-callback-in-promise</code></li>
<li><code>react/iframe-missing-sandbox</code></li>
<li><code>node/no-new-require</code></li>
</ul>
<p>And adds auto fixes/suggestions for:</p>
<ul>
<li><code>eslint/no-plusplus</code></li>
</ul>
<h3 id="enable-disable-rules-by-category" tabindex="-1">Enable/Disable Rules by Category <a class="header-anchor" href="#enable-disable-rules-by-category" aria-label="Permalink to “Enable/Disable Rules by Category”">&#8203;</a></h3>
<p>You can now enable or disable entire categories of rules with the <code>categories</code>
field inside of your configuration file.</p>
<p>Now, instead of running this command:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> correctness</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -W</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> suspicious</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint.json</span></span></code></pre>
</div><p>You can add a <code>categories</code> field to your <code>oxlint.json</code>:</p>
<table><tbody><tr><td>oxlintrc.json</td><td><div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark has-diff" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "categories"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line diff add"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "correctness"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"deny"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span></span>
<span class="line diff add"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "suspicious"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"warn"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span></span>
<span class="line diff add"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }, </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "no-const-assign"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "import/no-cycle"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div></td></tr></tbody></table>
<p>and drop the <code>-D</code> and <code>-W</code> flags.</p>
<h3 id="plugins-are-now-supported-in-configuration-files" tabindex="-1"><code>plugins</code> Are Now Supported in Configuration Files <a class="header-anchor" href="#plugins-are-now-supported-in-configuration-files" aria-label="Permalink to “plugins Are Now Supported in Configuration Files”">&#8203;</a></h3>
<p>Configuration files now support the <code>plugins</code> array from ESLint v8 configs.
This allows you to enable plugins without CLI arguments, making it possible to
use plugins in VSCode.</p>
<table><tbody><tr><td>oxlintrc.json</td><td><div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark has-diff" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line diff add"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "plugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"import"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "categories"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "correctness"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"deny"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "suspicious"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"warn"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "react/jsx-uses-react"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"off"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "react/react-in-jsx-scope"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"off"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div></td></tr></tbody></table>
<p>This plays nicely with <code>categories</code>, as enabled/disabled categories affect plugins as well.</p>
<table><tbody><tr><td>oxlintrc.json</td><td><div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "plugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"import"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // `categories` affects all enabled plugins</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "categories"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "correctness"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"allow"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "suspicious"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"warn"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "no-const-assign"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "import/no-cycle"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div></td></tr></tbody></table>
<h2 id="breaking-changes-and-migration-guide" tabindex="-1">Breaking Changes and Migration Guide <a class="header-anchor" href="#breaking-changes-and-migration-guide" aria-label="Permalink to “Breaking Changes and Migration Guide”">&#8203;</a></h2>
<h3 id="cli-vs-config-file-rule-priority" tabindex="-1">CLI vs Config File Rule Priority <a class="header-anchor" href="#cli-vs-config-file-rule-priority" aria-label="Permalink to “CLI vs Config File Rule Priority”">&#8203;</a></h3>
<p>Before, config files would override rules set in CLI arguments. For example, running this command:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> correctness</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlintrc.json</span></span></code></pre>
</div><p>With this config file</p>
<table><tbody><tr><td>oxlintrc.json</td><td><div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "no-const-assign"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div></td></tr></tbody></table>
<p>Would result in a single rule, <code>no-const-assign</code> being turned on at an error level with all other rules disabled (i.e. set to &quot;allow&quot;).</p>
<p>Now, <strong>CLI arguments will override config files</strong>. That same command with the
same config file will result with <strong>all rules being disabled</strong>. To get the same
behavior as before, enable and disable categories in your config file instead of
with CLI arguments.</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint.json</span></span></code></pre>
</div><table><tbody><tr><td>oxlintrc.json</td><td><div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark has-diff" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "categories"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line diff add"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "correctness"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"allow"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span></span>
<span class="line diff add"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }, </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "no-const-assign"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div></td></tr></tbody></table>
]]></content:encoded>
            <author>Don</author>
        </item>
        <item>
            <title><![CDATA[Oxc Minifier Alpha]]></title>
            <link>https://oxc.rs/blog/2025-03-13-minifier-alpha</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-03-13-minifier-alpha</guid>
            <pubDate>Thu, 13 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><br />
<p>We are excited to announce an alpha release for <a href="https://npmx.dev/package/oxc-minify" target="_blank" rel="noreferrer"><code>oxc-minify</code></a>.</p>
<p>While lacking some advanced minification techniques,
the current version already outperforms <code>esbuild</code> in terms of performance and compression size,
as demonstrated by <a href="https://github.com/privatenumber/minification-benchmarks" target="_blank" rel="noreferrer">minification-benchmarks</a>.</p>
<p>Comparing widely-used minifiers on <code>typescript.js</code>:</p>
<div align="center">
<p>| Artifact                                                                                                                          |                   Original size |                         Gzip size |                                   |
| :</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><br />
<p>We are excited to announce an alpha release for <a href="https://npmx.dev/package/oxc-minify" target="_blank" rel="noreferrer"><code>oxc-minify</code></a>.</p>
<p>While lacking some advanced minification techniques,
the current version already outperforms <code>esbuild</code> in terms of performance and compression size,
as demonstrated by <a href="https://github.com/privatenumber/minification-benchmarks" target="_blank" rel="noreferrer">minification-benchmarks</a>.</p>
<p>Comparing widely-used minifiers on <code>typescript.js</code>:</p>
<div align="center">
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">Artifact</th>
<th style="text-align:right">Original size</th>
<th style="text-align:right">Gzip size</th>
<th style="text-align:right"></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><a href="https://npmx.dev/package/typescript/v/4.9.5" target="_blank" rel="noreferrer">typescript v4.9.5</a> (<a href="https://unpkg.com/typescript@4.9.5/lib/typescript.js" target="_blank" rel="noreferrer">Source</a>)</td>
<td style="text-align:right"><code>10.95 MB</code></td>
<td style="text-align:right"><code>1.88 MB</code></td>
<td style="text-align:right"></td>
</tr>
<tr>
<td style="text-align:left"><strong>Minifier</strong></td>
<td style="text-align:right"><strong>Minified size</strong></td>
<td style="text-align:right"><strong>Minzipped size</strong></td>
<td style="text-align:right"><strong>Time</strong></td>
</tr>
<tr>
<td style="text-align:left"><a href="packages/minifiers/minifiers/swc.ts">@swc/core</a></td>
<td style="text-align:right"><strong><sup>🏆-70% </sup><code>3.32 MB</code></strong></td>
<td style="text-align:right"><strong><sup>🏆-54% </sup><code>858.29 kB</code></strong></td>
<td style="text-align:right"><sup><em>5x</em> </sup><code>2,179 ms</code></td>
</tr>
<tr>
<td style="text-align:left"><a href="packages/minifiers/minifiers/oxc-minify.ts">oxc-minify</a></td>
<td style="text-align:right"><sup>-69% </sup><code>3.35 MB</code></td>
<td style="text-align:right"><sup>-54% </sup><code>860.67 kB</code></td>
<td style="text-align:right">🏆 <code>444 ms</code></td>
</tr>
<tr>
<td style="text-align:left"><a href="packages/minifiers/minifiers/terser.ts">terser (no compress)</a></td>
<td style="text-align:right"><sup>-68% </sup><code>3.53 MB</code></td>
<td style="text-align:right"><sup>-53% </sup><code>879.30 kB</code></td>
<td style="text-align:right"><sup><em>14x</em> </sup><code>6,433 ms</code></td>
</tr>
<tr>
<td style="text-align:left"><a href="packages/minifiers/minifiers/esbuild.ts">esbuild</a></td>
<td style="text-align:right"><sup>-68% </sup><code>3.49 MB</code></td>
<td style="text-align:right"><sup>-51% </sup><code>915.55 kB</code></td>
<td style="text-align:right"><sup><em>1x</em> </sup><code>492 ms</code></td>
</tr>
<tr>
<td style="text-align:left"><a href="packages/minifiers/minifiers/terser.ts">terser</a> <sub title="Failed: timeout">❌ Timed out</sub></td>
<td style="text-align:right">-</td>
<td style="text-align:right">-</td>
<td style="text-align:right"><sup>⚠️</sup> <code>+10,000 ms</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="oxc-minify-usage-example" tabindex="-1"><a href="https://npmx.dev/package/oxc-minify" target="_blank" rel="noreferrer"><code>oxc-minify</code></a> Usage Example <a class="header-anchor" href="#oxc-minify-usage-example" aria-label="Permalink to “oxc-minify Usage Example”">&#8203;</a></h2>
<div class="language-typescript"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { minify } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxc-minify"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> filename</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "test.js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> code</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "const x = 'a' + 'b'; console.log(x);"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  compress: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    target: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"esnext"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  mangle: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    toplevel: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  codegen: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    removeWhitespace: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  sourcemap: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> minify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filename, code, options);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(result.code);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(result.map);</span></span></code></pre>
</div><h2 id="next-release" tabindex="-1">Next Release <a class="header-anchor" href="#next-release" aria-label="Permalink to “Next Release”">&#8203;</a></h2>
<p><code>oxc-minify</code> is being integrated into <a href="https://rolldown.rs" target="_blank" rel="noreferrer">Rolldown</a> as its built-in minifier,
and Rolldown is set to <a href="https://voidzero.dev/posts/announcing-voidzero-inc" target="_blank" rel="noreferrer">become the future of Vite</a>.</p>
<p>So it is critical for us to:</p>
<ul>
<li>Continue implementing advanced minification techniques, such as constant inlining and dead code removal.</li>
<li>Strengthen and expand our test infrastructure to ensure it is production-ready.</li>
</ul>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>Thank you <a href="https://github.com/sapphi-red" target="_blank" rel="noreferrer">@sapphi-red</a> for improving the minifier,
especially the advanced symbol minification algorithm which <code>esbuild</code> lacks.</p>
]]></content:encoded>
            <author>Boshen</author>
        </item>
        <item>
            <title><![CDATA[Oxlint Beta]]></title>
            <link>https://oxc.rs/blog/2025-03-15-oxlint-beta</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-03-15-oxlint-beta</guid>
            <pubDate>Sat, 15 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the beta release of Oxlint.</strong> Oxlint has since reached v1.0 stable! See the <a href="/blog/2025-06-10-oxlint-stable.html">Oxlint v1.0 Stable announcement</a> for the latest features and improvements.</p>
</Alert>
<p>We are thrilled to announce that Oxlint is now in beta release, after more than a year of development by the community!</p>
<p>This milestone represents a significant step forward in feature completeness, performance, and stability.</p>
<h2 id="how-to-use" tabindex="-1">How to use <a class="header-anchor" href="#how-to-use" aria-label="Permalink to “How to use”">&#8203;</a></h2>
<p>At this stage, Oxlint can be used to fully replace ESLint in small to medium projects.</p>
<p>For larger projects, our advice is to turn off ESLint rules via <a href="https://npmx.dev/package/eslint-plugin-oxlint" target="_blank" rel="noreferrer">eslint-plugin-oxlint</a>,
and run Oxlint before ESLint in your local or CI setup for a quicker feedback loop.</p>
<p>To test Oxlint in your codebase, you can use the package manager of your choice at the root of your codebase:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>deno</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">deno</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> npm:oxlint@latest</span></span></code></pre>
</div></td></tr></tbody></table>
<p>For more detailed instructions on how to use Oxlint and integrate it with your project or editor, check out the <a href="/docs/guide/usage/linter.html">installation guide</a>.</p>
<h2 id="highlight-of-new-features-since-general-availability" tabindex="-1">Highlight of new features since general availability <a class="header-anchor" href="#highlight-of-new-features-since-general-availability" aria-label="Permalink to “Highlight of new features since general availability”">&#8203;</a></h2>
<ul>
<li>Significant performance improvements, up to twice as fast compared to the previous release</li>
<li>Includes over 500 rules built-in, with no extra installation required</li>
<li>Many rules from the <code>typescript</code>, <code>unicorn</code>, <code>react</code>, <code>react-perf</code>, <code>nextjs</code>, <code>import</code>, <code>jsdoc</code>, <code>jsx-a11y</code>, <code>node</code>, <code>promise</code>, <code>jest</code>, <code>vitest</code> plugins are now complete.</li>
<li>Support for configuration via <a href="/docs/guide/usage/linter/nested-config.html#configuration-file-format"><code>.oxlintrc.json</code> files</a>, including <a href="/docs/guide/usage/linter/nested-config.html">nested configuration files</a>, using <code>extends</code> to share configuration between files, applying <code>overrides</code> to specific files, and more.</li>
<li>Supports linting <code>&lt;script&gt;</code> content in <code>.astro</code>, <code>.svelte</code> and <code>.vue</code> files with no additional configuration needed.</li>
<li>Allows applying <a href="/docs/guide/usage/linter/automatic-fixes.html">automatic fixes</a> and suggestions to files.</li>
</ul>
<h2 id="more-rules-more-performance" tabindex="-1">More rules, more performance <a class="header-anchor" href="#more-rules-more-performance" aria-label="Permalink to “More rules, more performance”">&#8203;</a></h2>
<p>We have focused on making Oxlint more feature complete, supporting many of the most commonly used ESLint rules and plugins, but we have also made Oxlint much faster as well.</p>
<p>The first <a href="./2023-12-12-announcing-oxlint.html">generally available (GA) release of Oxlint</a> had 205 rules in total, with 70 of those being enabled by default. This beta release now includes 502 rules in total, with 99 of those being enabled by default (a 41% increase in the number of rules enabled by default).</p>
<p>| Rule type       | Rule count (GA) | Rule count (beta) | Increase       |
|</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the beta release of Oxlint.</strong> Oxlint has since reached v1.0 stable! See the <a href="/blog/2025-06-10-oxlint-stable.html">Oxlint v1.0 Stable announcement</a> for the latest features and improvements.</p>
</Alert>
<p>We are thrilled to announce that Oxlint is now in beta release, after more than a year of development by the community!</p>
<p>This milestone represents a significant step forward in feature completeness, performance, and stability.</p>
<h2 id="how-to-use" tabindex="-1">How to use <a class="header-anchor" href="#how-to-use" aria-label="Permalink to “How to use”">&#8203;</a></h2>
<p>At this stage, Oxlint can be used to fully replace ESLint in small to medium projects.</p>
<p>For larger projects, our advice is to turn off ESLint rules via <a href="https://npmx.dev/package/eslint-plugin-oxlint" target="_blank" rel="noreferrer">eslint-plugin-oxlint</a>,
and run Oxlint before ESLint in your local or CI setup for a quicker feedback loop.</p>
<p>To test Oxlint in your codebase, you can use the package manager of your choice at the root of your codebase:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>deno</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">deno</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> npm:oxlint@latest</span></span></code></pre>
</div></td></tr></tbody></table>
<p>For more detailed instructions on how to use Oxlint and integrate it with your project or editor, check out the <a href="/docs/guide/usage/linter.html">installation guide</a>.</p>
<h2 id="highlight-of-new-features-since-general-availability" tabindex="-1">Highlight of new features since general availability <a class="header-anchor" href="#highlight-of-new-features-since-general-availability" aria-label="Permalink to “Highlight of new features since general availability”">&#8203;</a></h2>
<ul>
<li>Significant performance improvements, up to twice as fast compared to the previous release</li>
<li>Includes over 500 rules built-in, with no extra installation required</li>
<li>Many rules from the <code>typescript</code>, <code>unicorn</code>, <code>react</code>, <code>react-perf</code>, <code>nextjs</code>, <code>import</code>, <code>jsdoc</code>, <code>jsx-a11y</code>, <code>node</code>, <code>promise</code>, <code>jest</code>, <code>vitest</code> plugins are now complete.</li>
<li>Support for configuration via <a href="/docs/guide/usage/linter/nested-config.html#configuration-file-format"><code>.oxlintrc.json</code> files</a>, including <a href="/docs/guide/usage/linter/nested-config.html">nested configuration files</a>, using <code>extends</code> to share configuration between files, applying <code>overrides</code> to specific files, and more.</li>
<li>Supports linting <code>&lt;script&gt;</code> content in <code>.astro</code>, <code>.svelte</code> and <code>.vue</code> files with no additional configuration needed.</li>
<li>Allows applying <a href="/docs/guide/usage/linter/automatic-fixes.html">automatic fixes</a> and suggestions to files.</li>
</ul>
<h2 id="more-rules-more-performance" tabindex="-1">More rules, more performance <a class="header-anchor" href="#more-rules-more-performance" aria-label="Permalink to “More rules, more performance”">&#8203;</a></h2>
<p>We have focused on making Oxlint more feature complete, supporting many of the most commonly used ESLint rules and plugins, but we have also made Oxlint much faster as well.</p>
<p>The first <a href="./2023-12-12-announcing-oxlint.html">generally available (GA) release of Oxlint</a> had 205 rules in total, with 70 of those being enabled by default. This beta release now includes 502 rules in total, with 99 of those being enabled by default (a 41% increase in the number of rules enabled by default).</p>
<table tabindex="0">
<thead>
<tr>
<th>Rule type</th>
<th>Rule count (GA)</th>
<th>Rule count (beta)</th>
<th>Increase</th>
</tr>
</thead>
<tbody>
<tr>
<td>Default rules</td>
<td>70</td>
<td>99</td>
<td>+29 rules</td>
</tr>
<tr>
<td>Correctness</td>
<td>88</td>
<td>173</td>
<td>+88 rules</td>
</tr>
<tr>
<td>Performance</td>
<td>0</td>
<td>9</td>
<td>+9 rules</td>
</tr>
<tr>
<td>Restrictions</td>
<td>15</td>
<td>64</td>
<td>+49 rules</td>
</tr>
<tr>
<td>Pedantic</td>
<td>43</td>
<td>79</td>
<td>+36 rules</td>
</tr>
<tr>
<td>Style</td>
<td>38</td>
<td>137</td>
<td>+99 rules</td>
</tr>
<tr>
<td>Suspicious</td>
<td>7</td>
<td>28</td>
<td>+21 rules</td>
</tr>
<tr>
<td><strong>Total rules</strong></td>
<td>205</td>
<td><strong>502</strong></td>
<td><strong>+297 rules</strong></td>
</tr>
</tbody>
</table>
<p>Despite adding many new rules that are enabled by default, Oxlint is now much faster than it ever has been. Here are some <a href="https://gist.github.com/camchenry/cb09f6fae14ec1e3df1f72938b7350c8" target="_blank" rel="noreferrer">benchmarks</a> on some popular repositories:</p>
<table tabindex="0">
<thead>
<tr>
<th>Repository</th>
<th>File count</th>
<th>Lint time (GA)</th>
<th>Lint time (beta)</th>
<th>Speedup</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>elastic/kibana</code></td>
<td>68,591</td>
<td>6.02s</td>
<td><strong>3.11s</strong></td>
<td><strong>1.94x</strong></td>
</tr>
<tr>
<td><code>microsoft/vscode</code></td>
<td>5,703</td>
<td>1.697s</td>
<td><strong>0.792s</strong></td>
<td><strong>2.14x</strong></td>
</tr>
<tr>
<td><code>vitest-dev/vitest</code></td>
<td>1,732</td>
<td>105ms</td>
<td><strong>50ms</strong></td>
<td><strong>2.1x</strong></td>
</tr>
<tr>
<td><code>vuejs/core</code></td>
<td>1,063</td>
<td>217ms</td>
<td><strong>89ms</strong></td>
<td><strong>2.44x</strong></td>
</tr>
</tbody>
</table>
<h2 id="roadmap" tabindex="-1">Roadmap <a class="header-anchor" href="#roadmap" aria-label="Permalink to “Roadmap”">&#8203;</a></h2>
<p>One of the most commonly requested features for Oxlint is support for existing custom ESLint plugins. We have been busy working on the prerequisites for this feature, and to enable fast linter plugins written in JavaScript. We hope to have this feature available for the next major release, and more information to share about it in the near future.</p>
<p>We also are planning to continue improving the IDE/editor integrations, with improved support for VSCode, Zed, <code>coc.nvim</code>, and IntelliJ plugins.</p>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>Oxlint beta would not have been possible without the over 200 contributors to the project.</p>
<p>Special thanks goes to:</p>
<ul>
<li><a href="https://github.com/camc314" target="_blank" rel="noreferrer">@cam314</a>, <a href="https://github.com/mysteryven" target="_blank" rel="noreferrer">@mysteryven</a>, and <a href="https://github.com/shulaoda" target="_blank" rel="noreferrer">@shulaoda</a> for implementing many sophisticated lint rules, testing, and constantly improving everything.</li>
<li><a href="https://github.com/Sysix" target="_blank" rel="noreferrer">@Sysix</a> for maintaining <code>eslint-plugin-oxlint</code>.</li>
<li><a href="https://github.com/DonIsaac" target="_blank" rel="noreferrer">@DonIsaac</a> for improving configuration, documentation and website, and for representing Oxc at <a href="https://2024.squiggleconf.com" target="_blank" rel="noreferrer">SquiggleConf 2024</a>.</li>
<li><a href="https://github.com/leaysgur" target="_blank" rel="noreferrer">@leaysgur</a> for the RegExp parser and JSDoc plugin.</li>
<li><a href="https://github.com/u9g" target="_blank" rel="noreferrer">@u9g</a> and <a href="https://github.com/rzvxa" target="_blank" rel="noreferrer">@rzvxa</a> for implementing control flow graph analysis.</li>
<li><a href="https://github.com/branchseer" target="_blank" rel="noreferrer">@branchseer</a> for implementing the multi-file analysis runtime.</li>
<li><a href="https://github.com/camchenry" target="_blank" rel="noreferrer">@camchenry</a> for implementing nested configuration support.</li>
</ul>
]]></content:encoded>
            <author>Boshen</author>
            <author>Cam</author>
        </item>
        <item>
            <title><![CDATA[Oxlint v1.0 Stable]]></title>
            <link>https://oxc.rs/blog/2025-06-10-oxlint-stable</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-06-10-oxlint-stable</guid>
            <pubDate>Tue, 10 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><br>
<div  class="info custom-block"><p class="custom-block-title custom-block-title-default">INFO</p>
<p>This blog post was <a href="https://voidzero.dev/posts/announcing-oxlint-1-stable" target="_blank" rel="noreferrer">originally published on the VoidZero website</a>.</p>
</div>
<br>
<p>TL;DR: The first stable version Oxlint has been released! With a <a href="#benchmark">50~100x</a> performance improvement over ESLint, support for over 500 ESLint rules, and <a href="#real-world-impact">usage in major companies</a> like Shopify, Airbnb, and Mercedes-Benz, you should give it a try. <a href="#quick-start">Get started now</a>.</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><br>
<div  class="info custom-block"><p class="custom-block-title custom-block-title-default">INFO</p>
<p>This blog post was <a href="https://voidzero.dev/posts/announcing-oxlint-1-stable" target="_blank" rel="noreferrer">originally published on the VoidZero website</a>.</p>
</div>
<br>
<p>TL;DR: The first stable version Oxlint has been released! With a <a href="#benchmark">50~100x</a> performance improvement over ESLint, support for over 500 ESLint rules, and <a href="#real-world-impact">usage in major companies</a> like Shopify, Airbnb, and Mercedes-Benz, you should give it a try. <a href="#quick-start">Get started now</a>.</p>
<hr>
<p>Oxlint is a Rust-powered linter for JavaScript and TypeScript, designed to be fast and easy to adopt. Since its initial announcement in December 2023, Oxlint has undergone significant improvements and is now releasing its first stable version, 1.0.
In addition to the stable release, we also want to announce that Oxlint has a dedicated full-time maintainer, <a href="https://github.com/camc314" target="_blank" rel="noreferrer">Cameron</a>, and a growing core team working on maintaining and improving the linter.</p>
<h2 id="real-world-impact" tabindex="-1">Real-World Impact <a class="header-anchor" href="#real-world-impact" aria-label="Permalink to “Real-World Impact”">&#8203;</a></h2>
<p>We are extremely proud of the performance of Oxlint and its impact on real, large-scale codebases, which has led to reduced CI costs.</p>
<p>We are thankful for our <a href="https://github.com/oxc-project/oxc/network/dependents" target="_blank" rel="noreferrer">5,200 early adopters</a> and for companies and projects such as:</p>
<ul>
<li><strong>Shopify</strong>, where the front-end platform team uses Oxlint in the Shopify admin console.</li>
<li><strong>Airbnb</strong>, where they use multi-file analysis <a href="https://oxc.rs/docs/guide/usage/linter/rules/oxc/no-barrel-file.html" target="_blank" rel="noreferrer">oxc/no-barrel-file</a> and <a href="https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html" target="_blank" rel="noreferrer">import/no-cycle</a> on their 126,000+ files, which completes in 7s on CI. ESLint's implementation of these rules times out.</li>
<li><a href="https://www.mercedes-benz.io/blog/2025-05-16-how-can-modern-tooling-save-mercedes-benz-io-engineering-time" target="_blank" rel="noreferrer"><strong>Mercedes-Benz</strong></a>, where they observed a 71% decrease in lint time when switching from ESLint to Oxlint, with some project seeing up to a 97% speedup.</li>
<li>Large Open Source projects, from runtimes like <a href="https://github.com/oven-sh/bun/blob/main/oxlint.json" target="_blank" rel="noreferrer">Bun</a> to frameworks like <a href="https://github.com/preactjs/preact/blob/main/oxlint.json" target="_blank" rel="noreferrer">Preact</a>.</li>
</ul>
<p>On the largest repository we found, Oxlint reported:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>Finished in 22.5s on 264925 files with 101 rules using 10 threads.</span></span></code></pre>
</div><p>Based on real-world cases posted on <a href="https://x.com/boshen_c/status/1928264877115597053" target="_blank" rel="noreferrer">X</a> and <a href="https://bsky.app/profile/boshen.github.io/post/3lqe47xi47c2e" target="_blank" rel="noreferrer">Bluesky</a>,
Oxlint runs at approximately 10,000 files per second, depending on the total number of threads used.</p>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>Oxlint is perfect for developers who want to start linting their code without spending hours configuring tools. With zero setup required, you can start catching issues immediately:</p>
<p><strong>Run it, no config required.</strong></p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span></span></code></pre>
</div></td></tr><tr><td>deno</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;user-select:none;-webkit-user-select:none">$ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">deno</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> npm:oxlint@latest</span></span></code></pre>
</div></td></tr></tbody></table>
<p>While no setup or configuration is needed, Oxlint is configurable via an <code>.oxlintrc.json</code> file, which is useful for larger projects or projects that require more customization.
This configuration format is based on ESLint v8’s flat config, making migration easy and familiar.
Each source file is linted with the nearest applicable configuration, and you can use overrides to target specific glob patterns.
You can also extend shared configs to keep teams consistent.</p>
<p>For projects already using ESLint, <a href="https://github.com/oxc-project/oxlint-migrate" target="_blank" rel="noreferrer">oxlint-migrate</a> can be used to migrate an existing ESLint flat-config file to Oxlint.
Additionally, <a href="https://npmx.dev/package/eslint-plugin-oxlint" target="_blank" rel="noreferrer">eslint-plugin-oxlint</a> can disable overlapping ESLint rules while both linters are used together.
It is recommended to run <code>oxlint &amp;&amp; eslint</code> to benefit from Oxlint's faster feedback cycle.</p>
<p>For more detailed instructions on how to use Oxlint and integrate it with your project or editor, check out the <a href="https://oxc.rs/docs/guide/usage/linter" target="_blank" rel="noreferrer">installation guide</a>.</p>
<h2 id="versioning" tabindex="-1">Versioning <a class="header-anchor" href="#versioning" aria-label="Permalink to “Versioning”">&#8203;</a></h2>
<p>Unlike libraries that ship runtime code, a linter only changes the diagnostics it returns. Oxlint adheres to semantic versioning:</p>
<ul>
<li>Patch releases: Bug fixes only.</li>
<li>Minor releases: Expand rule coverage and diagnostics, without requiring configuration changes.</li>
<li>Major releases: CLI or configuration changes, that may require migration.
Note that minor releases can still break your CI if newly added rules uncover previously hidden issues. Learn more in our <a href="https://oxc.rs/docs/guide/usage/linter/versioning" target="_blank" rel="noreferrer">Versioning guide</a>.</li>
</ul>
<h2 id="highlights" tabindex="-1">Highlights <a class="header-anchor" href="#highlights" aria-label="Permalink to “Highlights”">&#8203;</a></h2>
<h3 id="comprehensive-rule-coverage" tabindex="-1">Comprehensive Rule Coverage <a class="header-anchor" href="#comprehensive-rule-coverage" aria-label="Permalink to “Comprehensive Rule Coverage”">&#8203;</a></h3>
<p>Oxlint includes over 500 rules from various sources:</p>
<ul>
<li>Complete ESLint rule set, including TypeScript-specific rules from <code>typescript-eslint</code> (excluding type checked rules).</li>
<li>Popular plugin rules from <code>eslint-plugin-unicorn</code>, <code>eslint-plugin-jsdoc</code>, <code>eslint-plugin-react</code>, <code>eslint-plugin-react-hooks</code>, <code>eslint-plugin-jest</code>, and <code>eslint-plugin-import</code></li>
<li>Unique Oxlint rules like <a href="https://oxc.rs/docs/guide/usage/linter/rules/oxc/bad-comparison-sequence" target="_blank" rel="noreferrer">bad comparison sequence</a>, <a href="https://oxc.rs/docs/guide/usage/linter/rules/oxc/const-comparisons" target="_blank" rel="noreferrer">const comparisons</a>, and <a href="https://oxc.rs/docs/guide/usage/linter/rules/oxc/only-used-in-recursion" target="_blank" rel="noreferrer">only used in recursion</a></li>
</ul>
<h3 id="flexible-configuration" tabindex="-1">Flexible Configuration <a class="header-anchor" href="#flexible-configuration" aria-label="Permalink to “Flexible Configuration”">&#8203;</a></h3>
<p>Configure Oxlint through <code>.oxlintrc.json</code> files with support for:</p>
<ul>
<li>Nested configurations that apply to specific directories</li>
<li>Override patterns for targeting specific file types or locations</li>
<li>Shared configuration extending for team consistency</li>
</ul>
<h3 id="editor-integration" tabindex="-1">Editor Integration <a class="header-anchor" href="#editor-integration" aria-label="Permalink to “Editor Integration”">&#8203;</a></h3>
<p>First-class editor support with extensions for:</p>
<ul>
<li><a href="https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode" target="_blank" rel="noreferrer">VS Code</a></li>
<li><a href="https://plugins.jetbrains.com/plugin/27061-oxc" target="_blank" rel="noreferrer">IntelliJ IDEA and WebStorm</a></li>
<li><a href="https://zed.dev/extensions?query=oxc" target="_blank" rel="noreferrer">Zed Editor</a></li>
<li>Language server protocol support for other editors</li>
</ul>
<h3 id="helpful-diagnostics" tabindex="-1">Helpful Diagnostics <a class="header-anchor" href="#helpful-diagnostics" aria-label="Permalink to “Helpful Diagnostics”">&#8203;</a></h3>
<p>Oxlint is built to deliver clear, actionable error messages - not just describing the issue, but visualizing it and suggesting how to fix it.</p>
<p><img src="https://github.com/oxc-project/oxc/assets/1430279/094a3b24-0433-42ae-aad2-48a7dec2b985" alt="CLI Demo">
<em>Oxlint running in the terminal with detailed error reporting</em></p>
<h2 id="benchmark" tabindex="-1">Benchmark <a class="header-anchor" href="#benchmark" aria-label="Permalink to “Benchmark”">&#8203;</a></h2>
<p>Our <a href="https://github.com/oxc-project/bench-javascript-linter" target="_blank" rel="noreferrer">benchmark</a> reveals that Oxlint is around 50~100 times faster than ESLint with the same setup.</p>
<table tabindex="0">
<thead>
<tr>
<th>Tool</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>oxlint (multi thread)</td>
<td>615.3 ms</td>
</tr>
<tr>
<td>oxlint (single thread)</td>
<td>1.840 s</td>
</tr>
<tr>
<td>eslint</td>
<td>33.481 s</td>
</tr>
</tbody>
</table>
<h2 id="roadmap" tabindex="-1">Roadmap <a class="header-anchor" href="#roadmap" aria-label="Permalink to “Roadmap”">&#8203;</a></h2>
<p>Oxlint 1.0 is just the beginning! While it is stable, we still have important features and improvements planned for future releases:</p>
<p><strong>Custom Rules</strong> – JavaScript plugin support is coming soon, enabling teams to write custom rules that integrate seamlessly with Oxlint's architecture.</p>
<p><strong>Performance Optimizations</strong> – Continued improvements to parsing and analysis speed.</p>
<p><strong>Fine-grained (per-glob) configuration</strong> - ESLint v9 configuration</p>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>Oxlint 1.0 represents the collective effort of <a href="https://github.com/oxc-project/oxc/graphs/contributors" target="_blank" rel="noreferrer">over 200 contributors</a> who have shaped this project. We're grateful for every bug report, feature request, and code contribution.</p>
<p>Special recognition goes to:</p>
<ul>
<li><a href="https://github.com/branchseer" target="_blank" rel="noreferrer">@branchseer</a> for implementing the multi-file analysis runtime.</li>
<li><a href="https://github.com/camc314" target="_blank" rel="noreferrer">@camc314</a>, <a href="https://github.com/mysteryven" target="_blank" rel="noreferrer">@mysteryven</a>, and <a href="https://github.com/shulaoda" target="_blank" rel="noreferrer">@shulaoda</a> for implementing many sophisticated lint rules, testing, and constantly improving everything.</li>
<li><a href="https://github.com/camchenry" target="_blank" rel="noreferrer">@camchenry</a> for implementing nested configuration support.</li>
<li><a href="https://github.com/DonIsaac" target="_blank" rel="noreferrer">@DonIsaac</a> for improving configuration, documentation and website, and for representing Oxc at <a href="https://2024.squiggleconf.com" target="_blank" rel="noreferrer">SquiggleConf 2024</a>.</li>
<li><a href="https://github.com/leaysgur" target="_blank" rel="noreferrer">@leaysgur</a> for the RegExp parser and JSDoc plugin.</li>
<li><a href="https://github.com/Sysix" target="_blank" rel="noreferrer">@Sysix</a> for maintaining <code>eslint-plugin-oxlint</code> and significant contributions to the language server and VSCode extension.</li>
<li><a href="https://github.com/u9g" target="_blank" rel="noreferrer">@u9g</a> and <a href="https://github.com/rzvxa" target="_blank" rel="noreferrer">@rzvxa</a> for implementing control flow graph analysis.</li>
</ul>
<h2 id="join-the-community" tabindex="-1">Join the Community <a class="header-anchor" href="#join-the-community" aria-label="Permalink to “Join the Community”">&#8203;</a></h2>
<p>We'd love to hear your feedback on Oxlint and are excited to see how it helps improve your development workflow. Connect with us:</p>
<ul>
<li><strong>Discord</strong>: Join our <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">community server</a> for real-time discussions</li>
<li><strong>GitHub</strong>: Share feedback on <a href="https://github.com/oxc-project/oxc/discussions" target="_blank" rel="noreferrer">GitHub Discussions</a></li>
<li><strong>Issues</strong>: Report bugs or request features on our <a href="https://github.com/oxc-project/oxc/issues" target="_blank" rel="noreferrer">issue tracker</a></li>
</ul>
<p>Your feedback drives Oxlint's evolution.</p>
<h2 id="give-it-a-try" tabindex="-1">Give It a Try <a class="header-anchor" href="#give-it-a-try" aria-label="Permalink to “Give It a Try”">&#8203;</a></h2>
<p>To get started, follow the <a href="https://oxc.rs/docs/guide/usage/linter" target="_blank" rel="noreferrer">installation guide</a>, or learn more about the <a href="https://oxc.rs/docs/guide/introduction" target="_blank" rel="noreferrer">Oxc project</a>.</p>
]]></content:encoded>
            <author>Boshen</author>
            <author>Cameron</author>
        </item>
        <item>
            <title><![CDATA[Oxlint Type-Aware Preview]]></title>
            <link>https://oxc.rs/blog/2025-08-17-oxlint-type-aware</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-08-17-oxlint-type-aware</guid>
            <pubDate>Sun, 17 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the technical preview of type-aware linting.</strong> For the latest alpha release with improved stability, configurability, and rule coverage, see the <a href="/blog/2025-12-08-type-aware-alpha.html">Type-Aware Linting Alpha announcement</a>.</p>
</Alert>
<br>
<p>We're thrilled to announce type-aware linting in <code>oxlint</code>!</p>
<p>The long-awaited <code>no-floating-promises</code> and related rules are here.</p>
<p>This preview release aims to engage with the community for collaboration and
discussion by documenting our decision process and technical details.</p>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>If <code>oxlint</code> is already configured, install <code>oxlint-tsgolint</code> and run <code>oxlint</code> with the <code>--type-aware</code> flag:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div><p>If <code>oxlint</code> is not configured but you want to see <code>no-floating-promises</code> in action:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div><p>We expect to see, for example:</p>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> × typescript</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">eslint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(no</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">floating</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">promises): Promises must be awaited, end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a call to .catch, end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a call to .then </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a rejection handler or be explicitly marked </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ignored</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> with</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `void`</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> operator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   ╭─[packages</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">rolldown</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">api</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">watch</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">watcher.ts:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">29</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> │       </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> │       </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">originClose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   ·       ──────────────</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">31</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> │     };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   ╰────</span></span></code></pre>
</div><p>Please visit our <a href="https://oxc.rs/docs/guide/usage/linter.html" target="_blank" rel="noreferrer">usage guide</a> for more configuration options.</p>
<h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<p>Our testing shows that repositories which previously took a minute to run with <code>typescript-eslint</code> now complete in less than 10 seconds.</p>
<p>This is achieved by leveraging <a href="https://github.com/microsoft/typescript-go" target="_blank" rel="noreferrer"><code>typescript-go</code></a>,
the <a href="https://devblogs.microsoft.com/typescript/typescript-native-port" target="_blank" rel="noreferrer">10x faster TypeScript</a> written in Go.</p>
<p>Using projects from <a href="https://github.com/oxc-project/oxc-ecosystem-ci" target="_blank" rel="noreferrer">oxc-ecosystem-ci</a>:</p>
<p>| Project  | Files | Time |
|</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the technical preview of type-aware linting.</strong> For the latest alpha release with improved stability, configurability, and rule coverage, see the <a href="/blog/2025-12-08-type-aware-alpha.html">Type-Aware Linting Alpha announcement</a>.</p>
</Alert>
<br>
<p>We're thrilled to announce type-aware linting in <code>oxlint</code>!</p>
<p>The long-awaited <code>no-floating-promises</code> and related rules are here.</p>
<p>This preview release aims to engage with the community for collaboration and
discussion by documenting our decision process and technical details.</p>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>If <code>oxlint</code> is already configured, install <code>oxlint-tsgolint</code> and run <code>oxlint</code> with the <code>--type-aware</code> flag:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div><p>If <code>oxlint</code> is not configured but you want to see <code>no-floating-promises</code> in action:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div><p>We expect to see, for example:</p>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> × typescript</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">eslint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(no</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">floating</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">promises): Promises must be awaited, end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a call to .catch, end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a call to .then </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a rejection handler or be explicitly marked </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ignored</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> with</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `void`</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> operator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   ╭─[packages</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">rolldown</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">api</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">watch</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">watcher.ts:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">29</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> │       </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> │       </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">originClose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   ·       ──────────────</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">31</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> │     };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   ╰────</span></span></code></pre>
</div><p>Please visit our <a href="https://oxc.rs/docs/guide/usage/linter.html" target="_blank" rel="noreferrer">usage guide</a> for more configuration options.</p>
<h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<p>Our testing shows that repositories which previously took a minute to run with <code>typescript-eslint</code> now complete in less than 10 seconds.</p>
<p>This is achieved by leveraging <a href="https://github.com/microsoft/typescript-go" target="_blank" rel="noreferrer"><code>typescript-go</code></a>,
the <a href="https://devblogs.microsoft.com/typescript/typescript-native-port" target="_blank" rel="noreferrer">10x faster TypeScript</a> written in Go.</p>
<p>Using projects from <a href="https://github.com/oxc-project/oxc-ecosystem-ci" target="_blank" rel="noreferrer">oxc-ecosystem-ci</a>:</p>
<table tabindex="0">
<thead>
<tr>
<th>Project</th>
<th>Files</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>napi-rs</td>
<td>144</td>
<td>1.0s</td>
</tr>
<tr>
<td>preact</td>
<td>245</td>
<td>2.7s</td>
</tr>
<tr>
<td>rolldown</td>
<td>314</td>
<td>1.5s</td>
</tr>
<tr>
<td>bluesky</td>
<td>1152</td>
<td>7.0s</td>
</tr>
</tbody>
</table>
<h2 id="type-aware-linting" tabindex="-1">Type-Aware Linting <a class="header-anchor" href="#type-aware-linting" aria-label="Permalink to “Type-Aware Linting”">&#8203;</a></h2>
<p>Please refer to
<a href="https://www.joshuakgoldberg.com/blog/rust-based-javascript-linters-fast-but-no-typed-linting-right-now" target="_blank" rel="noreferrer">Rust-Based JavaScript Linters: Fast, But No Typed Linting Right Now</a>
to understand the current status of type-aware linting in the ecosystem.</p>
<h2 id="technical-details" tabindex="-1">Technical Details <a class="header-anchor" href="#technical-details" aria-label="Permalink to “Technical Details”">&#8203;</a></h2>
<p>The core of this new functionality is <a href="https://github.com/oxc-project/tsgolint" target="_blank" rel="noreferrer">oxc-project/tsgolint</a>.</p>
<p>The <code>tsgolint</code> project was initially prototyped as <a href="https://github.com/typescript-eslint/tsgolint" target="_blank" rel="noreferrer">typescript-eslint/tsgolint</a>.
However, the <code>typescript-eslint</code> team decided not to allocate development resources to this prototype, as they plan to continue their work on <code>typescript-eslint</code> for typed linting with ESLint.</p>
<p><a href="https://github.com/Boshen" target="_blank" rel="noreferrer">@boshen</a> reached out to <a href="https://github.com/auvred" target="_blank" rel="noreferrer">@auvred</a> for a forked, scoped-down version adapted for oxlint.
This version would only contain type-aware rules without the sophisticated configuration resolution a full linter would require.</p>
<p><a href="https://github.com/auvred" target="_blank" rel="noreferrer">@auvred</a> generously offered to continue its development under the Oxc organization.</p>
<h3 id="architecture" tabindex="-1">Architecture <a class="header-anchor" href="#architecture" aria-label="Permalink to “Architecture”">&#8203;</a></h3>
<p><code>oxlint</code> (written in Rust) and <code>tsgolint</code> (written in Go) are compiled into their own binaries.</p>
<p><code>oxlint</code> serves as the &quot;frontend&quot; for <code>tsgolint</code>, handling the CLI, path traversal, ignore logic, and diagnostic printing.</p>
<p><code>tsgolint</code> acts as the backend for <code>oxlint</code>, accepting paths and configuration as input and outputting structured diagnostics.</p>
<p>This creates a simple pipeline:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>oxlint CLI (returns paths + rules + configuration)</span></span>
<span class="line"><span>  -> tsgolint (returns diagnostics)</span></span>
<span class="line"><span>  -> oxlint CLI (prints diagnostics)</span></span></code></pre>
</div><h3 id="tsgolint" tabindex="-1"><code>tsgolint</code> <a class="header-anchor" href="#tsgolint" aria-label="Permalink to “tsgolint”">&#8203;</a></h3>
<p><code>tsgolint</code> does not communicate with typescript-go via public APIs.</p>
<p>Instead, it compiles <code>typescript-go</code> by <a href="https://github.com/oxc-project/tsgolint/tree/main/shim" target="_blank" rel="noreferrer">shimming</a> its internal APIs to make them public.</p>
<p>All type-aware rules are written directly against these shimmed APIs.</p>
<p>While this isn't the recommended approach for accessing internals, it works!</p>
<h2 id="decision-process" tabindex="-1">Decision Process <a class="header-anchor" href="#decision-process" aria-label="Permalink to “Decision Process”">&#8203;</a></h2>
<h3 id="write-our-own-type-checker" tabindex="-1">Write our own type checker <a class="header-anchor" href="#write-our-own-type-checker" aria-label="Permalink to “Write our own type checker”">&#8203;</a></h3>
<p>Previous abandoned attempts to implement a type-checker included:</p>
<ul>
<li>My own attempt at <a href="https://gist.github.com/Boshen/d189de0fe0720a30c5182cb666e3e9a5" target="_blank" rel="noreferrer">writing type inference</a></li>
<li><a href="https://github.com/oxc-project/oxc/pull/413" target="_blank" rel="noreferrer">Integrate</a> <a href="https://github.com/kaleidawave/ezno" target="_blank" rel="noreferrer">ezno type checker</a> by <a href="https://github.com/kaleidawave" target="_blank" rel="noreferrer">@kaleidawave</a></li>
<li><a href="https://github.com/dudykr/stc" target="_blank" rel="noreferrer">stc</a> by <a href="https://github.com/kdy1" target="_blank" rel="noreferrer">@kdy1</a></li>
<li>There are also many attempts in the community that did not go far.</li>
</ul>
<p>Additionally, there's the work-in-progress <a href="https://biomejs.dev/blog/biome-v2/" target="_blank" rel="noreferrer">Biome 2.0</a> with its own type-inference implementation.</p>
<p>We determined that writing our own type-inferencer or type-checker was not feasible due to
the challenge of keeping up with a fast-moving target like TypeScript.</p>
<h3 id="communication-with-typescript-compiler" tabindex="-1">Communication with TypeScript Compiler <a class="header-anchor" href="#communication-with-typescript-compiler" aria-label="Permalink to “Communication with TypeScript Compiler”">&#8203;</a></h3>
<p>Prior to <code>typescript-go</code>, projects added plugin interfaces to TypeScript's public API by either mapping its AST to <code>estree</code> or directly traversing the TypeScript AST. Examples include:</p>
<ul>
<li><a href="https://typescript-eslint.io/getting-started/typed-linting" target="_blank" rel="noreferrer">typescript-eslint</a></li>
<li><a href="https://github.com/johnsoncodehk/tsslint" target="_blank" rel="noreferrer">tsslint</a></li>
<li><a href="https://github.com/ArnaudBarre/tsl" target="_blank" rel="noreferrer">tsl</a></li>
</ul>
<p>We also explored <a href="https://github.com/oxc-project/oxc/discussions/2855" target="_blank" rel="noreferrer">inter-process communication with oxlint</a> but abandoned the idea.</p>
<p>With <code>typescript-go</code>, the TypeScript team is <a href="https://github.com/microsoft/typescript-go/discussions/455" target="_blank" rel="noreferrer">leaning towards</a>
encoding the TypeScript AST and decoding it on the JavaScript side through inter-process communication.</p>
<p>While these approaches work, they still incur:</p>
<ul>
<li>Performance issues of varying degrees that don't suit oxlint's performance characteristics.</li>
<li>The cost of maintaining an AST mapping from TypeScript's AST.</li>
</ul>
<h2 id="considerations" tabindex="-1">Considerations <a class="header-anchor" href="#considerations" aria-label="Permalink to “Considerations”">&#8203;</a></h2>
<p>While <code>tsgolint</code> solves the performance issue, there are other technical challenges that need to be addressed.</p>
<h3 id="requirement-for-a-different-typescript-version" tabindex="-1">Requirement for a Different TypeScript Version <a class="header-anchor" href="#requirement-for-a-different-typescript-version" aria-label="Permalink to “Requirement for a Different TypeScript Version”">&#8203;</a></h3>
<p>We plan to release snapshots of <code>typescript-go</code> versions and align their version numbers with TypeScript.
You will then be able to install <code>oxlint-typescript</code> with the correct TypeScript version.</p>
<p>The downside of this approach is that you may need to upgrade TypeScript if <code>oxlint-tsgolint</code> requires changes.</p>
<h3 id="maintenance-cost-of-tsgolint" tabindex="-1">Maintenance cost of <code>tsgolint</code> <a class="header-anchor" href="#maintenance-cost-of-tsgolint" aria-label="Permalink to “Maintenance cost of tsgolint”">&#8203;</a></h3>
<p>Shimming TypeScript's internal APIs carries some risk. However, the TypeScript AST and its visitor are actually quite stable.
We accept this risk and will fix breaking changes when upgrading <code>typescript-go</code>.</p>
<p>Our <code>typescript-go</code> version is synced every day.</p>
<h2 id="performance-issues" tabindex="-1">Performance Issues <a class="header-anchor" href="#performance-issues" aria-label="Permalink to “Performance Issues”">&#8203;</a></h2>
<p><code>tsgolint</code> currently does not perform well on large monorepos with hundreds of projects or lots of project references.</p>
<p>It may hang with a deadlock or cause OOM (out-of-memory) if a bug is encountered.</p>
<p>We are actively addressing these issues, profiling and submitting improvements to <code>typescript-go</code>, benefiting all <code>typescript-go</code> users.</p>
<p>Our core team member <a href="https://github.com/camc314" target="_blank" rel="noreferrer">@camc314</a> has already submitted <a href="https://github.com/microsoft/typescript-go/pulls?q=is%3Apr+author%3Acamc314+" target="_blank" rel="noreferrer">many PRs</a> that made several code paths significantly faster.</p>
<h2 id="v1-0-release" tabindex="-1">v1.0 Release <a class="header-anchor" href="#v1-0-release" aria-label="Permalink to “v1.0 Release”">&#8203;</a></h2>
<p>For <code>tsgolint</code> v1.0, we will address:</p>
<ul>
<li>performance issue for large monorepos</li>
<li>be able to configure individual rules</li>
<li>correctness of each individual rules</li>
<li>IDE support</li>
<li>overall stability</li>
</ul>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>We'd like to extend our gratitude to:</p>
<ul>
<li>The TypeScript team for creating <code>typescript-go</code>.</li>
<li>The <code>typescript-eslint</code> team for their heartwarming support.</li>
<li><a href="https://github.com/auvred" target="_blank" rel="noreferrer">@auvred</a> for creating <code>tsgolint</code>.</li>
<li><a href="https://github.com/camchenry" target="_blank" rel="noreferrer">@camchenry</a> for the <code>oxlint</code> + <code>tsgolint</code> integration.</li>
<li><a href="https://github.com/camc314" target="_blank" rel="noreferrer">@camc314</a> for work on performance issues.</li>
</ul>
<h2 id="join-the-community" tabindex="-1">Join the Community <a class="header-anchor" href="#join-the-community" aria-label="Permalink to “Join the Community”">&#8203;</a></h2>
<p>We'd love to hear your feedback on <code>oxlint</code> and type-aware linting and are excited to see how it helps improve your development workflow.</p>
<p>Connect with us:</p>
<ul>
<li><strong>Discord</strong>: Join our <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">community server</a> for real-time discussions</li>
<li><strong>GitHub</strong>: Share feedback on <a href="https://github.com/oxc-project/oxc/discussions" target="_blank" rel="noreferrer">GitHub Discussions</a></li>
<li><strong>Issues</strong>: Report <code>oxlint</code> bugs to <a href="https://github.com/oxc-project/oxc/issues" target="_blank" rel="noreferrer">oxc</a> and type-aware linting bugs to <a href="https://github.com/oxc-project/tsgolint/issues" target="_blank" rel="noreferrer">tsgolint</a>.</li>
</ul>
<h2 id="next-steps" tabindex="-1">Next steps <a class="header-anchor" href="#next-steps" aria-label="Permalink to “Next steps”">&#8203;</a></h2>
<p>Install <code>oxlint</code>:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint@latest</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --init</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # generate .oxlintrc.json</span></span></code></pre>
</div><p>or follow the <a href="https://oxc.rs/docs/guide/usage/linter" target="_blank" rel="noreferrer">installation guide</a>.</p>
<p>Use the <code>--type-aware</code> CLI flag.</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dlx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div><p>And play around with any of the type-aware rules in <code>.oxlintrc.json</code>:</p>
<div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "$schema"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"./node_modules/oxlint/configuration_schema.json"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/await-thenable"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-array-delete"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-base-to-string"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-confusing-void-expression"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-duplicate-type-constituents"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-floating-promises"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-for-in-array"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-implied-eval"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-meaningless-void-operator"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-misused-promises"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-misused-spread"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-mixed-enums"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-redundant-type-constituents"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unnecessary-boolean-literal-compare"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unnecessary-template-expression"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unnecessary-type-arguments"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unnecessary-type-assertion"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-argument"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-assignment"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-call"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-enum-comparison"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-member-access"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-return"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-type-assertion"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-unsafe-unary-minus"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/non-nullable-type-assertion-style"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/only-throw-error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/prefer-promise-reject-errors"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/prefer-reduce-type-parameter"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/prefer-return-this-type"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/promise-function-async"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/related-getter-setter-pairs"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/require-array-sort-compare"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/require-await"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/restrict-plus-operands"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/restrict-template-expressions"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/return-await"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/switch-exhaustiveness-check"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/unbound-method"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/use-unknown-in-catch-callback-variable"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div>]]></content:encoded>
            <author>Boshen</author>
            <author>auvred</author>
            <author>Cam</author>
            <author>Cameron</author>
        </item>
        <item>
            <title><![CDATA[Oxlint JS Plugins Preview]]></title>
            <link>https://oxc.rs/blog/2025-10-09-oxlint-js-plugins</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-10-09-oxlint-js-plugins</guid>
            <pubDate>Thu, 09 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the preview release of Oxlint JS Plugins.</strong> JS Plugins have since reached alpha! See the <a href="/blog/2026-03-11-oxlint-js-plugins-alpha.html">Oxlint JS Plugins Alpha announcement</a> for the latest features and improvements.</p>
</Alert>
<br>
<p>Earlier this year <a href="https://github.com/oxc-project/oxc/discussions/10342" target="_blank" rel="noreferrer">we asked for input from the community</a>
to inform design for Oxlint support for custom JS plugins. Today, we are pleased to announce the result of many months
of research, prototyping, and finally building:</p>
<p><strong>Oxlint supports plugins written in JS!</strong></p>
<h4 id="key-features" tabindex="-1">Key features <a class="header-anchor" href="#key-features" aria-label="Permalink to “Key features”">&#8203;</a></h4>
<ul>
<li>ESLint-compatible plugin API. Oxlint will be able to run many existing ESLint plugins without modification.</li>
<li>An alternative API which is slightly different, and unlocks better performance.</li>
</ul>
<h4 id="what-this-is-and-isn-t" tabindex="-1">What this is and isn't <a class="header-anchor" href="#what-this-is-and-isn-t" aria-label="Permalink to “What this is and isn't”">&#8203;</a></h4>
<p>This preview release is just the beginning. It is important to note that:</p>
<ul>
<li>This initial release does not implement all of ESLint's plugin API.</li>
<li>Performance is good, but it's going to get <em>way</em> better - we have many optimizations in the pipeline.</li>
</ul>
<p>The most commonly-used APIs for code-checking rules <a href="#features">are implemented</a>, so many existing ESLint rules will already work.
But token-related APIs are absent, so stylistic (formatting) rules will not.</p>
<p>We invite users to take it for a spin, give feedback, and inform our priorities for the next phase of development.</p>
<h4 id="this-blog-post-covers" tabindex="-1">This blog post covers <a class="header-anchor" href="#this-blog-post-covers" aria-label="Permalink to “This blog post covers”">&#8203;</a></h4>
<ol>
<li>How to use it.</li>
<li>What's coming next.</li>
<li>Some of the technical details that enable our &quot;have cake and eat it&quot; approach of providing both ESLint compatibility
<strong>and</strong> excellent performance.</li>
</ol>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>Install Oxlint in your project:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span></span></code></pre>
</div><p>Write a custom JS plugin:</p>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// plugin.js</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// The simplest rule of all - no debugger</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> rule</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">      DebuggerStatement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"No debugger!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          node,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> plugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  meta: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"best-plugin-ever"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  rules: {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    "no-debugger"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: rule,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> plugin;</span></span></code></pre>
</div><p>Create config file enabling the plugin:</p>
<div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// .oxlintrc.json</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "jsPlugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"./plugin.js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "best-plugin-ever/no-debugger"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>Add a file to be linted:</p>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// foo.js</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">debugger</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
</div><p>Run Oxlint:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span></span></code></pre>
</div><p>Expect to see:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span> x best-plugin-ever(no-debugger): No debugger!</span></span>
<span class="line"><span>  ,-[foo.js:1:1]</span></span>
<span class="line"><span>1 | debugger;</span></span>
<span class="line"><span>  : ^^^^^^^^^</span></span>
<span class="line"><span>  `</span></span></code></pre>
</div>]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the preview release of Oxlint JS Plugins.</strong> JS Plugins have since reached alpha! See the <a href="/blog/2026-03-11-oxlint-js-plugins-alpha.html">Oxlint JS Plugins Alpha announcement</a> for the latest features and improvements.</p>
</Alert>
<br>
<p>Earlier this year <a href="https://github.com/oxc-project/oxc/discussions/10342" target="_blank" rel="noreferrer">we asked for input from the community</a>
to inform design for Oxlint support for custom JS plugins. Today, we are pleased to announce the result of many months
of research, prototyping, and finally building:</p>
<p><strong>Oxlint supports plugins written in JS!</strong></p>
<h4 id="key-features" tabindex="-1">Key features <a class="header-anchor" href="#key-features" aria-label="Permalink to “Key features”">&#8203;</a></h4>
<ul>
<li>ESLint-compatible plugin API. Oxlint will be able to run many existing ESLint plugins without modification.</li>
<li>An alternative API which is slightly different, and unlocks better performance.</li>
</ul>
<h4 id="what-this-is-and-isn-t" tabindex="-1">What this is and isn't <a class="header-anchor" href="#what-this-is-and-isn-t" aria-label="Permalink to “What this is and isn't”">&#8203;</a></h4>
<p>This preview release is just the beginning. It is important to note that:</p>
<ul>
<li>This initial release does not implement all of ESLint's plugin API.</li>
<li>Performance is good, but it's going to get <em>way</em> better - we have many optimizations in the pipeline.</li>
</ul>
<p>The most commonly-used APIs for code-checking rules <a href="#features">are implemented</a>, so many existing ESLint rules will already work.
But token-related APIs are absent, so stylistic (formatting) rules will not.</p>
<p>We invite users to take it for a spin, give feedback, and inform our priorities for the next phase of development.</p>
<h4 id="this-blog-post-covers" tabindex="-1">This blog post covers <a class="header-anchor" href="#this-blog-post-covers" aria-label="Permalink to “This blog post covers”">&#8203;</a></h4>
<ol>
<li>How to use it.</li>
<li>What's coming next.</li>
<li>Some of the technical details that enable our &quot;have cake and eat it&quot; approach of providing both ESLint compatibility
<strong>and</strong> excellent performance.</li>
</ol>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>Install Oxlint in your project:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span></span></code></pre>
</div><p>Write a custom JS plugin:</p>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// plugin.js</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// The simplest rule of all - no debugger</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> rule</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">      DebuggerStatement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"No debugger!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          node,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> plugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  meta: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"best-plugin-ever"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  rules: {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    "no-debugger"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: rule,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> plugin;</span></span></code></pre>
</div><p>Create config file enabling the plugin:</p>
<div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// .oxlintrc.json</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "jsPlugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"./plugin.js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "best-plugin-ever/no-debugger"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>Add a file to be linted:</p>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// foo.js</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">debugger</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
</div><p>Run Oxlint:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span></span></code></pre>
</div><p>Expect to see:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span> x best-plugin-ever(no-debugger): No debugger!</span></span>
<span class="line"><span>  ,-[foo.js:1:1]</span></span>
<span class="line"><span>1 | debugger;</span></span>
<span class="line"><span>  : ^^^^^^^^^</span></span>
<span class="line"><span>  `----</span></span></code></pre>
</div><p>For further details on authoring plugins, see <a href="/docs/guide/usage/linter/writing-js-plugins.html">the docs</a>.</p>
<h2 id="alternative-api" tabindex="-1">Alternative API <a class="header-anchor" href="#alternative-api" aria-label="Permalink to “Alternative API”">&#8203;</a></h2>
<p>Oxlint also offers a slightly different API which unlocks better performance.</p>
<p><strong>This alternative API produces plugins which are compatible with ESLint, as well as Oxlint.</strong></p>
<p>Example rule that flags files containing more than 5 class declarations:</p>
<h4 id="eslint-version" tabindex="-1">ESLint version <a class="header-anchor" href="#eslint-version" aria-label="Permalink to “ESLint version”">&#8203;</a></h4>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> rule</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> classCount </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">      ClassDeclaration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        classCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (classCount </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Too many classes"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, node });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h4 id="alternative-api-version" tabindex="-1">Alternative API version <a class="header-anchor" href="#alternative-api-version" aria-label="Permalink to “Alternative API version”">&#8203;</a></h4>
<div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { defineRule } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxlint"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> rule</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> defineRule</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  createOnce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Define counter variable</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> classCount;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">      before</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // Reset counter before traversing AST of each file</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        classCount </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      // Same as before</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">      ClassDeclaration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        classCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (classCount </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Too many classes"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, node });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span></code></pre>
</div><h4 id="the-differences" tabindex="-1">The differences <a class="header-anchor" href="#the-differences" aria-label="Permalink to “The differences”">&#8203;</a></h4>
<ol>
<li>Wrap the rule object in <code>defineRule(...)</code>.</li>
</ol>
<div class="language-diff"><button title="Copy Code" class="copy"></button><span class="lang">diff</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#B31D28;--shiki-dark:#FDAEB7">- const rule = {</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">+ const rule = defineRule({</span></span></code></pre>
</div><ol start="2">
<li>Use <code>createOnce</code> instead of <code>create</code>.</li>
</ol>
<div class="language-diff"><button title="Copy Code" class="copy"></button><span class="lang">diff</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#B31D28;--shiki-dark:#FDAEB7">-   create(context) {</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">+   createOnce(context) {</span></span></code></pre>
</div><ol start="3">
<li>Move any per-file setup from body of <code>create</code> into <code>before</code> hook.</li>
</ol>
<div class="language-diff"><button title="Copy Code" class="copy"></button><span class="lang">diff</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#B31D28;--shiki-dark:#FDAEB7">-     let classCount = 0;</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">+     let classCount;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      return {</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">+       before() {</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">+         classCount = 0; // Reset counter</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">+       },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ClassDeclaration(node) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          classCount++;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          if (classCount === 6) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            context.report({ message: "Too many classes", node });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  });</span></span></code></pre>
</div><p>This is the only significant difference - <code>create</code> (ESLint's method) is called repeatedly <em>for each file</em>,
whereas <code>createOnce</code> is called once only.</p>
<p>All other APIs behave exactly the same as in ESLint.</p>
<p>The reasons why this alternative API has potential to greatly improve performance are explained in
<a href="/docs/guide/usage/linter/writing-js-plugins.html#why-is-the-alternative-api-faster">the docs</a>.</p>
<h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<p>As mentioned above, performance has not been our focus in this initial preview release of Oxlint JS plugins.
Our primary goal has been to fill out enough of the API for JS plugins to be useful in real world projects,
and gather feedback from early adopters.</p>
<p>Performance at present is decent, but not by any means stellar.</p>
<p>However - and we feel this is the important point - our prototype of the <em>next</em> version demonstrates that the
architectural design we've settled on is capable of <em>exceptional</em> performance, once various optimizations are added
into the mix (see <a href="#under-the-hood">Under the hood</a>).</p>
<p>We'll be applying those optimization over the course of the next few months, and users will see multiple x speed-ups
compared to the current version.</p>
<p>That said, even without those optimizations, Oxlint's performance is still competitive.</p>
<p>Oxlint vs ESLint linting a medium-sized TypeScript project <a href="https://github.com/vuejs/core" target="_blank" rel="noreferrer">vuejs/core</a>:</p>
<table tabindex="0">
<thead>
<tr>
<th>Linter</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>ESLint</td>
<td>4,116 ms</td>
</tr>
<tr>
<td>ESLint multi-threaded</td>
<td>3,710 ms</td>
</tr>
<tr>
<td>Oxlint</td>
<td>48 ms</td>
</tr>
<tr>
<td>Oxlint with custom JS plugin</td>
<td>236 ms</td>
</tr>
</tbody>
</table>
<div>
<details>
<summary>Details</summary>
<div  class="info custom-block"><p class="custom-block-title custom-block-title-default">INFO</p>
<ul>
<li>Benchmark repo: <a href="https://github.com/overlookmotel/vue-core-cam/tree/bench-js-plugins" target="_blank" rel="noreferrer">https://github.com/overlookmotel/vue-core-cam/tree/bench-js-plugins</a></li>
<li>Benchmarked on MacBook Air M3, 24GB RAM</li>
<li>Bench command:</li>
</ul>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">hyperfine</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -i</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --warmup</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  './node_modules/.bin/oxlint --silent'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  './node_modules/.bin/oxlint -c .oxlintrc-with-custom-plugin.json --silent'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  'USE_CUSTOM_PLUGIN=true ./node_modules/.bin/eslint .'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  'USE_CUSTOM_PLUGIN=true ./node_modules/.bin/eslint . --concurrency=auto'</span></span></code></pre>
</div><p>Note: The version of Oxlint on NPM at time of writing (1.23.0) has a bug which affects this benchmark, and hugely
underestimates the cost of JS plugins. The above results were obtained using latest <code>main</code> branch, after the bug fix,
at <a href="https://github.com/oxc-project/oxc/commit/cd266b4c101c35c33e122457cdd0b514b44597a9" target="_blank" rel="noreferrer">this commit</a>.
Please also see <a href="#edit-18th-oct-2025">below</a>.</p>
</div>
</details>
</div>
<p>In this example, adding a simple JS plugin to Oxlint does have a significant cost, but Oxlint is still 15x faster
than ESLint, even using ESLint's new multi-threaded runner.</p>
<p>Obviously, more complicated JS plugins, or many of them, will have a higher performance cost.</p>
<h2 id="features" tabindex="-1">Features <a class="header-anchor" href="#features" aria-label="Permalink to “Features”">&#8203;</a></h2>
<p>Oxlint supports most of ESLint's APIs which are typically used in plugins/rules which rely only on AST inspection.
That includes most &quot;fix code&quot;-type rules.</p>
<p>It does not yet support token-based APIs, so stylistic (formatting) rules will not work yet.</p>
<h4 id="supported" tabindex="-1">Supported <a class="header-anchor" href="#supported" aria-label="Permalink to “Supported”">&#8203;</a></h4>
<ul>
<li>AST traversal</li>
<li>AST exploration (<code>node.parent</code>, <code>context.sourceCode.getAncestors</code>)</li>
<li>Fixes</li>
<li>Selectors (<a href="https://eslint.org/docs/latest/extend/selectors" target="_blank" rel="noreferrer">ESLint docs</a>)</li>
<li><code>SourceCode</code> APIs (e.g. <code>context.sourceCode.getText(node)</code>)</li>
</ul>
<h4 id="not-supported-yet" tabindex="-1">Not supported yet <a class="header-anchor" href="#not-supported-yet" aria-label="Permalink to “Not supported yet”">&#8203;</a></h4>
<ul>
<li>Language server (IDE) support</li>
<li>Rule options</li>
<li>Suggestions</li>
<li><s>Scope analysis</s> (<a href="https://github.com/oxc-project/oxc/pull/14890" target="_blank" rel="noreferrer">implemented</a> since v1.25.0)</li>
<li><code>SourceCode</code> APIs related to tokens and comments (e.g. <code>context.sourceCode.getTokens(node)</code>)</li>
<li>Control flow analysis</li>
</ul>
<h2 id="what-s-next" tabindex="-1">What's next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to “What's next”">&#8203;</a></h2>
<p>Over the next few months, we will be:</p>
<h4 id="_1-filling-out-the-plugin-api-surface" tabindex="-1">1. Filling out the plugin API surface <a class="header-anchor" href="#_1-filling-out-the-plugin-api-surface" aria-label="Permalink to “1. Filling out the plugin API surface”">&#8203;</a></h4>
<p>Aim is to support 100% of ESLint's plugin API surface, so that Oxlint will eventually be able to run <em>any</em> ESLint
plugin without modification.</p>
<h4 id="_2-improving-performance" tabindex="-1">2. Improving performance <a class="header-anchor" href="#_2-improving-performance" aria-label="Permalink to “2. Improving performance”">&#8203;</a></h4>
<p>Performance is already decent, but we have proven during our prototyping many significant performance gains from further
optimizations. We will apply them, and make JS plugins in Oxlint run at as close to Rust speed as we can get.</p>
<h2 id="under-the-hood" tabindex="-1">Under the hood <a class="header-anchor" href="#under-the-hood" aria-label="Permalink to “Under the hood”">&#8203;</a></h2>
<p>The rest of this post is not necessary to use JS plugins with Oxlint. But if you're interested in the geeky details
of how our implementation works, read on...</p>
<h3 id="the-big-question-to-eslint-compat-or-not-to-eslint-compat" tabindex="-1">The big question: To ESLint compat or not to ESLint compat? <a class="header-anchor" href="#the-big-question-to-eslint-compat-or-not-to-eslint-compat" aria-label="Permalink to “The big question: To ESLint compat or not to ESLint compat?”">&#8203;</a></h3>
<p>The question which <a href="https://github.com/oxc-project/oxc/discussions/10342" target="_blank" rel="noreferrer">we posed to the community</a> earlier this year
was whether Oxlint should aim for an ESLint-compatible plugin API or not.</p>
<p>Obviously, an ESLint-compatible interface is ideal in terms of familiarity and ease of migration from ESLint.</p>
<p>However, Oxlint is known for its excellent performance, and compromising that too much would not be desirable.</p>
<p>The main aim of our prototyping work over past few months has been to quantify what is the trade-off between performance
and ESLint compatibility, and to investigate if there's a &quot;have cake and eat it&quot; solution which satisfies both -
providing an ESLint-compatible API <em>and</em> acceptable performance (&quot;acceptable&quot; here means pretty damn fast!)</p>
<p>We believe that through a combination of different approaches, we've found a way to satisfy both demands.</p>
<h3 id="alternative-api-1" tabindex="-1">Alternative API <a class="header-anchor" href="#alternative-api-1" aria-label="Permalink to “Alternative API”">&#8203;</a></h3>
<p>See explanation <a href="/docs/guide/usage/linter/writing-js-plugins.html#why-is-the-alternative-api-faster">in docs</a>
of why this API unlocks potential for higher performance.</p>
<h3 id="raw-transfer" tabindex="-1">Raw transfer <a class="header-anchor" href="#raw-transfer" aria-label="Permalink to “Raw transfer”">&#8203;</a></h3>
<p>Tools like Oxc represent the code of a JS/TS file as an &quot;AST&quot;
(<a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank" rel="noreferrer">abstract syntax tree</a>).
ASTs are really big - much much larger than the source code they represent.</p>
<p>Typically, the biggest barrier to performant interop between JS and native languages like Rust is the serialization
and deserialization involved in transferring such large data structures between the &quot;two worlds&quot;.</p>
<p>The simplest and most common way to move an AST between JS and Rust is: Serialize the AST to JSON, send it across to JS
as a string and then &quot;rehydrate&quot; it again with <code>JSON.parse</code>. But this is extremely slow. Often the cost of these
conversions is so high that they massively outweigh the performance gain of using native code in the first place.
Other serialization formats are more efficient than JSON, but they still have a sizeable overhead.</p>
<p>We have developed a scheme &quot;raw transfer&quot; which cuts out serialization altogether, by using Rust's native memory layout
as the serialization format (more details on how it works <a href="https://github.com/oxc-project/oxc/issues/2409" target="_blank" rel="noreferrer">here</a>).</p>
<p>&quot;Raw transfer&quot; is the base of the current implementation of JS plugins.</p>
<h3 id="lazy-deserialization" tabindex="-1">Lazy deserialization <a class="header-anchor" href="#lazy-deserialization" aria-label="Permalink to “Lazy deserialization”">&#8203;</a></h3>
<p>The 2nd biggest enemy of good perf, particularly when running JS across multiple CPU cores in worker threads,
is the garbage collector. Every object you create also needs to be destroyed to recover its memory.
In JS, this is the job of the garbage collector. JS engines like V8 are highly optimized, but still garbage collection
is an expensive process, and GC &quot;steals&quot; CPU resources from the actual workload.</p>
<p>We have prototyped an AST visitor which deserializes the AST <em>lazily</em>, and only deserializes the parts of the AST which
actually <em>need</em> to be.</p>
<p>For example, if your lint rule relates to class declarations, this visitor will fly through most of the AST without
doing much, and will only create JS objects for <code>ClassDeclaration</code> AST nodes, which are then passed to the rule's code
to process. For the rest of the AST (variable declarations, <code>if</code> statements, functions, etc) there is no need to create
node objects at all.</p>
<p>This has 2 effects:</p>
<ol>
<li>Raw transfer cuts the cost of serialization to zero. Laziness dramatically reduces the other side
(deserialization) too.</li>
<li>Greatly reduced garbage collector pressure.</li>
</ol>
<p>Deno has taken a similar approach, which is explained brilliantly in
<a href="https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-11/" target="_blank" rel="noreferrer">Marvin Hagemeister's blog post</a>, and Deno lint
has a superbly efficient implementation.</p>
<p>However, we've found that it's the combination of lazy deserialization with &quot;raw transfer&quot; which delivers <em>really</em> good
performance. Our tests have found that, with both these overheads removed, JS plugins can run at much greater speed.</p>
<p>This optimization is not yet included in current version of JS plugins. We will implement it in a future version.</p>
<h2 id="try-it-out" tabindex="-1">Try it out! <a class="header-anchor" href="#try-it-out" aria-label="Permalink to “Try it out!”">&#8203;</a></h2>
<p>Please try out JS plugins and report your experience. All feedback - either positive or negative - is gratefully
received.</p>
<p>In particular, if you find that Oxlint is lacking some of the APIs you need for your plugins to work,
please let us know. We'll be filling in the gaps in the API over the next few months, and will prioritise those for
which there's greatest demand.</p>
<p>Happy linting!</p>
<hr>
<h4 id="edit-18th-oct-2025" tabindex="-1">Edit: 18th Oct 2025 <a class="header-anchor" href="#edit-18th-oct-2025" aria-label="Permalink to “Edit: 18th Oct 2025”">&#8203;</a></h4>
<p>The original version of this blog post published on 9th Oct contained benchmarks results which showed the performance
of Oxlint JS plugins to be far better than they are in reality. This was the result of a bug in Oxlint which was causing
JS plugins to be skipped on many files in certain circumstances when the config contains overrides. This bug lead to
the performance of JS plugins being way overestimated in the benchmarks we quoted.</p>
<p>We sincerely apologise for this mistake, and thank <a href="https://github.com/HerringtonDarkholme" target="_blank" rel="noreferrer">Herrington Darkholme</a>
for pointing out the error.</p>
]]></content:encoded>
            <author>overlookmotel</author>
            <author>Cameron</author>
        </item>
        <item>
            <title><![CDATA[Oxfmt: Oxc Formatter Alpha]]></title>
            <link>https://oxc.rs/blog/2025-12-01-oxfmt-alpha</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-12-01-oxfmt-alpha</guid>
            <pubDate>Mon, 01 Dec 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<AppBlogPostHeader /><Alert type="info">
<p><strong>This post announces the alpha release of Oxfmt.</strong> Oxfmt has since reached beta! See the <a href="/blog/2026-02-24-oxfmt-beta.html">Oxfmt Beta announcement</a> for the latest features and improvements.</p>
</Alert>
<p>We’re excited to announce the alpha release of <strong>Oxfmt</strong>, a Rust-powered, Prettier-compatible code formatter. This first release focuses on JavaScript and TypeScript, with support for additional languages coming soon.</p>
<p>Oxfmt is designed with these goals in mind:</p>
<ul>
<li><strong>Performance:</strong> More than 30× faster than Prettier and more than 3× faster than Biome on an initial run without a cache (<a href="https://github.com/oxc-project/bench-formatter" target="_blank" rel="noreferrer"><strong>benchmark</strong></a>).</li>
<li><strong>Compatibility:</strong> Prettier-compatible, so you can adopt Oxfmt in existing projects easily.</li>
<li><strong>Developer Experience:</strong> Upcoming features include import sorting, expanded formatting options, and support for Prettier plugins.</li>
</ul>
<h2 id="quick-start" tabindex="-1"><strong>Quick Start</strong> <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>Add <code>oxfmt</code> to your project:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt@latest</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt@latest</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt@latest</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bun</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt@latest</span></span></code></pre>
</div></td></tr><tr><td>deno</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">deno</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> npm:oxfmt@latest</span></span></code></pre>
</div></td></tr></tbody></table>
<p>Oxfmt follows Prettier’s configuration format. If you are using Prettier with a JSON configuration file, you can rename it to <code>.oxfmtrc.jsonc</code>:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .prettierrc.json</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .oxfmtrc.jsonc</span></span></code></pre>
</div><p>You can also start from this <code>.oxfmtrc.jsonc</code> configuration example:</p>
<div class="language-jsx"><button title="Copy Code" class="copy"></button><span class="lang">jsx</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  "$schema"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"./node_modules/oxfmt/configuration_schema.json"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // Use 80 if migrating from Prettier; 100 is the Oxfmt default!</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  "printWidth"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  "ignorePatterns"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Same as `.prettierignore`</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>Next, add <code>oxfmt</code> to your package.json scripts:</p>
<div class="language-jsx"><button title="Copy Code" class="copy"></button><span class="lang">jsx</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"scripts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  "format"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"oxfmt"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>Alternatively, refer to the <a href="/docs/guide/usage/formatter.html">installation guide</a> for detailed instructions.</p>
<h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<p>Oxfmt is incredibly fast. Our benchmark results on the <a href="https://github.com/outline/outline" target="_blank" rel="noreferrer">Outline</a> repository show:</p>
<ul>
<li>Over 30× faster than Prettier’s experimental CLI without cache</li>
<li>Over 20× faster than Prettier using Oxc’s parser through <code>@prettier/plugin-oxc</code></li>
<li>Over 3× faster than Biome, another Rust-based formatter</li>
</ul>
<p>For detailed benchmark setup, please refer to the following repository:</p>
<blockquote>
<p>oxc-project/bench-formatter<br>
<a href="https://github.com/oxc-project/bench-formatter" target="_blank" rel="noreferrer">https://github.com/oxc-project/bench-formatter</a></p>
</blockquote>
<h2 id="design" tabindex="-1">Design <a class="header-anchor" href="#design" aria-label="Permalink to “Design”">&#8203;</a></h2>
<p>The Oxc team prioritizes compatibility with existing ecosystems, making migrations straightforward, even for large codebases.</p>
<h3 id="code-formatting-results" tabindex="-1">Code formatting results <a class="header-anchor" href="#code-formatting-results" aria-label="Permalink to “Code formatting results”">&#8203;</a></h3>
<p>Oxfmt matches Prettier’s JavaScript formatting. If you are migrating to Oxfmt today, you shouldn’t see any formatting differences compared to Prettier.</p>
<p>You might see minor differences when migrating from older versions of Prettier (<a href="https://github.com/SBoudrias/Inquirer.js/pull/1912" target="_blank" rel="noreferrer">See an example migration</a>) because we identified areas in which Prettier’s formatting could be improved. We have been actively collaborating with the Prettier team by submitting bug reports and pull requests directly to Prettier. Many of these improvements landed in the recent <a href="https://prettier.io/blog/2025/11/27/3.7.0" target="_blank" rel="noreferrer">Prettier 3.7</a> release.</p>
<p>Oxfmt currently passes around <a href="https://github.com/oxc-project/oxc/tree/main/tasks/prettier_conformance/snapshots" target="_blank" rel="noreferrer">95%</a> of Prettier’s JavaScript and TypeScript tests, and we hope to work with the Prettier team to converge on formatting over time.</p>
<h3 id="printwidth-100-by-default" tabindex="-1"><code>printWidth: 100</code> by default <a class="header-anchor" href="#printwidth-100-by-default" aria-label="Permalink to “printWidth: 100 by default”">&#8203;</a></h3>
<p>We chose <code>printWidth: 100</code> as the default line length instead of Prettier's <code>80</code>. Our reasons include:</p>
<ul>
<li>TypeScript code tends to be longer than JavaScript due to type annotations.</li>
<li>Import statements often contain many items.</li>
<li>Larger screens provide more horizontal space.</li>
<li>Results in slightly fewer LLM tokens.</li>
</ul>
<p>While Oxfmt remains compatible with Prettier, it uses a different default print width of 100 characters. If you want to avoid large diffs when migrating from Prettier, explicitly set the print width to 80.</p>
<h3 id="ignorepatterns" tabindex="-1"><code>ignorePatterns</code> <a class="header-anchor" href="#ignorepatterns" aria-label="Permalink to “ignorePatterns”">&#8203;</a></h3>
<p>While Oxfmt supports <code>.prettierignore</code>, it also supports an <code>ignorePatterns</code> configuration option to consolidate all configuration into a single file.</p>
<h3 id="configuration" tabindex="-1">Configuration <a class="header-anchor" href="#configuration" aria-label="Permalink to “Configuration”">&#8203;</a></h3>
<p>Prettier JSON configuration files are compatible with Oxfmt. In the simplest case, migrating your config looks like this:</p>
<div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .prettierrc.json</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .oxfmtrc.jsonc</span></span></code></pre>
</div><p>If your editor supports the JSON language server, you can start with this minimal template after adding <code>oxfmt</code> to your <code>devDependencies</code>:</p>
<div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "$schema"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"./node_modules/oxfmt/configuration_schema.json"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "ignorePatterns"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: []</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>While we don’t yet support all of Prettier’s configuration options in this alpha release, we do support the following major options: <code>printWidth</code>, <code>tabWidth</code>, <code>useTabs</code>, <code>semi</code>, <code>singleQuote</code>, <code>quoteProps</code>, <code>jsxSingleQuote</code>, <code>trailingComma</code>, <code>bracketSpacing</code>, <code>objectWrap</code>, <code>bracketSameLine</code>, <code>arrowParens</code>, <code>endOfLine</code>, and <code>singleAttributePerLine</code>.</p>
<p>Check out all of the options in our <a href="https://oxc.rs/docs/guide/usage/formatter.html#configuration-file" target="_blank" rel="noreferrer">documentation</a>.</p>
<h3 id="terminal-output" tabindex="-1">Terminal Output <a class="header-anchor" href="#terminal-output" aria-label="Permalink to “Terminal Output”">&#8203;</a></h3>
<p>Oxfmt's default behavior is equivalent to <code>prettier . --write</code>, providing the same UX as <code>cargo fmt</code> and producing no output. You can use <code>--check</code> to display formatting differences and enforce oxfmt usage in CI pipelines.</p>
<h2 id="beta-release-plans" tabindex="-1">Beta Release Plans <a class="header-anchor" href="#beta-release-plans" aria-label="Permalink to “Beta Release Plans”">&#8203;</a></h2>
<p>Here are our plans for the beta release:</p>
<ul>
<li><a href="https://github.com/oxc-project/oxc/issues/15899" target="_blank" rel="noreferrer">Support more file formats</a> - like <code>.json</code> files</li>
<li><a href="https://github.com/oxc-project/oxc/issues/15180" target="_blank" rel="noreferrer">Add support for embedded language formatting</a> - css in js or graphql in js</li>
<li><a href="https://github.com/oxc-project/oxc/issues/13610" target="_blank" rel="noreferrer">Built-in sorting and aesthetics features</a>, such as <a href="https://github.com/oxc-project/oxc/issues/14253" target="_blank" rel="noreferrer">sort imports</a></li>
<li><a href="https://github.com/oxc-project/oxc/issues/15665" target="_blank" rel="noreferrer">Prettier plugins</a></li>
<li><a href="https://github.com/oxc-project/oxc/issues/15913" target="_blank" rel="noreferrer">Node.js API for Oxfmt</a></li>
<li><a href="https://github.com/oxc-project/oxc/issues/15066" target="_blank" rel="noreferrer">Disable newline at the end of file</a></li>
<li><a href="https://github.com/oxc-project/oxc/issues/15849" target="_blank" rel="noreferrer"><code>--migrate prettier</code></a></li>
<li><em>… and your feature requests</em></li>
</ul>
<p>You can track our progress towards the beta release here:</p>
<blockquote>
<p>Formatter Beta · Milestone #15 · oxc-project/oxc<br>
<a href="https://github.com/oxc-project/oxc/milestone/15" target="_blank" rel="noreferrer">https://github.com/oxc-project/oxc/milestone/15</a></p>
</blockquote>
<p>We also plan to relax some of the formatting opinions in future versions.</p>
<h2 id="next-steps" tabindex="-1">Next Steps <a class="header-anchor" href="#next-steps" aria-label="Permalink to “Next Steps”">&#8203;</a></h2>
<p>See the full installation guide in the <a href="https://oxc.rs/docs/guide/usage/formatter.html" target="_blank" rel="noreferrer">Oxfmt docs</a>.</p>
<h3 id="reporting-issues" tabindex="-1">Reporting Issues <a class="header-anchor" href="#reporting-issues" aria-label="Permalink to “Reporting Issues”">&#8203;</a></h3>
<p>For formatting differences, please refer to <a href="https://github.com/oxc-project/oxc/discussions/14669" target="_blank" rel="noreferrer">https://github.com/oxc-project/oxc/discussions/14669</a>.
Additionally, known issues are distinguished by <a href="https://github.com/oxc-project/oxc/issues?q=sort%3Aupdated-desc%20is%3Aissue%20label%3AA-formatter-prettier-diff" target="_blank" rel="noreferrer">labels</a>.</p>
<p>If you find any other issues, please create an issue with <a href="https://github.com/oxc-project/oxc/issues/new?template=formatter_diff_report.yaml" target="_blank" rel="noreferrer">dedicated template</a> on GitHub.</p>
<h3 id="join-the-community" tabindex="-1">Join the Community <a class="header-anchor" href="#join-the-community" aria-label="Permalink to “Join the Community”">&#8203;</a></h3>
<blockquote>
<p>RFC: Formatter · oxc-project/oxc · Discussion #13608<br>
<a href="https://github.com/oxc-project/oxc/discussions/13608" target="_blank" rel="noreferrer">https://github.com/oxc-project/oxc/discussions/13608</a></p>
</blockquote>
<p>We welcome your feedback to help make Oxfmt even better!</p>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>Oxfmt builds on a fork of the <a href="https://github.com/biomejs/biome/tree/main/crates/biome_formatter" target="_blank" rel="noreferrer"><code>biome_formatter</code></a> infrastructure, and we’d like to thank the Biome team, especially <a href="https://github.com/ematipico" target="_blank" rel="noreferrer">@ematipico</a> and <a href="https://github.com/MichaReiser" target="_blank" rel="noreferrer">@MichaReiser</a>. We’d also like to thank the Prettier team and <a href="https://github.com/fisker" target="_blank" rel="noreferrer">@fisker</a> for collaborating with us on formatting compatibility.</p>
]]></content:encoded>
            <author>Boshen</author>
            <author>Dunqing</author>
            <author>Yuji Sugiura</author>
        </item>
        <item>
            <title><![CDATA[Type-Aware Linting Alpha]]></title>
            <link>https://oxc.rs/blog/2025-12-08-type-aware-alpha</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2025-12-08-type-aware-alpha</guid>
            <pubDate>Mon, 08 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><br>
<p>We're excited to announce the alpha release of type-aware linting in Oxlint!</p>
<h2 id="overview" tabindex="-1">Overview <a class="header-anchor" href="#overview" aria-label="Permalink to “Overview”">&#8203;</a></h2>
<p>Following our <a href="/blog/2025-08-17-oxlint-type-aware.html">technical preview in August</a>, we're excited to announce that type-aware linting has reached alpha status. This milestone brings significant improvements in stability, configurability, and rule coverage.</p>
<p>Type-aware linting enables powerful rules like <code>no-floating-promises</code>, <code>no-misused-promises</code>, and <code>await-thenable</code> that catch bugs by utilizing TypeScript's type system. With 43 type-aware rules now available, you can catch entire categories of runtime errors before they happen.</p>
<p><strong>In this post:</strong></p>
<ul>
<li><a href="#quick-start">Quick Start</a> - Get started with type-aware linting in minutes</li>
<li><a href="#performance">Performance</a> - See how much faster type-aware linting is compared to ESLint</li>
<li><a href="#what-s-new-since-the-technical-preview">What's new since the technical preview</a> - New features and improvements</li>
<li><a href="#technical-details">Technical details</a> - How type-aware linting works under the hood</li>
<li><a href="#what-s-next">What's next</a> - Upcoming improvements for the beta release</li>
</ul>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>Install <code>oxlint</code> and <code>oxlint-tsgolint</code>, then run with the <code>--type-aware</code> flag:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bun</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr></tbody></table>
<p>To try a specific type-aware rule without other configuration (<code>oxlint-tsgolint</code> must be installed globally or locally already):</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr></tbody></table>
<p>For more configuration options, see our <a href="/docs/guide/usage/linter/type-aware.html">usage guide</a>.</p>
<h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<p>| Project         | Oxlint + Type Aware | ESLint + typescript-eslint | Improvement |
|</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><br>
<p>We're excited to announce the alpha release of type-aware linting in Oxlint!</p>
<h2 id="overview" tabindex="-1">Overview <a class="header-anchor" href="#overview" aria-label="Permalink to “Overview”">&#8203;</a></h2>
<p>Following our <a href="/blog/2025-08-17-oxlint-type-aware.html">technical preview in August</a>, we're excited to announce that type-aware linting has reached alpha status. This milestone brings significant improvements in stability, configurability, and rule coverage.</p>
<p>Type-aware linting enables powerful rules like <code>no-floating-promises</code>, <code>no-misused-promises</code>, and <code>await-thenable</code> that catch bugs by utilizing TypeScript's type system. With 43 type-aware rules now available, you can catch entire categories of runtime errors before they happen.</p>
<p><strong>In this post:</strong></p>
<ul>
<li><a href="#quick-start">Quick Start</a> - Get started with type-aware linting in minutes</li>
<li><a href="#performance">Performance</a> - See how much faster type-aware linting is compared to ESLint</li>
<li><a href="#what-s-new-since-the-technical-preview">What's new since the technical preview</a> - New features and improvements</li>
<li><a href="#technical-details">Technical details</a> - How type-aware linting works under the hood</li>
<li><a href="#what-s-next">What's next</a> - Upcoming improvements for the beta release</li>
</ul>
<h2 id="quick-start" tabindex="-1">Quick Start <a class="header-anchor" href="#quick-start" aria-label="Permalink to “Quick Start”">&#8203;</a></h2>
<p>Install <code>oxlint</code> and <code>oxlint-tsgolint</code>, then run with the <code>--type-aware</code> flag:</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bun</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint-tsgolint@latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span></span></code></pre>
</div></td></tr></tbody></table>
<p>To try a specific type-aware rule without other configuration (<code>oxlint-tsgolint</code> must be installed globally or locally already):</p>
<table><tbody><tr><td>npm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr><tr><td>pnpm</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr><tr><td>yarn</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr><tr><td>bun</td><td><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bunx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --type-aware</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -A</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> typescript/no-floating-promises</span></span></code></pre>
</div></td></tr></tbody></table>
<p>For more configuration options, see our <a href="/docs/guide/usage/linter/type-aware.html">usage guide</a>.</p>
<h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<table tabindex="0">
<thead>
<tr>
<th>Project</th>
<th>Oxlint + Type Aware</th>
<th>ESLint + typescript-eslint</th>
<th>Improvement</th>
</tr>
</thead>
<tbody>
<tr>
<td>vuejs/core</td>
<td>2.531 s</td>
<td>20.800 s</td>
<td>8.22x</td>
</tr>
<tr>
<td>outline/outline</td>
<td>4.448 s</td>
<td>55.070 s</td>
<td>12.38x</td>
</tr>
</tbody>
</table>
<p>Benchmarks were performed on a MacBook Pro M2 Max 12 Cores (8 performance and 4 efficiency).</p>
<p>Our performance testing shows that <code>oxlint</code> with type-aware linting is around 10 times faster than <code>eslint</code> with <code>typescript-eslint</code>. Take a look at our <a href="https://github.com/oxc-project/bench-linter" target="_blank" rel="noreferrer">performance benchmarks</a> for more details.</p>
<p>Oxlint can also be used to typecheck your codebase while linting. This avoids a duplicate work, as much of the type information is already computed during type-aware linting.</p>
<div  class="warning custom-block"><p class="custom-block-title">Known Issues</p>
<p>While <code>tsgolint</code> is ready for testing in production codebases, you may encounter issues with running out of memory when working with very large codebases. We are working on optimizing the memory usage for the next milestone. We would love if you tried <code>tsgolint</code> and reported any out-of-memory issues to us in the <a href="https://github.com/oxc-project/tsgolint" target="_blank" rel="noreferrer"><code>tsgolint</code> repository</a> and included some details about your project to help us improve memory usage.</p>
</div>
<h2 id="what-s-new-since-the-technical-preview" tabindex="-1">What's new since the technical preview? <a class="header-anchor" href="#what-s-new-since-the-technical-preview" aria-label="Permalink to “What's new since the technical preview?”">&#8203;</a></h2>
<h3 id="support-for-type-checking-while-linting" tabindex="-1">Support for type-checking while linting <a class="header-anchor" href="#support-for-type-checking-while-linting" aria-label="Permalink to “Support for type-checking while linting”">&#8203;</a></h3>
<p><code>tsgolint</code> now supports emitting type checking errors from TypeScript while linting. Since type-aware rules already require checking all of the types within a file, we are able to use this existing type information rather than discarding it. This means that in some cases, it is possible to skip doing a separate type-check command altogether (e.g., <code>tsc --noEmit</code>), reducing total time spent doing linting and type-checking in CI.</p>
<p>This is an experimental feature, but you can enable it by adding the <code>--type-check</code> and <code>--type-aware</code> flag to the <code>oxlint</code> command:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>$ oxlint --type-aware --type-check</span></span>
<span class="line"><span></span></span>
<span class="line"><span>  × typescript(TS2322): Type 'number' is not assignable to type 'string'.</span></span>
<span class="line"><span>   ╭─[index.ts:1:7]</span></span>
<span class="line"><span> 1 │ const message: string = 1</span></span>
<span class="line"><span>   ·       ───────</span></span>
<span class="line"><span>   ╰────</span></span></code></pre>
</div><h3 id="rule-configuration-support-in-oxlint" tabindex="-1">Rule configuration support in <code>oxlint</code> <a class="header-anchor" href="#rule-configuration-support-in-oxlint" aria-label="Permalink to “Rule configuration support in oxlint”">&#8203;</a></h3>
<p>Type-aware rules that run in <code>tsgolint</code> can be configured in <code>oxlint</code> just like any other lint rule. For example, you can configure the <code>no-floating-promises</code> rule to allow certain safe calls or ignore <code>void</code>:</p>
<div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "typescript/no-floating-promises"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      "error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "ignoreVoid"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "allowForKnownSafePromises"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"from"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"file"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"SafePromise"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"from"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"lib"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"PromiseLike"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>The configuration options are aligned with what <code>typescript-eslint</code> supports and documentation can be found in the configuration section for each rule (like <a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html#configuration" target="_blank" rel="noreferrer"><code>no-floating-promises</code></a>).</p>
<h3 id="inline-disable-comment-support-in-oxlint" tabindex="-1">Inline disable comment support in <code>oxlint</code> <a class="header-anchor" href="#inline-disable-comment-support-in-oxlint" aria-label="Permalink to “Inline disable comment support in oxlint”">&#8203;</a></h3>
<p>Rules that run in <code>tsgolint</code> can now be disabled similar to any other <code>oxlint</code> rule by placing a comment in the file or on a line:</p>
<div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* oxlint-disable typescript/no-floating-promises */</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// oxlint-disable-next-line typescript/no-floating-promises</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">x</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
</div><h3 id="more-supported-rules" tabindex="-1">More supported rules <a class="header-anchor" href="#more-supported-rules" aria-label="Permalink to “More supported rules”">&#8203;</a></h3>
<p>We've continued to make progress on porting popular rules from <code>typescript-eslint</code> which you can now use via <code>oxlint</code>. <code>tsgolint</code>, combined with <code>oxlint</code>, currently supports 43 type-aware rules.</p>
<p>Since the initial preview, support for the following rules has also been added:</p>
<ul>
<li><a href="/docs/guide/usage/linter/rules/typescript/no-deprecated.html"><code>no-deprecated</code></a> (one of the most commonly requested rules)</li>
<li><a href="/docs/guide/usage/linter/rules/typescript/prefer-includes.html"><code>prefer-includes</code></a></li>
<li><a href="/docs/guide/usage/linter/rules/typescript/strict-boolean-expressions.html"><code>strict-boolean-expressions</code></a></li>
</ul>
<h3 id="typescript-program-diagnostics-are-now-reported" tabindex="-1">TypeScript program diagnostics are now reported <a class="header-anchor" href="#typescript-program-diagnostics-are-now-reported" aria-label="Permalink to “TypeScript program diagnostics are now reported”">&#8203;</a></h3>
<p>Previously, if TypeScript failed to create and parse a program, these errors were not reported which led to confusion around why linting was not working. Now, we report any issues with creating a program as a diagnostic, including configuration issues in <code>tsconfig.json</code> files.</p>
<p>For example, if a <code>tsconfig.json</code> file contains <code>baseUrl</code>, that will be reported as an error, since <code>baseUrl</code> has been removed from TypeScript in v7.0:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>$ oxlint --type-aware</span></span>
<span class="line"><span></span></span>
<span class="line"><span>  × typescript(tsconfig-error): Invalid tsconfig</span></span>
<span class="line"><span>   ╭─[tsconfig.json:4:3]</span></span>
<span class="line"><span> 3 │     "compilerOptions": {</span></span>
<span class="line"><span> 4 │         "baseUrl": ".",</span></span>
<span class="line"><span>   ·         ─────────</span></span>
<span class="line"><span> 5 │         "experimentalDecorators": true,</span></span>
<span class="line"><span>   ╰────</span></span>
<span class="line"><span>  help: Option 'baseUrl' has been removed. Please remove it from your configuration.</span></span>
<span class="line"><span>        See https://github.com/oxc-project/tsgolint/issues/351 for more information.</span></span></code></pre>
</div><h3 id="automatic-fixes-for-type-aware-rules" tabindex="-1">Automatic fixes for type-aware rules <a class="header-anchor" href="#automatic-fixes-for-type-aware-rules" aria-label="Permalink to “Automatic fixes for type-aware rules”">&#8203;</a></h3>
<p>Type-aware rules now support automatic fixes via the <code>--fix</code> flag. When you run <code>oxlint --type-aware --fix</code>, fixable diagnostics from <code>tsgolint</code> are applied just like regular <code>oxlint</code> fixes. This brings full parity with non-type-aware rules for the fix workflow.</p>
<h2 id="technical-details" tabindex="-1">Technical details <a class="header-anchor" href="#technical-details" aria-label="Permalink to “Technical details”">&#8203;</a></h2>
<h3 id="architecture" tabindex="-1">Architecture <a class="header-anchor" href="#architecture" aria-label="Permalink to “Architecture”">&#8203;</a></h3>
<p>Type-aware linting in Oxlint uses a unique two-binary architecture:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>oxlint CLI (Rust)</span></span>
<span class="line"><span>  ├─ Handles file traversal, ignore logic, and diagnostics</span></span>
<span class="line"><span>  ├─ Runs non-type-aware rules and custom JS plugins</span></span>
<span class="line"><span>  ├─ Passes paths and configuration to tsgolint</span></span>
<span class="line"><span>  └─ Formats and displays results</span></span>
<span class="line"><span></span></span>
<span class="line"><span>tsgolint (Go)</span></span>
<span class="line"><span>  ├─ Uses typescript-go directly for type checking</span></span>
<span class="line"><span>  ├─ Executes type-aware rules</span></span>
<span class="line"><span>  └─ Returns structured diagnostics</span></span></code></pre>
</div><p>This design keeps Oxlint's core fast while leveraging TypeScript's type system through typescript-go. The frontend-backend separation means <code>oxlint</code> controls the user experience while <code>tsgolint</code> handles the heavy lifting of type analysis.</p>
<h3 id="typescript-compatibility" tabindex="-1">TypeScript compatibility <a class="header-anchor" href="#typescript-compatibility" aria-label="Permalink to “TypeScript compatibility”">&#8203;</a></h3>
<p><code>tsgolint</code> is based on <a href="https://github.com/microsoft/typescript-go" target="_blank" rel="noreferrer">typescript-go</a>, Microsoft's Go-based rewrite that will become TypeScript v7.0. For more details on TypeScript 7's progress, see the <a href="https://devblogs.microsoft.com/typescript/progress-on-typescript-7-december-2025/" target="_blank" rel="noreferrer">official TypeScript blog post</a>. This means that you might encounter some features which are no longer supported.</p>
<p><strong>Important compatibility notes:</strong></p>
<ul>
<li>Only TypeScript 7.0+ features are supported</li>
<li>Pre-7.0 syntax and deprecated features are not supported</li>
<li>Legacy <code>tsconfig.json</code> options like <code>baseUrl</code> have been removed in TypeScript 7.0</li>
</ul>
<p>If you're using deprecated features from TypeScript 6.0 or earlier, you'll need to migrate your codebase first. See the <a href="https://github.com/microsoft/TypeScript/issues/62508#issuecomment-3348649259" target="_blank" rel="noreferrer">TypeScript migration guide</a> for help updating deprecated tsconfig options.</p>
<h3 id="implementation-details" tabindex="-1">Implementation details <a class="header-anchor" href="#implementation-details" aria-label="Permalink to “Implementation details”">&#8203;</a></h3>
<p><code>tsgolint</code> doesn't use typescript-go's public APIs. Instead, it compiles typescript-go by <a href="https://github.com/oxc-project/tsgolint/tree/main/shim" target="_blank" rel="noreferrer">shimming</a> internal APIs to make them accessible. We actively track typescript-go updates and fix breaking changes as needed.</p>
<p>Our typescript-go fork is synced regularly using renovatebot, ensuring we stay current with the latest improvements and fixes. Once TypeScript 7.0 is officially released, we will track stable releases rather than the tip of the main branch.</p>
<h2 id="what-s-next" tabindex="-1">What's next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to “What's next”">&#8203;</a></h2>
<p>We're actively working on the following improvements for the beta release:</p>
<ul>
<li><strong>More supported rules</strong> - Currently we support 43 out of the 59 type-aware rules from <code>typescript-eslint</code>. As we head towards a beta release, we plan to continue expanding rule coverage.</li>
<li><strong>Performance and memory usage improvements</strong> - We're going to continue to optimize performance, especially for very large monorepos.</li>
</ul>
<h2 id="acknowledgements" tabindex="-1">Acknowledgements <a class="header-anchor" href="#acknowledgements" aria-label="Permalink to “Acknowledgements”">&#8203;</a></h2>
<p>We'd like to extend our gratitude to:</p>
<ul>
<li>The TypeScript team for creating <code>typescript-go</code>.</li>
<li>The <code>typescript-eslint</code> team for their heartwarming support.</li>
<li><a href="https://github.com/auvred" target="_blank" rel="noreferrer">@auvred</a> for creating <code>tsgolint</code>.</li>
<li><a href="https://github.com/camchenry" target="_blank" rel="noreferrer">@camchenry</a> for continued performance work, as well as implementing rule option support.</li>
</ul>
<h2 id="try-it-out" tabindex="-1">Try it out <a class="header-anchor" href="#try-it-out" aria-label="Permalink to “Try it out”">&#8203;</a></h2>
<p>Ready to get started? Head to the <a href="#quick-start">Quick Start</a> section above to install and run type-aware linting.</p>
<p>We'd love to hear your feedback on type-aware linting and are excited to see how it helps improve your development workflow.</p>
<p>Connect with us:</p>
<ul>
<li><strong>Discord</strong>: Join our <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">community server</a> for real-time discussions</li>
<li><strong>GitHub</strong>: Share feedback on <a href="https://github.com/oxc-project/oxc/discussions" target="_blank" rel="noreferrer">GitHub Discussions</a></li>
<li><strong>Issues</strong>: Report <code>oxlint</code> bugs to <a href="https://github.com/oxc-project/oxc/issues" target="_blank" rel="noreferrer">oxc</a> and type-aware linting bugs to <a href="https://github.com/oxc-project/tsgolint/issues" target="_blank" rel="noreferrer">tsgolint</a>.</li>
</ul>
]]></content:encoded>
            <author>Cameron</author>
            <author>Cam</author>
        </item>
        <item>
            <title><![CDATA[Oxfmt Beta]]></title>
            <link>https://oxc.rs/blog/2026-02-24-oxfmt-beta</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2026-02-24-oxfmt-beta</guid>
            <pubDate>Tue, 24 Feb 2026 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<AppBlogPostHeader /><p>We are excited to announce that Oxfmt has reached beta.</p>
<p>Oxfmt is a Rust-powered, Prettier-compatible code formatter built for the JavaScript ecosystem. It is designed to deliver full compatibility with modern tooling while dramatically improving performance.</p>
<p>In benchmarks, Oxfmt is more than 30× faster than Prettier and 3× faster than Biome on an initial run without caching. See the full <a href="https://github.com/oxc-project/bench-formatter" target="_blank" rel="noreferrer">benchmark</a> results.</p>
<p>Since the December alpha release, we have expanded support for additional file formats, added embedded language formatting, introduced import sorting, integrated Tailwind CSS support, and delivered numerous stability and compatibility improvements.</p>
<p>Oxfmt has already seen broad adoption across the ecosystem. Projects using Oxfmt include: <a href="https://github.com/openclaw/openclaw" target="_blank" rel="noreferrer">openclaw/openclaw</a>, <a href="https://github.com/vuejs/core" target="_blank" rel="noreferrer">vuejs/core</a>, <a href="https://github.com/vercel/turborepo" target="_blank" rel="noreferrer">vercel/turborepo</a>, <a href="https://github.com/huggingface/huggingface.js" target="_blank" rel="noreferrer">huggingface/huggingface.js</a>, <a href="https://github.com/getsentry/sentry-javascript" target="_blank" rel="noreferrer">getsentry/sentry-javascript</a>, <a href="https://github.com/npmx-dev/npmx.dev" target="_blank" rel="noreferrer">npmx-dev/npmx.dev</a> and many more.</p>
<h2 id="getting-started" tabindex="-1">Getting Started <a class="header-anchor" href="#getting-started" aria-label="Permalink to “Getting Started”">&#8203;</a></h2>
<p>Install <code>oxfmt</code> as a dev dependency:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt</span></span></code></pre>
</div><p>Add scripts to <code>package.json</code>:</p>
<tr><td>package.json</td><td><div class="vp-code-block-title">
      <div class="vp-code-block-title-bar">
          <span class="vp-code-block-title-text" data-title="package.json">package.json</span>
      </div>
        <div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "scripts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "fmt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"oxfmt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "fmt:check"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"oxfmt --check"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div>
      </div>
      </td></tr><p>Format files:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> fmt</span></span></code></pre>
</div><p>Check formatting without writing files:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> fmt:check</span></span></code></pre>
</div><h3 id="migrating-from-prettier" tabindex="-1">Migrating from Prettier <a class="header-anchor" href="#migrating-from-prettier" aria-label="Permalink to “Migrating from Prettier”">&#8203;</a></h3>
<p>Install, migrate your config, and reformat in a single command:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --migrate</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> prettier</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxfmt</span></span></code></pre>
</div><p>For the full migration guide, see <a href="/docs/guide/usage/formatter/migrate-from-prettier.html">Migrate from Prettier</a>.</p>
<h3 id="ai-migration-prompt" tabindex="-1">AI Migration Prompt <a class="header-anchor" href="#ai-migration-prompt" aria-label="Permalink to “AI Migration Prompt”">&#8203;</a></h3>
<p>Alternatively, you can copy this prompt to your AI coding assistant to migrate your project:</p>
<div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span>Migrate this project from Prettier to Oxfmt following https://oxc.rs/docs/guide/usage/formatter.html:</span></span>
<span class="line"><span>1. Install oxfmt and run `oxfmt --migrate prettier`</span></span>
<span class="line"><span>2. Update package.json scripts to use oxfmt</span></span>
<span class="line"><span>3. Update CI workflows to use `oxfmt --check`</span></span>
<span class="line"><span>4. Update lint-staged to use `oxfmt --no-error-on-unmatched-pattern`</span></span>
<span class="line"><span>5. Run oxfmt to reformat all files</span></span>
<span class="line"><span>6. Uninstall prettier and related packages</span></span>
<span class="line"><span>7. Update editor settings for oxfmt</span></span>
<span class="line"><span>8. Update CONTRIBUTING.md, AGENTS.md, or CLAUDE.md if they mention prettier</span></span></code></pre>
</div><p>For more detailed instructions, check out the <a href="https://oxc.rs/docs/guide/usage/formatter.html" target="_blank" rel="noreferrer">Oxfmt docs</a>.</p>
<h2 id="highlights-of-new-features-since-alpha" tabindex="-1">Highlights of New Features Since Alpha <a class="header-anchor" href="#highlights-of-new-features-since-alpha" aria-label="Permalink to “Highlights of New Features Since Alpha”">&#8203;</a></h2>
<h3 id="_100-prettier-compatibility" tabindex="-1">100% Prettier Compatibility <a class="header-anchor" href="#_100-prettier-compatibility" aria-label="Permalink to “100% Prettier Compatibility”">&#8203;</a></h3>
<p>Oxfmt now passes 100% of Prettier's JavaScript and TypeScript conformance tests. For the few remaining formatting inconsistencies, we have <a href="https://github.com/oxc-project/oxc/issues/18717" target="_blank" rel="noreferrer">reported them to the Prettier team</a> and are collaborating to converge on the expected behavior.</p>
<p>This means you can migrate from Prettier to Oxfmt with confidence that your code will be formatted identically. If you encounter any uncovered cases, please <a href="https://github.com/oxc-project/oxc/issues/new?template=formatter_diff_report.yaml" target="_blank" rel="noreferrer">report them</a>.</p>
<h3 id="additional-file-formats" tabindex="-1">Additional File Formats <a class="header-anchor" href="#additional-file-formats" aria-label="Permalink to “Additional File Formats”">&#8203;</a></h3>
<p>Oxfmt now formats JavaScript, JSX, TypeScript, TSX, JSON, JSONC, JSON5, YAML, TOML, HTML, Angular, Vue, CSS, SCSS, Less, Markdown, MDX, GraphQL, Ember, and Handlebars. This means you can use a single formatter for your entire project.</p>
<h3 id="tailwind-css-integration" tabindex="-1">Tailwind CSS Integration <a class="header-anchor" href="#tailwind-css-integration" aria-label="Permalink to “Tailwind CSS Integration”">&#8203;</a></h3>
<p>Automatic <a href="/docs/guide/usage/formatter/sorting.html#sort-tailwind-css-classes">Tailwind CSS class sorting</a> is supported for both JS/TS and non-JS/TS files. The functionality of <code>prettier-plugin-tailwindcss</code> is built-in, so the plugin is no longer required.</p>
<h3 id="import-sorting" tabindex="-1">Import Sorting <a class="header-anchor" href="#import-sorting" aria-label="Permalink to “Import Sorting”">&#8203;</a></h3>
<p>Built-in <a href="/docs/guide/usage/formatter/sorting.html#sort-imports">import sorting</a> is now available with configurable options:</p>
<ul>
<li><code>ignoreCase</code> - Case-insensitive sorting</li>
<li><code>sortSideEffects</code> - Sort side-effect imports</li>
<li><code>newlinesBetween</code> - Control blank lines between import groups</li>
<li><code>groups</code> - Custom sort order groups</li>
<li><code>customGroups</code> - Define custom grouping rules</li>
</ul>
<p>For more options, please see the <a href="/docs/guide/usage/formatter/config-file-reference.html#sortimports">full reference</a>.</p>
<h3 id="package-json-sorting" tabindex="-1"><code>package.json</code> Sorting <a class="header-anchor" href="#package-json-sorting" aria-label="Permalink to “package.json Sorting”">&#8203;</a></h3>
<p>Automatic <a href="/docs/guide/usage/formatter/sorting.html#sort-package-json-fields">package.json field sorting</a> is enabled by default, keeping your package.json files consistently organized.</p>
<h3 id="embedded-language-formatting" tabindex="-1">Embedded Language Formatting <a class="header-anchor" href="#embedded-language-formatting" aria-label="Permalink to “Embedded Language Formatting”">&#8203;</a></h3>
<p>Format code <a href="/docs/guide/usage/formatter/embedded-formatting.html">embedded in template literals</a>:</p>
<ul>
<li>CSS-in-JS with styled-components-like syntaxes, <code>styled-jsx</code> and CSS prop support</li>
<li>Angular <code>@Component</code> template and styles</li>
</ul>
<h3 id="node-js-api" tabindex="-1">Node.js API <a class="header-anchor" href="#node-js-api" aria-label="Permalink to “Node.js API”">&#8203;</a></h3>
<p>A programmatic API is now available:</p>
<div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { format, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FormatOptions } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "oxfmt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> input</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `let a=42;`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FormatOptions</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  semi: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">code</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> format</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a.js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, input, options);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(code); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// "let a = 42"</span></span></code></pre>
</div><h3 id="cli-changes" tabindex="-1"><a href="/docs/guide/usage/formatter/cli.html">CLI Changes</a> <a class="header-anchor" href="#cli-changes" aria-label="Permalink to “CLI Changes”">&#8203;</a></h3>
<ul>
<li><code>--init</code> - Bootstrap a new configuration file</li>
<li><code>--migrate prettier</code> - Migrate from Prettier configuration</li>
<li><code>--migrate biome</code> - Migrate from Biome configuration</li>
<li><code>--stdin-filepath</code> - Specify filepath for stdin input</li>
<li>Glob pattern expansion support - <code>oxfmt './packages/**/*.{js,jsx}'</code></li>
</ul>
<h3 id="config-changes" tabindex="-1"><a href="/docs/guide/usage/formatter/config.html">Config Changes</a> <a class="header-anchor" href="#config-changes" aria-label="Permalink to “Config Changes”">&#8203;</a></h3>
<ul>
<li><a href="/docs/guide/usage/formatter/config.html#overrides"><code>overrides</code></a> - Apply different options to specific file patterns</li>
<li><a href="/docs/guide/usage/formatter/config.html#insertfinalnewline"><code>insertFinalNewline</code></a> - Control trailing newlines</li>
<li><a href="/docs/guide/usage/formatter/config.html#editorconfig"><code>.editorconfig</code></a> support for <code>insert_final_newline</code></li>
</ul>
<h3 id="editor-support" tabindex="-1"><a href="/docs/guide/usage/formatter/editors.html">Editor Support</a> <a class="header-anchor" href="#editor-support" aria-label="Permalink to “Editor Support”">&#8203;</a></h3>
<p>Oxfmt works in all supported editors: VS Code, Cursor, Zed, IntelliJ IDEA, WebStorm, Neovim, and any editor with LSP support.</p>
<h2 id="roadmap" tabindex="-1">Roadmap <a class="header-anchor" href="#roadmap" aria-label="Permalink to “Roadmap”">&#8203;</a></h2>
<p>We are continuing to improve Oxfmt towards a stable release:</p>
<ul>
<li>Prettier plugins support</li>
<li>Improve xxx-in-js formatting</li>
<li>Stability</li>
<li>Performance optimizations</li>
</ul>
<h2 id="next-steps" tabindex="-1">Next Steps <a class="header-anchor" href="#next-steps" aria-label="Permalink to “Next Steps”">&#8203;</a></h2>
<p>See the full installation guide in the <a href="/docs/guide/usage/formatter.html">Oxfmt docs</a>.</p>
<h3 id="reporting-issues" tabindex="-1">Reporting Issues <a class="header-anchor" href="#reporting-issues" aria-label="Permalink to “Reporting Issues”">&#8203;</a></h3>
<p>For formatting differences, please refer to the <a href="https://github.com/oxc-project/oxc/discussions/14669" target="_blank" rel="noreferrer">formatting differences discussion</a>.</p>
<h3 id="join-the-community" tabindex="-1">Join the Community <a class="header-anchor" href="#join-the-community" aria-label="Permalink to “Join the Community”">&#8203;</a></h3>
<p>We'd love to hear your feedback on Oxfmt. Connect with us:</p>
<ul>
<li>Discord: Join our <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">community server</a> for real-time discussions</li>
<li>GitHub: Share feedback on the <a href="https://github.com/oxc-project/oxc/discussions/13608" target="_blank" rel="noreferrer">Formatter RFC</a></li>
<li>Issues: Report bugs or request features on our <a href="https://github.com/oxc-project/oxc/issues" target="_blank" rel="noreferrer">issue tracker</a></li>
</ul>
]]></content:encoded>
            <author>Boshen</author>
            <author>Dunqing</author>
            <author>Yuji Sugiura</author>
        </item>
        <item>
            <title><![CDATA[Oxlint JS Plugins Alpha]]></title>
            <link>https://oxc.rs/blog/2026-03-11-oxlint-js-plugins-alpha</link>
            <guid isPermaLink="false">https://oxc.rs/blog/2026-03-11-oxlint-js-plugins-alpha</guid>
            <pubDate>Wed, 11 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[<AppBlogPostHeader /><br>
<p><strong>JavaScript plugins for Oxlint have reached alpha - and we expect 80% of ESLint users can now switch to Oxlint and have it &quot;just work&quot;.</strong></p>
<p>Oxlint already has over 650 popular lint rules implemented in Rust, running at native speed. JS plugins fill in the gaps - an ESLint-compatible plugin API, letting you run existing ESLint plugins and write your own custom rules, all within Oxlint. Native performance for most rules, full flexibility for the rest.</p>
<p>Since the <a href="./2025-10-09-oxlint-js-plugins.html">first technical preview</a> last year, we've filled out almost the entire ESLint plugin API, added TypeScript plugin support, auto-fixes, IDE integration, and <a href="#performance">major performance gains</a>.</p>
<p>This means many teams can replace ESLint with Oxlint, without rewriting their lint rules.</p>
<p>This alpha release marks the point where we feel JS plugins are ready for adoption in real world projects.</p>
<p>Most projects should find that Oxlint can now act as a drop-in replacement for ESLint, with straightforward migration, and large reduction in linting time.</p>
<h3 id="features" tabindex="-1">Features <a class="header-anchor" href="#features" aria-label="Permalink to “Features”">&#8203;</a></h3>
<ul>
<li>Run most existing ESLint plugins without modification.</li>
<li>Write your own custom lint rules in JavaScript or TypeScript.</li>
<li>Get auto-fixes and suggestions from JS plugin rules.</li>
<li>See JS plugin diagnostics live in your IDE via the language server.</li>
</ul>
<h3 id="how-reliable-is-it" tabindex="-1">How reliable is it? <a class="header-anchor" href="#how-reliable-is-it" aria-label="Permalink to “How reliable is it?”">&#8203;</a></h3>
<p>Oxlint JS plugins support is tested against the full test suite of ESLint itself, and also against a wide selection of ESLint plugins, including:</p>
<p>| Plugin                                                                                                  |  Tests | Pass rate |
|</p>
]]></description>
            <content:encoded><![CDATA[<AppBlogPostHeader /><br>
<p><strong>JavaScript plugins for Oxlint have reached alpha - and we expect 80% of ESLint users can now switch to Oxlint and have it &quot;just work&quot;.</strong></p>
<p>Oxlint already has over 650 popular lint rules implemented in Rust, running at native speed. JS plugins fill in the gaps - an ESLint-compatible plugin API, letting you run existing ESLint plugins and write your own custom rules, all within Oxlint. Native performance for most rules, full flexibility for the rest.</p>
<p>Since the <a href="./2025-10-09-oxlint-js-plugins.html">first technical preview</a> last year, we've filled out almost the entire ESLint plugin API, added TypeScript plugin support, auto-fixes, IDE integration, and <a href="#performance">major performance gains</a>.</p>
<p>This means many teams can replace ESLint with Oxlint, without rewriting their lint rules.</p>
<p>This alpha release marks the point where we feel JS plugins are ready for adoption in real world projects.</p>
<p>Most projects should find that Oxlint can now act as a drop-in replacement for ESLint, with straightforward migration, and large reduction in linting time.</p>
<h3 id="features" tabindex="-1">Features <a class="header-anchor" href="#features" aria-label="Permalink to “Features”">&#8203;</a></h3>
<ul>
<li>Run most existing ESLint plugins without modification.</li>
<li>Write your own custom lint rules in JavaScript or TypeScript.</li>
<li>Get auto-fixes and suggestions from JS plugin rules.</li>
<li>See JS plugin diagnostics live in your IDE via the language server.</li>
</ul>
<h3 id="how-reliable-is-it" tabindex="-1">How reliable is it? <a class="header-anchor" href="#how-reliable-is-it" aria-label="Permalink to “How reliable is it?”">&#8203;</a></h3>
<p>Oxlint JS plugins support is tested against the full test suite of ESLint itself, and also against a wide selection of ESLint plugins, including:</p>
<table tabindex="0">
<thead>
<tr>
<th>Plugin</th>
<th style="text-align:right">Tests</th>
<th style="text-align:right">Pass rate</th>
</tr>
</thead>
<tbody>
<tr>
<td>ESLint built-in rules</td>
<td style="text-align:right">33,006</td>
<td style="text-align:right">100%</td>
</tr>
<tr>
<td><a href="https://www.npmjs.com/package/eslint-plugin-react-hooks" target="_blank" rel="noreferrer">React hooks</a> (including React Compiler rules)</td>
<td style="text-align:right">5,007</td>
<td style="text-align:right">100%</td>
</tr>
<tr>
<td><a href="https://eslint.style/" target="_blank" rel="noreferrer">ESLint Stylistic</a></td>
<td style="text-align:right">18,310</td>
<td style="text-align:right">99.99%</td>
</tr>
<tr>
<td><a href="https://www.npmjs.com/package/eslint-plugin-testing-library" target="_blank" rel="noreferrer">Testing Library</a></td>
<td style="text-align:right">17,016</td>
<td style="text-align:right">100%</td>
</tr>
<tr>
<td><a href="https://www.npmjs.com/package/eslint-plugin-sonarjs" target="_blank" rel="noreferrer">SonarJS</a></td>
<td style="text-align:right">3,951</td>
<td style="text-align:right">99.6%*</td>
</tr>
<tr>
<td><a href="https://www.npmjs.com/package/@e18e/eslint-plugin" target="_blank" rel="noreferrer">e18e</a></td>
<td style="text-align:right">474</td>
<td style="text-align:right">100%*</td>
</tr>
</tbody>
</table>
<p><small>* excluding type-aware rules</small></p>
<p>If a plugin isn't in the list above, it will very likely still work - it just isn't included in <a href="https://github.com/oxc-project/oxc/tree/13606c3ab16cc273a6fad7e2de964ffa0ad0a241/apps/oxlint/conformance" target="_blank" rel="noreferrer">our conformance test suite</a> yet.</p>
<p>ESLint's own tests cover the entire API surface, so a 100% pass rate gives us confidence that we've covered corner cases, as well as the happy path. Please try it out and let us know!</p>
<p>Oxlint is already used in production by many companies and projects, including <a href="https://x.com/_chenglou/status/2026408795857981610" target="_blank" rel="noreferrer">Midjourney</a>, <a href="https://github.com/preactjs/preact" target="_blank" rel="noreferrer">Preact</a>, <a href="https://github.com/PostHog/posthog" target="_blank" rel="noreferrer">Posthog</a>, <a href="https://github.com/outline/outline" target="_blank" rel="noreferrer">Outline</a>, and <a href="https://github.com/actualbudget/actual" target="_blank" rel="noreferrer">Actual</a>.</p>
<h3 id="what-it-can-t-do-yet" tabindex="-1">What it can't do (yet) <a class="header-anchor" href="#what-it-can-t-do-yet" aria-label="Permalink to “What it can't do (yet)”">&#8203;</a></h3>
<ul>
<li>Limited support for front-end frameworks' custom file formats (e.g. Svelte, Vue, Angular) - coming later this year.</li>
<li>No custom type-aware rules (TypeScript-ESLint's rules are already built into Oxlint via <a href="./../docs/guide/usage/linter/type-aware.html">type-aware linting</a>).</li>
<li>Some users have found the experience on Windows sub-par. Out of memory errors are <a href="https://github.com/oxc-project/oxc/issues/19395" target="_blank" rel="noreferrer">a known issue</a>, specifically on Windows. We're working on it. In the meantime, if you hit this problem, we recommend running Oxlint in WSL, if that's an option.</li>
</ul>
<p>You can follow our progress towards filling these gaps on the <a href="https://github.com/oxc-project/oxc/issues/19918" target="_blank" rel="noreferrer">tracking issue</a>.</p>
<h2 id="getting-started" tabindex="-1">Getting Started <a class="header-anchor" href="#getting-started" aria-label="Permalink to “Getting Started”">&#8203;</a></h2>
<p>Install <code>oxlint</code> as a dev dependency:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> oxlint</span></span></code></pre>
</div><p>Add a script to <code>package.json</code>:</p>
<tr><td>package.json</td><td><div class="vp-code-block-title">
      <div class="vp-code-block-title-bar">
          <span class="vp-code-block-title-text" data-title="package.json">package.json</span>
      </div>
        <div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "scripts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "lint"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"oxlint"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div>
      </div>
      </td></tr><p>Create a config file (or use <a href="#migrating-from-eslint">our migration tool</a>):</p>
<tr><td>.oxlintrc.json</td><td><div class="vp-code-block-title">
      <div class="vp-code-block-title-bar">
          <span class="vp-code-block-title-text" data-title=".oxlintrc.json">.oxlintrc.json</span>
      </div>
        <div class="language-json"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "jsPlugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"eslint-plugin-testing-library"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "testing-library/no-render-in-lifecycle"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div>
      </div>
      </td></tr><p>Lint your project:</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> lint</span></span></code></pre>
</div><h3 id="migrating-from-eslint" tabindex="-1">Migrating from ESLint <a class="header-anchor" href="#migrating-from-eslint" aria-label="Permalink to “Migrating from ESLint”">&#8203;</a></h3>
<p>Most projects should find that migrating from ESLint is straightforward.</p>
<p>The simplest route is via the <code>@oxlint/migrate</code> tool.</p>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> @oxlint/migrate</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> eslint.config.js</span></span></code></pre>
</div><p>Or ask your coding agent to do it for you with the <a href="https://skills.sh/oxc-project/oxc/migrate-oxlint" target="_blank" rel="noreferrer"><code>migrate-oxlint</code> skill</a>.</p>
<p>See the <a href="./../docs/guide/usage/linter/migrate-from-eslint.html">migration guide</a> for more details.</p>
<h2 id="eslint-rules" tabindex="-1">ESLint rules <a class="header-anchor" href="#eslint-rules" aria-label="Permalink to “ESLint rules”">&#8203;</a></h2>
<p>Oxlint already natively implements most of ESLint's built-in rules, rewritten in Rust, but not all rules are implemented yet.</p>
<p>To bridge this gap, we provide <a href="https://www.npmjs.com/package/oxlint-plugin-eslint" target="_blank" rel="noreferrer">oxlint-plugin-eslint</a>, which contains all ESLint's built-in rules packaged as an Oxlint JS plugin.</p>
<p>This unlocks rules like <code>no-restricted-syntax</code> which are not yet implemented natively in Oxlint.</p>
<tr><td>.oxlintrc.json</td><td><div class="vp-code-block-title">
      <div class="vp-code-block-title-bar">
          <span class="vp-code-block-title-text" data-title=".oxlintrc.json">.oxlintrc.json</span>
      </div>
        <div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "jsPlugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"oxlint-plugin-eslint"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Note: "eslint-js" not "eslint"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "eslint-js/no-restricted-syntax"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      "error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "selector"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ThrowStatement > CallExpression[callee.name=/Error$/]"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Use `new` keyword when throwing an `Error`."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div>
      </div>
      </td></tr><p>Oxlint also implements a subset of rules from plugins like <a href="https://www.npmjs.com/package/eslint-plugin-jsdoc" target="_blank" rel="noreferrer">eslint-plugin-jsdoc</a> natively. For rules which aren't implemented in Oxlint itself, you can use the <code>eslint-plugin-jsdoc</code> package directly. This is the recommended pattern:</p>
<tr><td>.oxlintrc.json</td><td><div class="vp-code-block-title">
      <div class="vp-code-block-title-bar">
          <span class="vp-code-block-title-text" data-title=".oxlintrc.json">.oxlintrc.json</span>
      </div>
        <div class="language-jsonc"><button title="Copy Code" class="copy"></button><span class="lang">jsonc</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "jsPlugins"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Set up an alias for the plugin "jsdoc-js"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"jsdoc-js"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"specifier"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"eslint-plugin-jsdoc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  ],</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "rules"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Use the alias to refer to rules from the plugin</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "jsdoc-js/check-examples"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "jsdoc-js/require-description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Use plain "jsdoc" for rules which Oxlint implements natively</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "jsdoc/require-property-name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "jsdoc/require-property-description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div>
      </div>
      </td></tr><h2 id="performance" tabindex="-1">Performance <a class="header-anchor" href="#performance" aria-label="Permalink to “Performance”">&#8203;</a></h2>
<p>Since the first technical preview, we have &quot;Rustified&quot; large chunks of the code powering JS plugins, which has delivered significant performance gains. In particular, plugins which rely on tokens APIs (e.g. ESLint Stylistic) are up to 5 times faster than before.</p>
<p>As a benchmark, we migrated Node.js's repo from ESLint to Oxlint. Node.js is a large project utilizing many custom lint rules, as well as several heavy ESLint plugins (98 JS lint rules in total).</p>
<table tabindex="0">
<thead>
<tr>
<th>Linter</th>
<th>Time</th>
<th>Speed-up</th>
</tr>
</thead>
<tbody>
<tr>
<td>ESLint</td>
<td>1 minute, 43 seconds</td>
<td></td>
</tr>
<tr>
<td>Oxlint</td>
<td>21 seconds</td>
<td>4.8x</td>
</tr>
</tbody>
</table>
<div>
<details>
<summary>Details</summary>
<div  class="info custom-block"><p class="custom-block-title custom-block-title-default">INFO</p>
<ul>
<li>
<p><a href="https://github.com/overlookmotel/node" target="_blank" rel="noreferrer">Benchmark repo</a></p>
</li>
<li>
<p>6298 files linted</p>
</li>
<li>
<p>104 built-in Oxlint rules (Rust)</p>
</li>
<li>
<p>75 rules from JS plugins (JS)</p>
</li>
<li>
<p>23 custom rules (JS)</p>
</li>
<li>
<p>Benchmarked on Mac Mini M4, 48GB RAM, Node.js 24.14.0</p>
</li>
<li>
<p>ESLint benchmark:</p>
</li>
</ul>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> checkout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> bench-eslint</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ci</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">hyperfine</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -i</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --warmup</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --runs</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "node --run eslint"</span></span></code></pre>
</div><ul>
<li>Oxlint benchmark:</li>
</ul>
<div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" dir="ltr" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> checkout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> bench-oxlint</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ci</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">hyperfine</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -i</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --warmup</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --runs</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "node --run oxlint"</span></span></code></pre>
</div></div>
</details>
</div>
<p>Projects which currently use TypeScript-ESLint or <code>eslint-plugin-import</code> will likely see <strong>much larger</strong> performance gains. <a href="https://discord.com/channels/1079625926024900739/1080712072012238858/threads/1478161352097796206" target="_blank" rel="noreferrer">One user in our Discord</a> reported a 16x speed-up linting their company's 2 million line codebase when switching from ESLint to Oxlint, with heavy usage of JS plugins. Projects which use JS plugins more sparingly have reported speed gains of up to 100x.</p>
<h3 id="future-perf-improvements" tabindex="-1">Future perf improvements <a class="header-anchor" href="#future-perf-improvements" aria-label="Permalink to “Future perf improvements”">&#8203;</a></h3>
<p>This is just the beginning!</p>
<p>While Oxlint with JS plugins is already significantly faster than ESLint, we have many more optimizations in the pipeline.</p>
<p>The key to Oxlint's JS plugin performance is a new, highly optimized, low-level mechanism for communicating between Rust and JS, which we call &quot;raw transfer&quot;.</p>
<p>The Rust/JS boundary has always been the fundamental problem for native tooling supporting JS plugins. Native code is fast, but the cost of sending data back and forth between Rust and JS can be so high that it offsets that gain, resulting in mediocre performance overall.</p>
<p>Raw transfer reduces the cost of moving data between Rust and JS almost to zero, finally enabling native code and JS plugins to work effectively in tandem.</p>
<p>The first iteration of raw transfer is already at work under the hood of Oxlint, but we've only just begun leveraging what it can do. As we continue this work, we expect to see a further step-change in performance, bringing JS plugins close to native Rust performance.</p>
<p>If you're interested in the details, Oxc core team member <a href="https://github.com/overlookmotel" target="_blank" rel="noreferrer">@overlookmotel</a> gave <a href="https://www.youtube.com/watch?v=ofQV3xiBgT8" target="_blank" rel="noreferrer">a talk at ViteConf 2025</a> on this subject.</p>
<p>In short: Oxlint is already the fastest JS/TS linter in existence. It's going to get a lot faster.</p>
<h3 id="perf-tip-1-use-a-formatter" tabindex="-1">Perf tip 1: Use a formatter <a class="header-anchor" href="#perf-tip-1-use-a-formatter" aria-label="Permalink to “Perf tip 1: Use a formatter”">&#8203;</a></h3>
<p>We strongly recommend moving from using the linter for code formatting, to using <a href="./../docs/guide/usage/formatter.html">Oxfmt</a> (or your preferred formatter), if you can.</p>
<p>Oxfmt is 30x faster than Prettier, and will also dramatically reduce linting time vs linter plugins like ESLint Stylistic.</p>
<p>Oxlint and Oxfmt make a very strong team!</p>
<h3 id="perf-tip-2-choose-plugins-wisely" tabindex="-1">Perf tip 2: Choose plugins wisely <a class="header-anchor" href="#perf-tip-2-choose-plugins-wisely" aria-label="Permalink to “Perf tip 2: Choose plugins wisely”">&#8203;</a></h3>
<p>Contrary to what many believe, it is perfectly possible to write extremely performant JavaScript code. Oxlint is not fast just because it's written in Rust - it's also carefully designed with performance in mind.</p>
<p>The code of JS plugins themselves is not under Oxlint's control. To get good performance out of Oxlint overall requires the JS plugins you select to perform well too.</p>
<p>If a plugin uses inefficient algorithms or performs a lot of filesystem operations, it'll be slow in ESLint, and slow in Oxlint too. What Oxlint <em>can</em> do is provide a lightning-fast parser and performant APIs for plugins to interface with, but it can't magically make slow JS code faster.</p>
<p>We will in future provide a utility to diagnose which plugins/rules are the performance bottlenecks in your project, if you find that linting is not as fast as you'd like.</p>
<h2 id="creating-custom-plugins" tabindex="-1">Creating custom plugins <a class="header-anchor" href="#creating-custom-plugins" aria-label="Permalink to “Creating custom plugins”">&#8203;</a></h2>
<p>If your project has specific needs, it's simple to create a custom JS plugin for Oxlint.</p>
<p>Please see the <a href="./../docs/guide/usage/linter/js-plugins.html">JS plugin guide</a>.</p>
<h1 id="faq" tabindex="-1">FAQ <a class="header-anchor" href="#faq" aria-label="Permalink to “FAQ”">&#8203;</a></h1>
<p><strong>Can Oxlint run ESLint plugins?</strong>
Yes. Most plugins work without modification.</p>
<p><strong>Is Oxlint faster than ESLint?</strong>
Yes. Benchmarks typically show 4x–100x speedups.</p>
<p><strong>Can I migrate gradually?</strong>
Yes. You can run Oxlint alongside ESLint.</p>
<h2 id="thanks-to" tabindex="-1">Thanks to <a class="header-anchor" href="#thanks-to" aria-label="Permalink to “Thanks to”">&#8203;</a></h2>
<p>Bringing JS plugins up to this milestone has been the work of many hands. In particular, we'd like to thank:</p>
<ul>
<li><a href="https://github.com/Sysix" target="_blank" rel="noreferrer">@Sysix</a> for tireless work on the language server integration.</li>
<li><a href="https://github.com/lilnasy" target="_blank" rel="noreferrer">@lilnasy</a> for building out many of the APIs.</li>
</ul>
<h2 id="join-the-community" tabindex="-1">Join the community <a class="header-anchor" href="#join-the-community" aria-label="Permalink to “Join the community”">&#8203;</a></h2>
<p>We'd love to hear your feedback on Oxlint JS plugins, and are excited to see how it helps improve your development workflow.</p>
<p>Connect with us:</p>
<ul>
<li><strong>Discord</strong>: Join our <a href="https://discord.gg/9uXCAwqQZW" target="_blank" rel="noreferrer">community server</a> for real-time discussions</li>
<li><strong>GitHub</strong>: Share feedback on <a href="https://github.com/oxc-project/oxc/discussions" target="_blank" rel="noreferrer">GitHub Discussions</a></li>
<li><strong>Issues</strong>: Report <code>oxlint</code> bugs to <a href="https://github.com/oxc-project/oxc/issues" target="_blank" rel="noreferrer">oxc</a>.</li>
</ul>
]]></content:encoded>
            <author>overlookmotel</author>
            <author>Cameron</author>
        </item>
    </channel>
</rss>