Migrate from Prettier to bun fmt
bun fmt reads your .prettierrc and prints what Prettier 3 prints. In most projects you only change the command.
Start with --doctor. It shows what Bun will do with your config, and it doesn't format or write anything.
bun fmt --doctorUsing .prettierrc (Prettier config)
4 files are formatted natively
Built-in plugins: @ianvs/prettier-plugin-sort-imports
You can remove: @ianvs/prettier-plugin-sort-imports
Still needed: prettier (the "format" script runs it)
Not checked: other tools' configs, CI files, Git hooksChange the scripts.
{
"scripts": {
"format": "prettier --write .",
"format:check": "prettier --check .",
"format": "bun fmt",
"format:check": "bun fmt --check"
}
}bun fmt writes by default and formats the current directory, so --write . goes away. Other flags and arguments stay the same. Change CI and Git hooks too.
If your script is called fmt, don't skip this: bun fmt runs a fmt script when package.json has one, so you'd still get Prettier.
Watch out for two differences in hooks and shell scripts:
- No arguments means the current directory. Prettier prints an error there. So if the file list can be empty, as in
git diff --cached --name-only | xargs bun fmtorbun fmt $(git ls-files '*.foo'), Bun formats everything. Usebun fmt --stagedin a pre-commit hook, orxargs -r. bun fmt file.tswrites the file and prints its name.prettier file.tsprints the formatted code. To print it, pipe the code in:bun fmt --stdin-filepath file.ts < file.ts.
Piping into --parser works like in Prettier: generate | bun fmt --parser typescript > out.ts.
Check that nothing changes. With a Prettier config, --check prints what Prettier prints.
bun fmt --check$ bun fmt --check
Checking formatting...
All matched files use Prettier code style!Run --doctor again. No script runs Prettier anymore, so it can go too.
You can remove: @ianvs/prettier-plugin-sort-imports, prettier
Not checked: other tools' configs, CI files, Git hooksbun remove prettier @ianvs/prettier-plugin-sort-importsLeave .prettierrc as it is, including plugins.
Keep prettier if your editor's Prettier extension uses it.
Bun reads everything Prettier reads:
.prettierrcin JSON, YAML, TOML, JavaScript, or TypeScript,prettier.config.*, and"prettier"inpackage.json, withoverrides.editorconfig,.prettierignore, and.gitignore// prettier-ignorecomments and the@formatand@noformatpragmas- Every flag of Prettier 3 except
--file-infoand--support-info
Bun doesn't load Prettier plugins. These are built in, with all their options, so leave them in plugins:
prettier-plugin-tailwindcss@trivago/prettier-plugin-sort-imports@ianvs/prettier-plugin-sort-importsprettier-plugin-organize-imports@prettier/plugin-oxc
Svelte, Astro, and other languages that come from a plugin go to your installed Prettier. So does package.json if you use prettier-plugin-packagejson. Keep prettier and every plugin in plugins installed. --doctor shows which files those are.
Using .prettierrc (Prettier config)
3 files are formatted natively
1 file goes to your installed Prettier: 1 *.svelte
Built-in plugins: @ianvs/prettier-plugin-sort-imports
Plugins that use your installed Prettier: prettier-plugin-svelte
Still needed: @ianvs/prettier-plugin-sort-imports, prettier, prettier-plugin-svelte (some files go to them)With any other plugin, Bun skips the files that config covers and exits with code 2. A plugin could print them differently, and Bun won't guess. Pass --allow-unsupported to format them without the plugin.
[error] 3 files were not formatted because the Prettier config uses plugins that bun fmt does not include: prettier-plugin-brace-style
[error] Use --allow-unsupported to format them without the plugins.You don't have to keep .prettierrc. Move the options to bunfig.toml, under the same names, and delete the file. overrides become [[fmt.overrides]].
[fmt]
semi = false
singleQuote = trueWithout a Prettier config, bun fmt also formats TOML files, and --check prints a shorter report.
Differences from Prettier#
If bun fmt and Prettier 3 print different code, that's a bug. Open an issue. These differences are intentional:
- It writes by default.
--writeis accepted and does nothing. - No arguments means the current directory.
- Only changed files are listed, followed by a summary on stderr.
- An unknown flag is an error. Prettier warns and continues.
--cachedoes nothing. Every run formats every file.- Exit code
2means something went wrong, like a syntax error or a skipped file. Prettier uses1for some of these. - Bytes that aren't valid UTF-8 are kept. Prettier replaces them.
- Where Prettier's output changes what a file means, Bun's differs. That's rare. In a Handlebars template Prettier drops
<!DOCTYPE html>, and it joins the lines of a<script>, so a// commentswallows the code after it. In CSS it turnsFont\ AwesomeintoFont\Awesome. Bun keeps all three. - Symlinks that lead out of the repository aren't written through.
console.login your config file is hidden unless the config fails to load.
See also: