# Formatter

> Bun's fast, built-in formatter for JavaScript, TypeScript, CSS, HTML, JSON, YAML, Markdown, and more

Bun ships with a fast, built-in code formatter. There's nothing to install and nothing to configure.

- JavaScript, TypeScript, JSX, CSS, SCSS, Less, HTML, Vue, Angular, JSON, YAML, TOML, Markdown, MDX, GraphQL, and Handlebars
- The same output as [Prettier](https://prettier.io)
- Sorts imports, Tailwind CSS classes, and `package.json`
- Works with your existing Prettier or oxfmt config

## Run the formatter

```bash terminal icon="terminal"
bun fmt
```

```txt
src/index.ts
src/server.ts
Formatted 2 files, 2 unchanged [3.47ms]
```

`bun fmt` rewrites the files in the current directory that need it and prints their names. It skips `node_modules`, anything in your `.gitignore`, minified files (`*.min.js`, `*.min.css`) and lock files such as `package-lock.json`.

To format specific files, pass paths or globs.

```bash terminal icon="terminal"
bun fmt src "test/**/*.ts"
```

Embedded code is formatted too: `<script>` and `<style>` in HTML and Vue, code blocks in Markdown, and `` css`...` ``, `` html`...` ``, and `` graphql`...` `` templates in JavaScript.

## Check without writing

`--check` lists the files that need formatting and writes nothing.

```bash terminal icon="terminal"
bun fmt --check
```

```txt
src/index.ts
src/server.ts
2 files need formatting. Run bun fmt to fix them.
```

The exit code is `1` if a file needs formatting, `0` if none do, and `2` if something went wrong, like a syntax error. That makes it the command for CI.

```yaml .github/workflows/format.yml icon="file-code"
steps:
  - uses: actions/checkout@v4
  - uses: oven-sh/setup-bun@v2
  - run: bun fmt --check
```

## Options

Options live in `bunfig.toml`. To create the section, run `bun fmt --init`.

```toml bunfig.toml icon="settings"
[fmt]
printWidth = 100
semi = false
singleQuote = true
```

| Option          | Default | What it does                  |
| --------------- | ------- | ----------------------------- |
| `printWidth`    | `80`    | Wrap lines at this column     |
| `tabWidth`      | `2`     | Spaces per indentation level  |
| `useTabs`       | `false` | Indent with tabs              |
| `semi`          | `true`  | Print semicolons              |
| `singleQuote`   | `false` | Use single quotes             |
| `trailingComma` | `"all"` | `"all"`, `"es5"`, or `"none"` |

All of [Prettier's options](https://prettier.io/docs/options) work, under the same names. Each one is also a flag, like `--print-width 100` or `--no-semi`.

### Different options for some files

```toml bunfig.toml icon="settings"
[[fmt.overrides]]
files = ["*.test.ts", "scripts/**"]
options = { printWidth = 120 }
```

### `.editorconfig`

`bun fmt` reads `indent_style`, `indent_size`, `tab_width`, `max_line_length`, and `end_of_line` from `.editorconfig`. `bunfig.toml` overrides them.

## Ignore files

To skip more than `.gitignore` does, list the files in `bunfig.toml`. A `.prettierignore` file works too.

```toml bunfig.toml icon="settings"
[fmt]
ignorePatterns = ["vendor/", "**/*.gen.ts"]
```

## Ignore code

`bun fmt` uses Prettier's comment, so existing ones keep working. It applies to the next statement, element, or rule.

```ts
// prettier-ignore
const matrix = [
  1, 0, 0,
  0, 1, 0,
  0, 0, 1,
];
```

In JSX it's `{/* prettier-ignore */}`, in CSS `/* prettier-ignore */`, in HTML and Markdown `<!-- prettier-ignore -->`, and in YAML and GraphQL `# prettier-ignore`.

## Sort imports

```toml bunfig.toml icon="settings"
[fmt]
sortImports = true
```

```ts title="Before"
import { z } from "zod";
import { b, a } from "./util";
import { db } from "@/db";
import { readFile } from "node:fs/promises";
import { c } from "./util";
```

```ts title="After"
import { readFile } from "node:fs/promises";

import { z } from "zod";

import { db } from "@/db";

import { a, b, c } from "./util";
```

- Imports are grouped: built-in modules, packages, aliases like `@/`, relative paths, styles.
- Each group is sorted by path, and the names in `{ }` are sorted too.
- Two imports from the same module become one.
- Side-effect imports like `import "./setup"` never move, and nothing moves past one.

To pick your own groups, use a table. See [`format.sortImports`](/runtime/bunfig#format-sortimports).

```toml bunfig.toml icon="settings"
[fmt.sortImports]
groups = ["react", "builtin", "external", "internal", ["parent", "sibling", "index"]]
customGroups = [{ groupName = "react", elementNamePattern = ["react", "react-dom/**"] }]
```

## Sort Tailwind CSS classes

```toml bunfig.toml icon="settings"
[fmt]
sortTailwindcss = true
```

```tsx
<a className="p-4 flex m-2" /> // [!code --]
<a className="m-2 flex p-4" /> // [!code ++]
```

Classes are sorted in Tailwind's recommended order, in `class` and `className` and in calls to `clsx`, `cn`, `cva`, `twMerge`, and [a few more](/runtime/bunfig#format-sorttailwindcss). The order comes from the `tailwindcss` package in your project, so version 3 or 4 has to be installed.

If your `.prettierrc` lists `prettier-plugin-tailwindcss`, sorting is already on, with that plugin's options and defaults.

To name your own functions or your stylesheet, use a table.

```toml bunfig.toml icon="settings"
[fmt.sortTailwindcss]
stylesheet = "./src/app.css"
functions = ["clsx", "tw"]
```

## Sort `package.json`

```toml bunfig.toml icon="settings"
[fmt]
sortPackageJson = true
```

Keys go in the conventional order: `name`, `version`, `description`, and so on.

```json title="Before"
{
  "dependencies": { "zod": "^4.0.0" },
  "scripts": { "dev": "bun --hot src/index.ts" },
  "version": "1.0.0",
  "name": "app"
}
```

```json title="After"
{
  "name": "app",
  "version": "1.0.0",
  "scripts": {
    "dev": "bun --hot src/index.ts"
  },
  "dependencies": {
    "zod": "^4.0.0"
  }
}
```

## Format JSDoc comments

```toml bunfig.toml icon="settings"
[fmt]
jsdoc = true
```

```js title="Before"
/**
 * adds two numbers
 * @returns {number} the sum
 * @param {number} b second number
 * @param {number} a   first number
 */
```

```js title="After"
/**
 * Adds two numbers
 *
 * @param {number} a First number
 * @param {number} b Second number
 * @returns {number} The sum
 */
```

## Standard input

Pipe text through `bun fmt`. It prints the result and writes nothing. The path picks the language and the options. The file doesn't have to exist.

```bash terminal icon="terminal"
bun fmt --stdin-filepath src/index.ts < src/index.ts
```

No path to give? Name the parser instead. Your config still applies, except for what goes by a file name: `overrides`, `.editorconfig`, and ignore files.

```bash terminal icon="terminal"
bun run generate-types | bun fmt --parser typescript > types.ts
```

## Git hooks

`--staged` formats only the files you're about to commit and stages them again, so you don't need `lint-staged`.

```sh .git/hooks/pre-commit icon="terminal"
#!/bin/sh
bun fmt --staged
```

A file with both staged and unstaged changes isn't written, because staging it again would commit the rest. Bun names the file and exits with code `2`.

`--changed` formats the files that differ from your default branch. Pass a ref to compare with something else.

```bash terminal icon="terminal"
bun fmt --changed
bun fmt --changed=origin/dev
```

## Migrate from Prettier or oxfmt

Already have a `.prettierrc` or an `.oxfmtrc.json`? `bun fmt` reads it and prints what that tool prints. Change the script and you're done.

```json package.json icon="file-json"
{
  "scripts": {
    "format": "prettier --write .", // [!code --]
    "format": "bun fmt" // [!code ++]
  }
}
```

If `package.json` has a `fmt` script, `bun fmt` runs that script. Inside the script, `bun fmt` is the formatter.

Svelte and Astro aren't built in. If your `.prettierrc` lists their plugin, Bun sends those files to your installed Prettier. To see which files those are, and which packages you can uninstall:

```bash terminal icon="terminal"
bun fmt --doctor
```

See the guides: [Migrate from Prettier](/guides/format/migrate-from-prettier) and [Migrate from oxfmt](/guides/format/migrate-from-oxfmt).

# CLI Usage

```bash
bun fmt [flags] [files, directories, or globs]
```

### Modes

<ParamField path="-c, --check" type="boolean">
  Write nothing. Exit with code 1 if a file needs formatting
</ParamField>

<ParamField path="-l, --list-different" type="boolean">
  Like <code>--check</code>, but print only the file names
</ParamField>

<ParamField path="--stdin-filepath" type="string">
  Format standard input as this file and print the result
</ParamField>

<ParamField path="--init" type="boolean">
  Add a <code>[fmt]</code> section to <code>bunfig.toml</code>
</ParamField>

<ParamField path="--doctor" type="boolean">
  Show what Bun does with your Prettier or oxfmt config, and which packages you can remove
</ParamField>

### Files

<ParamField path="--staged" type="boolean">
  Format only the files staged in Git, and stage them again
</ParamField>

<ParamField path="--changed" type="string">
  Format only the files that differ from a Git ref. Defaults to the default branch
</ParamField>

<ParamField path="--ignore-pattern" type="string">
  Skip files that match this glob. Can be repeated
</ParamField>

### Options

<ParamField path="--print-width" type="number" default="80">
  Wrap lines at this column
</ParamField>

<ParamField path="--tab-width" type="number" default="2">
  Spaces per indentation level
</ParamField>

<ParamField path="--use-tabs" type="boolean">
  Indent with tabs
</ParamField>

<ParamField path="--no-semi" type="boolean">
  Only print semicolons where they are needed
</ParamField>

<ParamField path="--single-quote" type="boolean">
  Use single quotes
</ParamField>

<ParamField path="--trailing-comma" type="string" default="all">
  <code>all</code>, <code>es5</code>, or <code>none</code>
</ParamField>

<ParamField path="--sort-imports" type="boolean">
  Sort and group imports
</ParamField>

<ParamField path="--sort-tailwindcss" type="boolean">
  Sort Tailwind CSS classes
</ParamField>

<ParamField path="--sort-package-json" type="boolean">
  Sort the keys of <code>package.json</code>
</ParamField>

<ParamField path="--jsdoc" type="boolean">
  Format JSDoc comments
</ParamField>

<ParamField path="--no-editorconfig" type="boolean">
  Do not read <code>.editorconfig</code>
</ParamField>

All of [Prettier's options](https://prettier.io/docs/options) are flags too.

### Output

<ParamField path="--log-level" type="string" default="log">
  <code>silent</code>, <code>error</code>, <code>warn</code>, <code>log</code>, or <code>debug</code>
</ParamField>

<ParamField path="--threads" type="number">
  Number of threads. Defaults to one per CPU core
</ParamField>

`bun fmt` also accepts the flags of Prettier and oxfmt. Run `bun fmt --help --all` to see them.
