Biome 05 🧹 The check Command — Running all tools in one pass
The check command is the single invocation that runs the formatter, the linter, and the import organizer together. It is the command that the Biome quick start recommends for the everyday workflow, and it is the command that the pre-commit hook and the CI job use because it covers the three concerns in one parse pass . The alternative—running format and lint as separate commands—parses the same files twice, and the double parse is the cost that the check command exists to remove. The Biome skill reference states the rule plainly: “Use biome check instead of running biome format and biome lint separately — single pass is faster” .
The command is not a synonym for the CI check. The check command accepts the --write flag, which means it can modify the files. The ci command is the read-only variant that Biome provides for the pipelines, and the skill reference is explicit that the CI job should use ci rather than check because “check allows --write which is dangerous in pipelines” . The distinction is the same as the one between the local fix and the remote gate: the local developer wants the fixes applied, and the CI wants to know whether the fixes are needed without applying them.
Key point: biome check runs the formatter, the linter, and the import organizer in a single pass. Without --write, it is a read-only audit that reports the diagnostics and exits non-zero if any error is found. With --write, it applies the safe fixes from all three tools. The ci command is the read-only variant for the pipelines.
Why the check command is the default
The single-parse problem. The formatter and the linter both need the same abstract syntax tree. Running biome format and then biome lint parses each file twice, and the second parse produces the same tree as the first. The check command parses once and runs both tools against the same tree, which is the architectural decision that makes it faster than the two separate commands . The speed difference is not marginal for a large repository; it is the difference between a hook that the developer tolerates and a hook that the developer disables.
The three-tool problem. The check command does not just run the formatter and the linter. It also runs the import organizer, which is the assist action that sorts the imports and removes the unused ones. The import organization is the third concern, and it is the one that the ESLint and Prettier setup handled with a separate plugin and a separate configuration. The check command runs all three, and the single command is the replacement for the three separate tools .
The fix-application problem. The --write flag applies the safe fixes from the three tools. The formatter’s fix is the formatting, the linter’s safe fix is the correction that does not change the behavior, and the import organizer’s fix is the sorted imports. The --unsafe flag extends the fixes to the linter’s unsafe fixes, which are the corrections that may change the behavior and require the manual review . The flag combination is the mechanism that lets the developer choose the level of automation.
The trade-off. The check command is the combined audit, but it is not the targeted tool. A developer who is debugging a formatting issue may want to run only the formatter, and the format command is the targeted alternative. The check command is the default because the combined audit is the common case, and the targeted commands are the exception for the debugging sessions. The default is the combination, and the combination is the reason the toolchain is one command.
a. The read-only check and the write check
The check command without the --write flag is the read-only audit. It reports the diagnostics and exits with a non-zero code if any error is found. The read-only mode is the one that the developer runs before the commit, and the one that the CI runs when the ci command is not available.
# The read-only check
npx @biomejs/biome check ./src
The command parses the files, runs the formatter, the linter, and the import organizer, and reports the diagnostics. The files are not modified. The exit code is 1 if any error-level diagnostic is found, and 0 if the files are clean .
The check command with the --write flag applies the safe fixes. The formatter’s formatting, the linter’s safe fixes, and the import organizer’s sorting are all applied in the single pass.
# The check with the safe fixes
npx @biomejs/biome check --write ./src
The --write flag is the mechanism that turns the audit into a fix. The files are modified in place, and the diagnostics that remain are the ones that the safe fixes could not address. The remaining diagnostics are the ones that the developer must fix manually or the ones that the linter reports as unsafe .
The --unsafe flag extends the fixes to the linter’s unsafe fixes. The unsafe fixes may change the behavior, so they require the manual review. The flag requires --write, because an unsafe fix without the write is a contradiction.
# The check with the safe and unsafe fixes
npx @biomejs/biome check --write --unsafe ./src
The --write --unsafe combination is the most aggressive fix mode. The formatter, the linter’s safe fixes, the linter’s unsafe fixes, and the import organizer all run, and the files are modified. The developer reviews the diff before the commit, because the unsafe fixes are the ones that can change the semantics .
b. The file filters and the inline overrides
The check command accepts the same file filters as the format and lint commands. The --staged flag filters the files to the Git-staged ones, and the --changed flag filters to the files changed since the default branch. The --since flag is the explicit branch comparison.
# The check on the Git-staged files (the pre-commit hook)
npx @biomejs/biome check --staged --write
# The check on the changed files (the CI mechanism)
npx @biomejs/biome check --changed
The --staged flag is the pre-commit hook mechanism. The hook runs the check on the files that are about to be committed, and the --write flag applies the fixes to the staged content. The --changed flag is the CI mechanism, and it is the one that the pipeline uses to check only the files that differ from the default branch .
The check command also accepts the inline tool overrides. The --formatter-enabled=false, --linter-enabled=false, and --organize-imports-enabled=false flags override the biome.json settings for the single invocation. The overrides are the mechanism that lets the check command behave like the format or the lint command without the separate invocation.
# The check with the linter disabled
npx @biomejs/biome check --write ./src --linter-enabled=false
# The check with the formatter disabled
npx @biomejs/biome check --write ./src --formatter-enabled=false
The --linter-enabled=false makes the check command run only the formatter and the import organizer. The --formatter-enabled=false makes it run only the linter and the import organizer. The overrides are the mechanism that makes the check command the only command the project needs, with the tool selection done by the flag rather than the verb .
The --diagnostic-level and the --max-diagnostics flags control the output. The --diagnostic-level=error filters the output to the errors, and the --max-diagnostics=20 caps the number of the printed diagnostics. The filters are the mechanism that makes the migration readable, where the project has hundreds of diagnostics and the CI job needs to see the first twenty .
Complete Example Session
# ============================================
# PART 1: THE READ-ONLY CHECK
# ============================================
# The read-only check.
npx @biomejs/biome check ./src
# The command runs the formatter, the linter, and the import organizer.
# The files are not modified.
# The exit code is 1 if any error-level diagnostic is found.
# ============================================
# PART 2: THE CHECK WITH THE SAFE FIXES
# ============================================
# The check with the safe fixes.
npx @biomejs/biome check --write ./src
# The command applies the formatter, the safe lint fixes, and the import sorting.
# The files are modified in place.
# ============================================
# PART 3: THE CHECK WITH THE UNSAFE FIXES
# ============================================
# The check with the unsafe fixes.
npx @biomejs/biome check --write --unsafe ./src
# The command applies the safe and unsafe fixes.
# The unsafe fixes may change the behavior.
# The developer reviews the diff before the commit.
# ============================================
# PART 4: THE STAGED FILES
# ============================================
# The check on the Git-staged files.
npx @biomejs/biome check --staged --write
# The command checks only the staged files.
# The pre-commit hook uses this.
# ============================================
# PART 5: THE CHANGED FILES
# ============================================
# The check on the changed files.
npx @biomejs/biome check --changed
# The command checks the files that differ from the default branch.
# The CI uses this.
# ============================================
# PART 6: THE INLINE TOOL OVERRIDES
# ============================================
# The check with the linter disabled.
npx @biomejs/biome check --write ./src --linter-enabled=false
# The command runs only the formatter and the import organizer.
# ============================================
# PART 7: THE DIAGNOSTIC FILTERS
# ============================================
# The check with the error-level diagnostics only.
npx @biomejs/biome check ./src --diagnostic-level=error
# The check with the maximum diagnostic count.
npx @biomejs/biome check ./src --max-diagnostics=20
# ============================================
# PART 8: THE CI COMMAND
# ============================================
# The read-only CI check.
npx @biomejs/biome ci ./src
# The ci command is the read-only variant.
# It does not accept --write.
# The CI pipeline uses this.
# ============================================
# PART 9: THE STDIN CHECK
# ============================================
# The stdin check.
echo 'let a;' | npx @biomejs/biome check --stdin-file-path=file.js
# The command checks the code from stdin.
# The filename tells Biome which parser to use.
# ============================================
# PART 10: THE CHECKLIST
# ============================================
# [ ] The check command runs the formatter, the linter, and the import organizer.
# [ ] The --write flag applies the safe fixes.
# [ ] The --unsafe flag applies the unsafe fixes and requires --write.
# [ ] The --staged flag filters to the Git-staged files.
# [ ] The --changed flag filters to the changed files.
# [ ] The --linter-enabled and --formatter-enabled flags override the tools.
# [ ] The --diagnostic-level flag filters the output.
# [ ] The ci command is used in the CI, not the check command.
The ten parts covered the read-only check, the safe fixes, the unsafe fixes, the staged files, the changed files, the inline overrides, the diagnostic filters, the CI command, the stdin check, and the checklist. The through-line is that the check command is the single pass that runs the three tools, and the flags are the mechanism that controls the scope and the fix level.
Quick Reference
The check command modes
| Mode | Command | Files modified |
|---|---|---|
| Read-only | biome check ./src | No |
| Safe fixes | biome check --write ./src | Yes |
| Unsafe fixes | biome check --write --unsafe ./src | Yes |
The file filters
| Flag | Purpose |
|---|---|
--staged | The Git-staged files (pre-commit) |
--changed | The files changed since the default branch (CI) |
--since=<ref> | The files changed since a specific ref |
The inline tool overrides
| Flag | Effect |
|---|---|
--formatter-enabled=false | Disable the formatter |
--linter-enabled=false | Disable the linter |
--organize-imports-enabled=false | Disable the import organizer |
The output filters
| Flag | Effect |
|---|---|
--diagnostic-level=error | Show only the errors |
--max-diagnostics=20 | Cap the printed diagnostics |
--error-on-warnings | Treat the warnings as errors |
Best Practices
✅ Do This:
# Use check for the full audit
npx @biomejs/biome check --write ./src # ✅
# Use --staged for the pre-commit hook
npx @biomejs/biome check --staged --write # ✅
# Use the ci command in the pipeline
npx @biomejs/biome ci ./src # ✅
❌ Don’t Do This:
# Use check with --write in the CI
npx @biomejs/biome check --write ./src # the CI modifies the repo // ❌
# Run format and lint separately for the full audit
npx @biomejs/biome format ./src && npx @biomejs/biome lint ./src // ❌ (the double parse)
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The check does not modify the files | The --write flag is missing | Add --write |
| The unsafe fix is not applied | The --unsafe flag is missing | Add --unsafe with --write |
| The CI modifies the repository | The check --write is used instead of ci | Use biome ci |
| The pre-commit hook is slow | The --staged flag is missing | Add --staged |
| The migration is unreadable | The --max-diagnostics is not set | Add --max-diagnostics=20 |
Real-World Examples
1. The read-only check
npx @biomejs/biome check ./src
2. The check with the safe fixes
npx @biomejs/biome check --write ./src
3. The check with the unsafe fixes
npx @biomejs/biome check --write --unsafe ./src
4. The staged files
npx @biomejs/biome check --staged --write
5. The changed files
npx @biomejs/biome check --changed
6. The linter disabled
npx @biomejs/biome check --write ./src --linter-enabled=false
7. The diagnostic level
npx @biomejs/biome check ./src --diagnostic-level=error
8. The max diagnostics
npx @biomejs/biome check ./src --max-diagnostics=20
9. The CI command
npx @biomejs/biome ci ./src
10. The stdin check
echo 'let a;' | npx @biomejs/biome check --stdin-file-path=file.js
Visual
The Check Command’s Three Tools
┌──────────────────────────────────────────────────────────────┐
│ THE CHECK COMMAND RUNS THREE TOOLS IN ONE PASS │
│ │
│ Source file │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ One parse │ The AST is built once │
│ └──────────┬──────────┘ │
│ │ │
│ ┌──────┴──────┬──────────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────────┐ │
│ │Formatter│ │ Linter │ │ Import │ │
│ │ │ │ │ │ Organizer │ │
│ └───┬────┘ └───┬────┘ └─────┬──────┘ │
│ │ │ │ │
│ └────────────┴───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ The diagnostics and │ │
│ │ the fixes │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
The Write and Unsafe Flags
┌──────────────────────────────────────────────────────────────┐
│ THE FIX LEVELS │
│ │
│ No flags: │
│ ┌─────────────────────┐ │
│ │ The diagnostics are │ The files are not modified │
│ │ reported │ │
│ └─────────────────────┘ │
│ │
│ --write: │
│ ┌─────────────────────┐ │
│ │ The safe fixes are │ The formatting, the safe lint │
│ │ applied │ fixes, and the import sorting │
│ └─────────────────────┘ │
│ │
│ --write --unsafe: │
│ ┌─────────────────────┐ │
│ │ The unsafe fixes are│ The behavior can change │
│ │ also applied │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
The Check vs the CI Command
┌──────────────────────────────────────────────────────────────┐
│ CHECK VS CI │
│ │
│ biome check biome ci │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Accepts --write │ │ Read-only │ │
│ │ For the local dev │ │ For the pipelines │ │
│ │ Can modify files │ │ Cannot modify files │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ The check is the local tool. │
│ The ci is the remote gate. │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
check | Runs the formatter, the linter, and the import organizer |
--write | Applies the safe fixes from the three tools |
--unsafe | Applies the unsafe fixes, requires --write |
--staged | The Git-staged files (pre-commit) |
--changed | The files changed since the default branch (CI) |
ci | The read-only variant for the pipelines |
| Single pass | The formatter and the linter share the AST |
Key takeaways:
biome checkruns the three tools in a single parse pass. The formatter, the linter, and the import organizer all read from the same AST, which is the architectural decision that makes the command faster than the separateformatandlintinvocations .- The
--writeflag is the fix application. Without it, the command is a read-only audit that reports the diagnostics and exits non-zero if any error is found. With it, the safe fixes from the three tools are applied . - The
--unsafeflag extends the fixes to the behavior-changing ones. The unsafe fixes may change the semantics, so the developer reviews the diff before the commit. The flag requires--write. - The
--stagedand--changedflags are the file filters. The--stagedflag is the pre-commit hook mechanism, and the--changedflag is the CI mechanism for the files that differ from the default branch . - The
cicommand is the read-only variant for the pipelines. Thecheckcommand accepts--write, which is dangerous in the CI because it modifies the repository. Thecicommand is the read-only gate that the pipeline should use .
Remember: The check command is the single pass that runs the formatter, the linter, and the import organizer. The --write flag applies the safe fixes, the --unsafe flag extends the fixes to the behavior-changing ones, and the --staged and --changed flags filter the files. The ci command is the read-only variant for the pipeline. The single parse is the reason the command exists, and the three tools in one invocation are the reason it is the default.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!