Linter
Bun's fast, built-in linter for JavaScript, TypeScript, and JSX
Bun ships with a fast, built-in linter. There's nothing to install and nothing to configure.
- 1,000+ rules from ESLint, typescript-eslint, React, import, unicorn, jsx-a11y, Jest, Vitest, and more
- Type-aware rules, without the
typescriptpackage - Auto-fix with
--fix - Works with your existing ESLint or oxlint config
Run the linter#
bun lint1 | export function total(prices: number[]) {
2 | let sum = 0;
3 | for (let i = 0; i < prices.length; i--) {
^
error: The update clause in this loop moves the variable in the wrong direction. for-direction
at src/cart.ts:3:3
5 | }
6 |
7 | let tax = 0.2;
^
warn: 'tax' is never reassigned. Use 'const' instead. prefer-const
at src/cart.ts:7:7
2 problems (1 error, 1 warning)
1 can be fixed with --fix
Linted 1 file [5.17ms]bun lint checks every .js, .jsx, .ts, and .tsx file in the current directory (plus the .mjs, .cjs, .mts, .cts variants). It skips node_modules and anything in your .gitignore.
To lint specific files, pass paths or globs.
bun lint src "test/**/*.test.ts"The exit code is 1 if there are errors and 0 if there are only warnings.
Fix problems#
Many rules can fix what they report. --fix applies those fixes and writes the files.
bun lint --fixDefault rules#
With no config, bun lint turns on the rules that catch real bugs:
- Every file: ESLint's recommended rules
- TypeScript: typescript-eslint's recommended rules
- React:
rules-of-hooks,exhaustive-deps, andjsx-key, ifreactis in yourpackage.json - Tests: leftover
test.only,expect()without a matcher, un-awaited.resolves, and a few more, in files that import frombun:test
Likely bugs are errors. Unused code, style suggestions, and code that people often write on purpose, like while (match = re.exec(text)), are warnings. A warning doesn't fail the run.
A few defaults differ from ESLint's, so that ordinary code isn't reported:
require()is allowed in TypeScript files. Bun runsimportandrequire()in the same file.- A name that starts with
_may be unused. done && done();andok ? resolve() : reject();are fine as statements.- A no-break space or a full-width space is only reported in code, not in text, comments or JSX.
process.exit()ends acase, and// fall-throughor// no breakmarks one that goes on.{false && <Debug />}is a fine way to switch something off for a while.- An array of JSX elements needs keys only where React renders it as a list.
import Reactcounts as used in a file with JSX.
Each rule's page says what differs and how to change it.
- In
.d.tsfiles only the errors run. - An
eslint-disablecomment for a rule that is off is left alone.
Configure rules#
Rules live in bunfig.toml. Every built-in rule works the same way. There are no plugins to install.
[lint.rules]
"no-console" = "warn"
"prefer-const" = "off"
"eqeqeq" = ["error", "smart"] # with options
"unicorn/prefer-node-protocol" = "error"
"@typescript-eslint/no-explicit-any" = "off"An option you don't set keeps its default.
To create the section, run bun lint --init.
A typo is an error, not a silent no-op:
2 | "no-consle" = "warn"
^
error: Unknown rule "no-consle"
Did you mean "no-console"?
at bunfig.toml:2:1Find a rule#
Browse all rules, or look one up from the terminal. In most terminals you can also click the rule name in a report.
bun lint --rules # list every rule
bun lint --explain prefer-const # what it does, examples, optionsTurn on a group of rules#
Categories switch on many rules at once: correctness, suspicious, pedantic, perf, style, restriction, nursery.
[lint.categories]
suspicious = "warn"
perf = "warn"Ignore files#
[lint]
ignorePatterns = ["vendor/", "**/*.gen.ts"]Disable a rule in code#
bun lint uses ESLint's comments, so existing ones keep working.
// eslint-disable-next-line no-console -- the CLI prints its version
console.log(version);
/* eslint-disable no-console */
console.log("off until the end of the file");A comment that no longer disables anything gets a warning, and --fix removes it.
Type-aware rules#
Some bugs only show up with types, like a promise nobody awaits. --type-aware turns on the recommended rules that use them.
bun lint --type-aware5 | export function onClick() {
6 | save("hello");
^
error: Promises must be awaited, end with a call to .catch, ... @typescript-eslint/no-floating-promises
at src/save.ts:6:3Types come from bun check, Bun's built-in type checker. It's slower than a plain run, because your code is type checked first. To make it the default:
[lint]
typeAware = trueOnly want one of them? Turn it on like any other rule. You don't need typeAware.
[lint.rules]
"@typescript-eslint/no-floating-promises" = "error"To report type errors too, like bun check does, set typeCheck = true or pass --type-check.
Git hooks#
--staged lints only the files you're about to commit, so you don't need lint-staged.
#!/bin/sh
bun lint --staged --fix--changed lints the files that differ from your default branch. Pass a ref to compare with something else.
bun lint --changed
bun lint --changed=origin/devCI#
In GitHub Actions, bun lint annotates the pull request diff automatically.
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun lint --max-warnings 0 # fail on warnings tooFor other systems, pick a report format with --format: json, junit, checkstyle, gitlab, sarif, unix.
Migrate from ESLint or oxlint#
Already have an eslint.config.js, .eslintrc, or .oxlintrc.json? bun lint reads it and reports what that tool reports. Change the script and you're done.
{
"scripts": {
"lint": "eslint ."
"lint": "bun lint"
}
}If package.json has a lint script, bun lint runs that script. Inside the script, bun lint is the linter.
Rules from built-in plugins run natively. Any other ESLint plugin still runs, in JavaScript. To see which is which, and which packages you can uninstall:
bun lint --doctorSee the guides: Migrate from ESLint and Migrate from oxlint. For custom rules, see ESLint plugins.
CLI Usage#
bun lint [flags] [files, directories, or globs]Rules#
Set a rule for this run: --rule 'eqeqeq: [error, smart]'
Also run the rules that need type information
List every built-in rule. Add -f json for machine-readable output
Print the documentation for a rule
Add a [lint] section to bunfig.toml
Fixing#
Apply fixes and write the files
Also apply suggestions, which may change what the code does
Compute fixes without writing them. The json format includes the fixed code
Files#
Lint only the files staged in Git
Lint only the files that differ from a Git ref. Defaults to the default branch
Skip files that match this glob. Can be repeated
Lint ignored files too
Output#
pretty, stylish, json, unix, github,
junit, checkstyle, gitlab, sarif, or agent
Write the report to a file
Report errors only
Exit with code 1 if there are more warnings than this
Show every problem. By default, more than 50 identical problems are grouped
Tools#
Show which rules of your ESLint or oxlint config run natively, and which packages you can remove
Print the resolved config for a file
bun lint also accepts the flags of ESLint and oxlint. Run bun lint --help --all to see them.