Open-source project
antfu/eslint-config avatar
antfu/eslint-config

antfu/eslint-config: a personal ESLint flat config you can install with one line

Anthony's ESLint config preset

6,271 stars575 forksJavaScriptMIT

At a glance

What is it?
@antfu/eslint-config is Anthony Fu's opinionated ESLint flat config preset, delivered as the npm package @antfu/eslint-config. It replaces Prettier for formatting, covers TypeScript, Vue, JSX, JSON, YAML, TOML and Markdown out of the box, and its own README calls it a personal config, which is the main thing to weigh before adopting it.
Who is it for?
Adopt it if you want one line of config and accept the author's style choices, including single quotes, no semicolons, sorted imports and dangling commas, and if you will review the diff after every version bump. Do not adopt it if you need a slow-moving rule set, a committee-owned standard, or a config that will not change under you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 28 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem @antfu/eslint-config removes: a config file you have to maintain

Most ESLint setups grow into a maintenance project of their own. You install eslint, then eslint-plugin-import, then a TypeScript parser, then typescript-eslint, then a Vue or React plugin, then Prettier, then eslint-config-prettier to switch off the rules Prettier already handles. Each of those has its own peer dependency range and its own breaking changes. The README of @antfu/eslint-config frames the alternative in one line: "Reasonable defaults, best practices, only one line of config." That is the whole pitch. The preset bundles the parser, the plugins and the stylistic rules, and you write a single call.

The intended audience is a developer who wants formatting and linting decided already. The README is explicit that formatting is handled by ESLint itself, aimed to be used standalone without Prettier, and built on ESLint Stylistic. If your team already has a style guide that differs from single quotes, no semicolons and dangling commas, this preset is not a neutral starting point. It is someone else's answer to a question you have already answered differently.

How the flat config composes: one function call, many internal configs

The mechanism is ESLint's flat config system. Instead of .eslintrc.json with extends chains, flat config exports an array of config objects from a file such as eslint.config.mjs. @antfu/eslint-config exports a function that returns a populated array. Calling antfu() with no arguments gives you the default set; the optional features (React, Next.js, Svelte, UnoCSS, Astro, Solid, and formatters for CSS, HTML, XML and similar) are switched on through the options object passed to that same call.

Because the return value is an ordinary flat config array, you can spread it and append your own objects, or pass extra configs as additional arguments after the options object. The README's legacy example shows exactly that shape: antfu({ ignores: [] }, ...compat.config({ extends: ['eslint:recommended'] })). The preset also reads .gitignore by default, which the README lists as a feature, so ignored files do not need a separate ignore list. One consequence worth noting: the README states that .eslintignore no longer works in flat config, so any project migrating from eslintrc loses that file as a mechanism and has to express ignores inside the config object.

Installing @antfu/eslint-config and running the first lint

There are two paths. The starter wizard is a CLI that sets up a project or migrates a legacy eslintrc config to flat config, and the README gives it as a single command run through pnpm's dlx:

bash
pnpm dlx @antfu/eslint-config@latest

If you prefer to wire it yourself, install ESLint and the preset as dev dependencies. The README uses pnpm, and the repository's package.json declares pnpm as the package manager:

bash
pnpm i -D eslint @antfu/eslint-config

Then create eslint.config.mjs in the project root. The README's minimal example is three lines, and the default export is the result of calling antfu with no arguments:

js
// eslint.config.mjs
import antfu from '@antfu/eslint-config'

export default antfu()

Add lint scripts to package.json. The README suggests lint for a check and lint:fix for autofix, and the preset is designed so that formatting fixes come from the same command rather than a separate formatter:

json
{
  "scripts": {
    "lint": "eslint",
    "lint:fix": "eslint --fix"
  }
}

Running pnpm lint should report violations and pnpm lint:fix should rewrite formatting, including import order, quotes and semicolons. To see what the preset actually enables, the repository's own dev script runs the config inspector against its eslint.config.ts, which is the same tool you can point at your own config.

Editor setup is where the preset stops being invisible

The README spends a lot of space on IDE integration, and that is a signal about where the friction lives. For VS Code it instructs you to disable Prettier, turn off format on save, and run ESLint fixes on save instead. It also supplies a list of rule customizations that silence stylistic rules in the editor while still applying their fixes, covering patterns like style/*, format/*, *-indent, *-spacing, *quotes and *-semi. Zed gets an equivalent block, and Neovim a Lua snippet.

The reason for the customizations is practical: if every quote and comma shows up as a squiggle, the editor becomes noise and developers stop reading diagnostics. Suppressing a rule's severity while keeping it fixable means the file is corrected on save without the problem being announced. That is a reasonable trade, but it does mean the editor no longer tells you when formatting drifts. The check moves entirely to CI. If your CI does not run eslint, the preset's formatting guarantees are only as good as each developer's save-on-format setting.

The limitation the README states itself: this is a personal config

The warning block in the README is unusually direct. It says the author is appreciative that many people use the config, then says: "please keep in mind that this is still a personal config with a lot of opinions." It follows with concrete advice: if you use it directly, review the changes every time you update, or fork it if you want more control over the rules.

That is the honest description of the trade. You are adopting one person's rule choices, and those choices can change between minor versions. A rule that was an error in v9.4.1 may be off in v9.5.0, and the release cadence visible in the repository is fast: three releases on the same day, 2026-09-02, moving from v9.4.1 through v9.5.0 to v9.5.1. Fast releases are not a defect in themselves, but they make the README's instruction to review every update load-bearing rather than polite. Teams that pin the version and update quarterly will feel less of this than teams that float on latest.

The second constraint is the peer dependency range. The README states the preset requires ESLint v9.5.0 or newer, and package.json lists eslint under peerDependencies as ^9.10.0 || ^10.0.0. The optional integrations have their own floors: @next/eslint-plugin-next is >=15.0.0, astro-eslint-parser is >=1.0.2, @unocss/eslint-plugin is >=0.50.0. If your project is stuck on an older ESLint, this preset is simply unavailable until you upgrade, and the flat config migration is a prerequisite rather than a side effect.

What you give up compared with Airbnb, Standard or a hand-built config

The alternative most teams compare against is eslint-config-airbnb and its TypeScript variant, or eslint-config-standard. The difference in approach is not the rule count, it is the governance model. Airbnb's config is maintained as a shared standard with a published style guide, and it has historically shipped in the eslintrc format with extends chains. Standard is a fixed, deliberately narrow rule set that changes rarely. Both aim to be the same config for everyone and to move slowly.

@antfu/eslint-config does the opposite. It is flat config only, it bundles the formatter instead of delegating to Prettier, and it is maintained by one person who says so in the README. The upside is that you get TypeScript, Vue, JSX, JSON, YAML, TOML and Markdown coverage without assembling plugins, and the style rules that Prettier would normally own are part of the same lint pass. The downside is that the update policy is yours to enforce, not the maintainer's. A team that wants the rule set to be a stable contract across years will find Airbnb or a hand-written config easier to defend in review, at the cost of assembling and maintaining the plugin graph themselves.

Licence, maintenance and the cost of staying current

The package is MIT licensed, and package.json declares "license": "MIT" with funding pointed at the author's GitHub sponsors page. MIT means you can use, modify and redistribute it, including in closed-source projects, provided the copyright notice and permission notice travel with it. That is a permissive licence with no copyleft obligation, but it is not legal advice and does not cover the licences of the bundled plugins, which have their own terms. If your organisation audits dependency licences, the transitive set is what to check, not just this package.

On maintenance, the repository is not archived and the last push was on 2026-09-02, with v9.5.1 released the same day. The upgrade cost is the part to plan for. Because the preset is opinionated and releases frequently, a version bump can change formatting across the codebase, which shows up as a large diff that reviewers cannot meaningfully read. The README's own recommendation, review the changes every time you update, is the cheapest mitigation: read the release notes and run eslint --fix on a branch before merging the bump, so the formatting churn is isolated from functional changes.

Editorial conclusion

Adopt it if you want one line of config and accept the author's style choices, including single quotes, no semicolons, sorted imports and dangling commas, and if you will review the diff after every version bump. Do not adopt it if you need a slow-moving rule set, a committee-owned standard, or a config that will not change under you. Before committing, check that your ESLint version satisfies the peer dependency range, and run the config inspector to see which rules the preset actually turns on.

Frequently asked questions

How do I install @antfu/eslint-config?

Either run the starter wizard with pnpm dlx @antfu/eslint-config@latest, or install it manually with pnpm i -D eslint @antfu/eslint-config and create an eslint.config.mjs file that exports antfu(). The preset requires ESLint v9.5.0 or newer.

What is eslint.config.mjs in an @antfu/eslint-config setup?

It is the flat config file ESLint reads from the project root. With this preset it imports antfu from @antfu/eslint-config and exports the result of calling antfu(), which returns an array of flat config objects.

Can I use Prettier together with @antfu/eslint-config?

The README describes the preset as aimed to be used standalone without Prettier, and its VS Code instructions tell you to set prettier.enable to false. Formatting is handled by ESLint through ESLint Stylistic instead.

How do I add rules to an @antfu/eslint-config setup?

The function returns a flat config array, so you can pass extra config objects as additional arguments after the options object, or spread the result and append your own entries. The README shows this pattern when combining the preset with a legacy config converted through FlatCompat.

What is the eslint.config.js file in an ESLint project?

It is the configuration file ESLint reads, and in flat config it exports an array of config objects. With @antfu/eslint-config that array comes from calling antfu(), and the README's examples use the .mjs extension for it.

Official sources

  1. antfu/eslint-config on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/antfu-eslint-config.svg)](https://hysenlabs.com/projects/antfu-eslint-config)