Biome 04 🧹 CLI Basics — format, lint, and check commands
Biome’s command-line interface is built around three verbs: format, lint, and check. Each verb maps to one or more of the tools that Biome provides. The format command runs the formatter. The lint command runs the linter. The check command runs both, plus the import organizer, in a single pass . The verbs are not interchangeable, and the choice between them is the difference between a targeted fix and a full audit. The check command is the one that the pre-commit hook and the CI job use, because it covers the three concerns in one invocation. The format and lint commands are the ones the developer uses when they want to isolate a single tool.
The flags are the second half of the CLI. The --write flag is the one that applies the changes; without it, the command is a read-only check. The --unsafe flag extends the fixes to the ones that can change the behavior, and it requires --write . The --staged and --changed flags filter the files to the ones that Git has staged or changed, which is the mechanism that keeps the pre-commit hook fast. The --stdin-file-path flag is the mechanism for the editor integration and the piped input, where the code comes from stdin and the filename is the hint that tells Biome which parser to use. The exit code, the diagnostic levels, and the output formats are the third layer, and they are the layer that the CI pipeline reads.
Key point: format runs the formatter, lint runs the linter, and check runs the formatter, the linter, and the import organizer together. The --write flag applies the safe fixes and the formatting; without it, the command is a read-only check. The --unsafe flag applies the fixes that can change the behavior, and it requires --write. The --staged and --changed flags filter the files to the Git-staged or Git-changed ones. The exit code is 0 on success, 1 on the diagnostics, and 2 on the configuration or the internal error.
Why the three commands exist
The single-tool problem. A developer who is debugging a formatting issue wants to run only the formatter. Running the full check would also report the lint errors, which are noise for the formatting task. The format command is the targeted tool, and the lint command is the targeted tool for the lint errors. The separation is the mechanism that lets the developer focus on one concern at a time.
The full-audit problem. A CI job wants to check the formatting, the lint rules, and the import order in one pass. Running three separate commands would parse the files three times and produce three separate exit codes. The check command is the combined audit, and the single parse is the reason it is faster than the three separate commands . The check is the command that the CI and the pre-commit hook use.
The read-only problem. The --write flag is the difference between a check and a fix. Without it, the command reports the problems and exits with a non-zero code if any are found. With it, the command applies the safe fixes and the formatting. The read-only mode is the CI mode, and the write mode is the local mode. The distinction is the mechanism that keeps the CI from modifying the repository.
The file-filter problem. A pre-commit hook should only check the files that the developer has staged. Checking the whole repository on every commit is slow and produces the errors for the files the developer did not touch. 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 filter is the mechanism that makes the hook fast.
The diagnostic-level problem. A project that is migrating to Biome has hundreds of diagnostics, and the CI job would fail on all of them. The --diagnostic-level flag filters the output to the errors, the warnings, or the information, and the --max-diagnostics flag caps the number of diagnostics that are printed . The filtering is the mechanism that makes the migration incremental.
The exit-code problem. The CI pipeline reads the exit code, not the output. The exit code is 0 when there are no diagnostics, 1 when there are diagnostics, and 2 when the command fails for a reason other than the diagnostics, such as the malformed configuration or the internal error . The distinction is the mechanism that separates the lint failure from the tool failure.
a. The format and lint commands
The format command runs the formatter. The --write flag applies the changes; without it, the command reports the files that are not formatted and exits with a non-zero code.
# The format check (read-only)
npx @biomejs/biome format ./src
# The format fix
npx @biomejs/biome format --write ./src
# The format check with the specific diagnostic level
npx @biomejs/biome format ./src --diagnostic-level=error
The read-only form is the one that the CI uses when the formatting is a separate gate. The write form is the one that the developer runs locally to apply the changes. The --diagnostic-level=error flag filters the output to the errors, which is the mechanism that suppresses the informational diagnostics during a migration . The formatter configuration in the biome.json governs the output, and the --write flag is the mechanism that writes it.
# The lint check (read-only)
npx @biomejs/biome lint ./src
# The lint fix (safe fixes only)
npx @biomejs/biome lint --write ./src
# The lint fix with the unsafe fixes
npx @biomejs/biome lint --write --unsafe ./src
# The lint check with the maximum diagnostic count
npx @biomejs/biome lint ./src --max-diagnostics=20
The lint command runs the linter. The --write flag applies the safe fixes, and the --unsafe flag extends the fixes to the ones that can change the behavior . The unsafe fixes are the ones that the linter cannot guarantee are behavior-preserving, such as the removal of a variable that might have a side effect. The --unsafe flag requires --write, because a read-only unsafe fix makes no sense. The --max-diagnostics=20 flag caps the output to the first 20 diagnostics, which is the mechanism that keeps a noisy migration readable .
b. The check command and the file filters
The check command runs the formatter, the linter, and the import organizer in a single pass. It is the command that the quick start recommends for the full audit .
# The full check (read-only)
npx @biomejs/biome check ./src
# The full check with the safe fixes
npx @biomejs/biome check --write ./src
# The full check with the unsafe fixes
npx @biomejs/biome check --write --unsafe ./src
The check command is the combination, and the --write flag applies the safe fixes from the three tools. The --unsafe flag is the extension for the behavior-changing fixes. The check is the one command that the pre-commit hook and the CI use, and the format and lint are the targeted commands.
# The check on the Git-staged files
npx @biomejs/biome check --staged
# The check on the files changed since the default branch
npx @biomejs/biome check --changed
# The check on the files changed since a specific branch
npx @biomejs/biome check --since=origin/develop
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 filters are the mechanism that keeps the check fast, and the pre-commit hook is the case where the --staged flag is the right choice.
The --stdin-file-path flag is the mechanism for the piped input. The code comes from stdin, and the filename tells Biome which parser to use. The file does not need to exist on disk.
# The stdin check
echo 'let a;' | npx @biomejs/biome check --stdin-file-path=file.js
# The stdin check with the specific diagnostic level
echo 'let a;' | npx @biomejs/biome check --stdin-file-path=file.js --diagnostic-level=error
The --stdin-file-path is the editor integration mechanism, and it is the way to check a buffer that has not been saved to disk. The path is the hint for the parser and the configuration overrides, not a file that Biome reads. The --diagnostic-level flag is the filter for the output, and it works with the stdin mode.
The --formatter-enabled, --linter-enabled, and --organize-imports-enabled flags are the inline overrides. They override the biome.json settings for a single invocation, which is the mechanism for the CI job that wants to check only the formatting without the lint rules.
# 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 check with the import organizer disabled
npx @biomejs/biome check --write ./src --organize-imports-enabled=false
The inline overrides are the mechanism that makes the check command the only command the project needs. The --linter-enabled=false makes the check behave like the format, and the --formatter-enabled=false makes it behave like the lint. The --organize-imports-enabled=false keeps the import order untouched while the formatting and the linting run.
Complete Example Session
# ============================================
# PART 1: THE FORMAT CHECK
# ============================================
# The read-only format check.
npx @biomejs/biome format ./src
# The command reports the unformatted files.
# The exit code is non-zero if any file is not formatted.
# ============================================
# PART 2: THE FORMAT FIX
# ============================================
# The format fix.
npx @biomejs/biome format --write ./src
# The command formats the files in place.
# The exit code is zero if the formatting succeeds.
# ============================================
# PART 3: THE LINT CHECK
# ============================================
# The read-only lint check.
npx @biomejs/biome lint ./src
# The command reports the lint errors.
# The exit code is non-zero if any error is found.
# ============================================
# PART 4: THE LINT FIX
# ============================================
# The safe lint fixes.
npx @biomejs/biome lint --write ./src
# The command applies the safe fixes.
# The behavior-changing fixes are not applied.
# ============================================
# PART 5: THE UNSAFE LINT FIX
# ============================================
# The unsafe lint fixes.
npx @biomejs/biome lint --write --unsafe ./src
# The command applies the unsafe fixes.
# The --unsafe flag requires --write.
# ============================================
# PART 6: THE FULL CHECK
# ============================================
# The full check with the safe fixes.
npx @biomejs/biome check --write ./src
# The command runs the formatter, the linter, and the import organizer.
# The safe fixes are applied.
# ============================================
# PART 7: THE STAGED FILES
# ============================================
# The check on the Git-staged files.
npx @biomejs/biome check --staged
# The command only checks the files that are staged for the commit.
# The pre-commit hook uses this.
# ============================================
# PART 8: THE CHANGED FILES
# ============================================
# The check on the files changed since the default branch.
npx @biomejs/biome check --changed
# The command only checks the files that differ from the default branch.
# ============================================
# 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 format command runs the formatter.
# [ ] The lint command runs the linter.
# [ ] 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 --stdin-file-path flag checks the piped input.
# [ ] The --diagnostic-level flag filters the output.
# [ ] The --max-diagnostics flag caps the diagnostic count.
# [ ] The --linter-enabled and --formatter-enabled flags override the configuration.
The ten parts covered the format check, the format fix, the lint check, the lint fix, the unsafe lint fix, the full check, the staged files, the changed files, the stdin check, and the checklist. The through-line is that the three verbs map to the three tools, and the flags are the mechanism that controls the scope, the output, and the write behavior.
Quick Reference
The three commands
| Command | Tools | Read-only default |
|---|---|---|
format | The formatter | Yes |
lint | The linter | Yes |
check | The formatter, the linter, the import organizer | Yes |
The key flags
| Flag | Commands | Purpose |
|---|---|---|
--write | format, lint, check | Apply the safe fixes |
--unsafe | lint, check | Apply the unsafe fixes (requires --write) |
--staged | check, format, lint | The Git-staged files |
--changed | check, format, lint | The files changed since the default branch |
--since=<ref> | check, format, lint | The files changed since a specific ref |
--stdin-file-path | check, format | The piped input with the filename hint |
The diagnostic flags
| Flag | Purpose |
|---|---|
--diagnostic-level=<level> | Filter to error, warn, or info |
--max-diagnostics=<n> | Cap the number of printed diagnostics |
--error-on-warnings | Treat the warnings as errors |
--verbose | Print the additional details |
The inline tool overrides
| Flag | Purpose |
|---|---|
--formatter-enabled=<bool> | Enable or disable the formatter |
--linter-enabled=<bool> | Enable or disable the linter |
--organize-imports-enabled=<bool> | Enable or disable the import organizer |
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 # ✅
# Use --unsafe with --write
npx @biomejs/biome lint --write --unsafe ./src # ✅
# Use --diagnostic-level to suppress the info during a migration
npx @biomejs/biome check ./src --diagnostic-level=error # ✅
❌ Don’t Do This:
# Use --unsafe without --write
npx @biomejs/biome lint --unsafe ./src # ❌
# Run the full check in the pre-commit hook
npx @biomejs/biome check ./src # the whole repo is slow # ❌
# Ignore the exit code in the CI
npx @biomejs/biome check ./src || true # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The command 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 pre-commit hook is slow | The --staged flag is missing | Add --staged |
| The editor integration does not work | The --stdin-file-path is missing | Add the flag with the filename |
| The CI fails on the info diagnostics | The --diagnostic-level is not set | Add --diagnostic-level=error |
| The migration is unreadable | The --max-diagnostics is not set | Add --max-diagnostics=20 |
Real-World Examples
1. The format check
npx @biomejs/biome format ./src
2. The format fix
npx @biomejs/biome format --write ./src
3. The lint check
npx @biomejs/biome lint ./src
4. The lint fix with the unsafe fixes
npx @biomejs/biome lint --write --unsafe ./src
5. The full check
npx @biomejs/biome check --write ./src
6. The staged files
npx @biomejs/biome check --staged
7. The changed files
npx @biomejs/biome check --changed
8. The stdin check
echo 'let a;' | npx @biomejs/biome check --stdin-file-path=file.js
9. The diagnostic level
npx @biomejs/biome check ./src --diagnostic-level=error
10. The max diagnostics
npx @biomejs/biome check ./src --max-diagnostics=20
Visual
The Three Verbs and the Tools
┌──────────────────────────────────────────────────────────────┐
│ THE VERBS MAP TO THE TOOLS │
│ │
│ format lint check │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Formatter│ │ Linter │ │Formatter│ │
│ │ │ │ │ │ Linter │ │
│ │ │ │ │ │ Import │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ The check is the combination. │
│ The format and lint are the targeted tools. │
└──────────────────────────────────────────────────────────────┘
The Write and Unsafe Flags
┌──────────────────────────────────────────────────────────────┐
│ THE FLAGS DECIDE WHAT CHANGES │
│ │
│ No flags: │
│ ┌─────────────────────┐ │
│ │ The diagnostics are │ The exit code is 1 │
│ │ reported, the files │ if there are diagnostics. │
│ │ are not modified │ │
│ └─────────────────────┘ │
│ │
│ --write: │
│ ┌─────────────────────┐ │
│ │ The safe fixes are │ The files are modified │
│ │ applied │ │
│ └─────────────────────┘ │
│ │
│ --write --unsafe: │
│ ┌─────────────────────┐ │
│ │ The unsafe fixes │ The behavior can change │
│ │ are also applied │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
The File Filters
┌──────────────────────────────────────────────────────────────┐
│ THE FILE FILTERS │
│ │
│ --staged: │
│ ┌─────────────────────┐ │
│ │ The Git-staged │ The pre-commit hook mechanism │
│ │ files only │ │
│ └─────────────────────┘ │
│ │
│ --changed: │
│ ┌─────────────────────┐ │
│ │ The files changed │ The CI mechanism │
│ │ since the default │ │
│ │ branch │ │
│ └─────────────────────┘ │
│ │
│ --stdin-file-path: │
│ ┌─────────────────────┐ │
│ │ The code from stdin │ The editor integration │
│ │ with the filename │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
format | The formatter only |
lint | The linter only |
check | The formatter, the linter, the import organizer |
--write | Applies the safe fixes and the formatting |
--unsafe | Applies the unsafe fixes, requires --write |
--staged | The Git-staged files only |
--changed | The files changed since the default branch |
--stdin-file-path | The piped input with the filename hint |
--diagnostic-level | The filter for error, warn, or info |
--max-diagnostics | The cap on the printed diagnostics |
Key takeaways:
- The three verbs map to the three tools.
formatruns the formatter,lintruns the linter, andcheckruns both plus the import organizer . Thecheckis the combined audit, and theformatandlintare the targeted commands. - The
--writeflag is the difference between a check and a fix. Without it, the command reports the problems and exits with a non-zero code. With it, the command applies the safe fixes and the formatting . The read-only mode is the CI mode, and the write mode is the local mode. - The
--unsafeflag extends the fixes to the behavior-changing ones. The unsafe fixes are the ones the linter cannot guarantee are behavior-preserving, and the flag requires--write. A read-only unsafe fix makes no sense. - The
--stagedand--changedflags filter the files. 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 filters are the mechanism that keeps the check fast. - The
--stdin-file-pathflag is the editor integration mechanism. The code comes from stdin, and the filename tells Biome which parser to use. The file does not need to exist on disk. - The
--diagnostic-leveland--max-diagnosticsflags control the output. The--diagnostic-level=errorsuppresses the warnings and the information during a migration, and the--max-diagnostics=20caps the output to the first 20 diagnostics . The two flags are the mechanism that makes the migration readable. - The
--formatter-enabled,--linter-enabled, and--organize-imports-enabledflags are the inline overrides. They override thebiome.jsonsettings for a single invocation, which is the mechanism for the CI job that wants to check only one of the tools.
Remember: The Biome CLI is three verbs and a set of flags. The format, lint, and check commands map to the formatter, the linter, and the combined audit. The --write flag applies the changes, the --unsafe flag extends the fixes to the behavior-changing ones, and the --staged and --changed flags filter the files. The --diagnostic-level and --max-diagnostics flags control the output, and the --formatter-enabled, --linter-enabled, and --organize-imports-enabled flags are the inline overrides. The check is the command that the pre-commit hook and the CI use, and the format and lint are the targeted commands. The verbs are the tools, and the flags are the scope.
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!