Bun(バン)は、JavaScriptとTypeScriptの実行、パッケージ管理、テスト、バンドルを1つの実行ファイルにまとめたツールです。実行エンジンはNode.jsと同じV8ではなく、Safari由来のJavaScriptCoreです。2026年10月25日時点の最新安定版は1.4.4(10月22日公開)で、1.4.3で型チェックの bun check、1.4.4で整形の bun fmt が組み込みのコマンドになりました。Homebrewで入れるなら、公式ドキュメントが案内しているのは brew install oven-sh/bun/bun です。短い brew install bun は別のformulaを指すので、その違いも説明します。
まとめ:Bunの導入と使い方の要点
- Bunは英単語のbunと同じ綴りで「バン」と読む。開発元のOvenは2025年12月2日にAnthropicに買収されたが、MITライセンスのオープンソースのまま開発が続いている。
- エンジンはV8ではなくJavaScriptCore。Node.jsのAPIは
node:モジュールごとに実装の度合いが違い、Node-APIのネイティブアドオンは多くが動く一方、V8のC++ APIやV8のプロファイラに頼るツールは動かないことがある。 - macOSとLinuxは
curl -fsSL https://bun.com/install | bash、Windowsはpowershell -c "irm bun.sh/install.ps1|iex"で入る。macOSは13.0以降、Windowsは10 バージョン1809以降が必要。 - Homebrewでは
oven-sh/buntap(公式配布バイナリを配置)と、homebrew-core のbun(ソースからビルド)が並存している。Intel Macでbrew install bunを実行すると、LLVMとRustを入れてソースからビルドすることになる。更新はbun upgradeではなくbrew upgrade bun。 bun installは既存のnpmプロジェクトでも動き、package-lock.jsonを読んでbun.lockに移行する。依存パッケージのpostinstallは、既定ではnpm由来の既定許可リスト掲載パッケージだけが実行対象になる。- 型チェックは
bun check(1.4.3〜)、整形はbun fmt(1.4.4〜)。package.jsonに同名のスクリプトがあるとそちらが優先される。bun lintは今も組み込みではない。 - 更新チャネルはstableとcanaryの2つだけでLTSは無い。本番とCIでは、インストーラーにタグを渡すか、GitHub Actionsの
setup-bunに版を読ませて固定する。Bun自身はpackage.jsonの版指定を見ない。
Bunの読み方と位置づけ|Node.jsとnpmの役割を1つに集約したツール
Bunの読み方と開発体制
Bunは英単語の bun(丸い小型のパン)と同じ綴りで、英語の発音 /bʌn/ に沿って「バン」と読むのが一般的です。「Bun.js」「bun js」と書かれることもありますが、公式の名称は単にBunです。開発はJarred Sumner氏が率いるOvenが行ってきました。2025年12月2日には公式ブログが「Bun has been acquired by Anthropic.」と発表し、同じ記事で「Bun stays open-source & MIT-licensed」と明記しています。1.0は2023年9月8日、Windows対応を加えた1.1は2024年4月1日、1.4.0は2026年8月20日に公開されました。
Node.jsの開発環境との役割の対応
Node.jsで開発するときは、実行はnode、依存関係はnpm、型チェックはtsc、整形はPrettier、バンドルはesbuildやwebpackと、役割ごとに別のツールを組み合わせます。Bun 1.4.4は、このうち実行・依存関係の管理・型チェック・整形・テスト・バンドルを組み込み機能として提供し、リンターだけは持っていません。
| 役割 | Node.jsでの一般的な構成 | Bun(1.4.4) |
|---|---|---|
| スクリプト実行 | node | bun run / bun ファイル名 |
| 依存関係の管理 | npm・pnpm・yarn | bun install / bun add |
| パッケージの一時実行 | npx | bunx(bun x) |
| 型チェック | tsc --noEmit |
bun check(1.4.3〜) |
| 整形 | Prettier | bun fmt(1.4.4〜) |
| リント | ESLint | なし(scriptsで呼ぶ) |
| テスト | node:test・Jest・Vitest | bun test |
| バンドル | esbuild・webpack | bun build |
Node.js側の構成はNode.jsの仕組みと版の選び方、npmとnpxの役割はnpmのCLIとレジストリの役割とnpxとnpm execの違いで説明しています。
Bunランタイムの仕組み|JavaScriptCoreで動くNode.js互換の実行環境
エンジンはV8ではなくJavaScriptCore
Bunを「V8ベースの高速ランタイム」と紹介する記事がありますが、誤りです。公式リポジトリのREADMEは、Bunランタイムを「a drop-in replacement for Node.js」と定義したうえで「powered by JavaScriptCore under the hood」と書いています。JavaScriptCoreはSafari(WebKit)のエンジンで、V8はNode.jsとChrome系のエンジンです。公式ブログのV8 API対応の解説は、ガベージコレクタがJavaScriptCoreでは「Non-moving, conservative」、V8では「Moving, precise」と、両者を別の設計の実装として対比しています。
1.4.4で process.versions を表示すると、少し紛らわしい値が返ります。
bun -e 'console.log(process.versions.node, process.versions.v8, process.release.name)'
# 26.3.0 14.6.202.34-node.20 node
bun -e 'import { heapStats } from "bun:jsc"; console.log(heapStats().heapSize)'
# 134939(JavaScriptCoreのヒープの使用量・バイト)
process.versions.node は26.3.0、v8 にも版らしい文字列が入り、process.release.name は node です。Node.js向けのライブラリが版を判定して分岐しても動くように、Node.jsを名乗っているためです。この値で「V8で動いている」と判断しないでください。エンジンを確かめるなら process.versions.bun(1.4.4)と process.versions.webkit を見ます。JavaScriptCoreを直接扱う低レベルAPIは bun:jsc モジュールにあり、heapStats() などでヒープの状態を取れます。
実装言語は1.4系で切り替わりました。GitHubのタグごとに src/ 配下を数えると、安定版の1.3系最終の bun-v1.3.14 は .zig が1,290ファイルで .rs は0、bun-v1.4.4 は .rs が3,238ファイルで .zig は0でした。1.3系はZig、1.4系はRustで書かれています。移植で変わった挙動はBun 1.4のRust移植と1.3からの移行で変わる挙動にまとめています。
Node.js互換が成り立つ範囲とネイティブアドオン
公式の互換表によると、Bunは各リリース前に、Node.jsのテストスイートに含まれる数千件のテストを実行しています。ただし互換の度合いは node: モジュールごとに違い、移行で問題になりやすいのは次の4つです。
| 対象 | 互換表の状態 | 移行で起きること |
|---|---|---|
| node:fs | 完全実装(テスト98%通過) | ほぼそのまま動く |
| node:cluster | 一部実装 | HTTPの負荷分散はLinuxのみ |
| node:v8 | 一部実装 | CPUプロファイル系が無い |
| node:inspector | 一部実装 | Runtime.evaluate・HeapProfilerが無い |
node:cluster は、ワーカーごとのHTTPサーバーがそれぞれ独自にソケットを開くため、プロセス間でHTTPリクエストを振り分けられるのは SO_REUSEPORT を使うLinuxだけです。node:v8 はヒープスナップショットを取れますが、統計値はJavaScriptCoreのヒープを表し、startCpuProfile や takeCoverage はありません。node:inspector も、Session で使えるのは Profiler ドメインなどに限られ、Runtime.evaluate と HeapProfiler ドメインは未実装です。互換表もプロファイリングには bun:jsc を使うよう案内しています。
C++のネイティブアドオンは、どのAPIで書かれているかで結果が分かれます。Node-APIの公式ドキュメントによると、BunはNode-APIを独自に実装しており、既存の拡張の多くはそのまま動きます。.node ファイルも require() で読み込めます。一方、V8のC++ APIを直接呼ぶアドオンについては、1.1.25から対応するAPIを順に増やしている途中で、すべてが動くわけではありません。
Node.jsから置き換えない方がよいのは、V8のC++ APIに直接依存するアドオン、V8のプロファイラやインスペクタに接続するAPMエージェント、複数プロセスでのHTTP負荷分散を node:cluster に任せている構成(Linux以外)です。まず bun install・bun check・bun test だけをBunに寄せ、本番の実行はNode.jsのまま据え置く段階導入なら、失敗しても戻しやすくなります。既存システムの実行基盤をどこまで入れ替えるかを設計から決める案件は、フルスクラッチ開発として相談を受けています。
Node.js・Deno・Viteとの守備範囲の違い
BunとViteは、開発サーバーとバンドルの範囲で機能が重なりますが、ランタイムやパッケージ管理まで含むBunとは提供範囲が異なります。Viteは開発サーバーとビルドを受け持つビルドツールで、コードを実行するランタイムを持ちません。
| ツール | エンジン | ランタイム | パッケージ管理 | バンドル |
|---|---|---|---|---|
| Bun | JavaScriptCore | あり | 内蔵 | 内蔵 |
| Node.js | V8 | あり | npm(同梱) | 別ツール |
| Deno | V8 | あり | 内蔵 | 内蔵(deno bundle) |
| Vite | なし | なし | なし | あり |
BunとViteは一緒に使えます。公式のViteガイドによると、bun create vite my-app で作ったプロジェクトは追加の設定なしで動きます。ただしBunは既定でViteのCLI先頭にある #!/usr/bin/env node に従うため、bunx vite だけでは中身はNode.jsで動きます。Bunで動かすには bunx --bun vite と --bun を付けます。DenoとBun・Node.jsの選定は、Denoの開発体制の変化も含めてDeno・Bun・Node.jsの比較と移行の判断で扱っています。ランタイムは替えずにリントや変換だけを速くしたい場合は、Rust製ツールチェーンのOxcのようにビルド層だけを差し替える方が影響は小さく済みます。
Bunのインストール方法|curl・Windows・npm・Docker
Bunの公式インストールドキュメントが挙げる導入経路は次のとおりです。どの経路でも、導入後は新しいターミナルで bun --version を実行して確認します。
| 経路 | 対象OS | 更新コマンド | 削除コマンド |
|---|---|---|---|
| curlスクリプト | macOS・Linux | bun upgrade | rm -rf ~/.bun |
| PowerShellスクリプト | Windows | bun upgrade | ~\.bun\uninstall.ps1 |
| Homebrew | macOS・Linux | brew upgrade bun | brew uninstall bun |
| Scoop | Windows | scoop update bun | scoop uninstall bun |
| npm | 全OS | npm install -g bun | npm uninstall -g bun |
| Docker | Linux(x64・arm64) | イメージの再取得 | イメージの削除 |
入れた経路と同じ経路で更新・削除するのが原則です。経路を混ぜると、PATH上に別々のbunが2つ残ります。
macOS・Linuxはcurlスクリプト
curl -fsSL https://bun.com/install | bash
# 特定の版を入れる場合はタグを渡す
curl -fsSL https://bun.com/install | bash -s "bun-v1.4.3"
スクリプトは ~/.bun/bin にバイナリを置きます。導入後に command not found になる場合は、~/.zshrc などに export BUN_INSTALL="$HOME/.bun" と export PATH="$BUN_INSTALL/bin:$PATH" を追記してシェルを読み直します。Linuxでは unzip パッケージが必要です。カーネルは5.6以上が推奨で、3.10(RHEL 7)でも新しいシステムコールの機能を落として動きます。glibc版のバイナリはglibc 2.17以上が前提で、Alpine Linuxのようにglibcのないディストリビューションにはmusl版があります。
WindowsはPowerShellかScoop
powershell -c "irm bun.sh/install.ps1|iex"
# 版を指定する場合
iex "& {$(irm https://bun.com/install.ps1)} -Version 1.4.3"
Windows 10 バージョン1809以降が必要です。1.1(2024年4月1日)でWindowsにネイティブ対応したため、WSLは必須ではありません。Scoopを使っている環境なら scoop install bun でも入ります。PATHに入らないときは & "$env:USERPROFILE\.bun\bin\bun" --version で実体が動くかを確かめ、動けばユーザー環境変数のPathに %USERPROFILE%\.bun\bin を足します。
npmとDockerでの導入
Node.jsが入っている環境なら npm install -g bun でも導入できます。npmパッケージ bun はOSとCPUに合ったバイナリ(Intel Macなら @oven/bun-darwin-x64)を依存として取り込みます。npm 11.17.0で1.4.4を入れたところ、allowScripts で未承認のinstallスクリプトがあるという警告(npm warn allow-scripts)が出ましたが、postinstallは実行されて正常に終わり、bun --version は1.4.4を返しました。コンテナでは公式イメージ oven/bun を使い、用途に応じて debian・slim・distroless・alpine のタグを選びます。
bun vs brew|Homebrewで入れる前に知るべき2つのformula
Homebrewでは、コマンドの書き方によって入るものが変わります。2026年10月24日時点でOven公式のtapとhomebrew-coreのbun formulaを確認した結果は次のとおりです。
| 項目 | brew install oven-sh/bun/bun | brew install bun |
|---|---|---|
| formulaの管理元 | Oven(oven-sh/homebrew-bun) | Homebrew(homebrew-core) |
| 入るもの | GitHub Releasesの公式バイナリ | ソースからビルドしたバイナリ |
| ビルド済み配布(bottle) | 不要(配布物をそのまま配置) | Apple Silicon(Sequoia以降)とLinuxのみ |
| 公式ドキュメントの記載 | あり | なし |
| 旧版の固定 | [email protected] などの版別formula | なし |
版はどちらも1.4.4で揃っていますが、中身の作り方が違います。公式ドキュメントに沿うなら、tapを指定する brew install oven-sh/bun/bun を使ってください。
homebrew-core版のビルド方法とbottle配布の範囲
homebrew-coreの Formula/b/bun.rb は、bottle(Homebrewがビルド済みで配る成果物)のある環境ではそれを展開し、無い環境では利用者の手元でビルドします。ビルドは bun-v1.4.4 タグのソースを取得し、WebKitを浅いクローンで取り込んで行います。formulaのコメントによれば、WebKitの全履歴は約18GBあり、浅いクローンでも約7GBです。ビルド時の依存はcmake・llvm・ninja・rust(Intel Macではnasmも)で、加えてBun自身のビルドスクリプトを動かすために、上流のCIと同じ公式バイナリの1.4.2を「bootstrap」として先にダウンロードします。ソースからビルドする formula でも、Bunを作るのにBunが要る構成です。ビルド時の引数は --canary=off です。tap側の bun.rb は、CPUに合わせてaarch64・x64・x64-baselineのzipを選んで展開するだけで、ファイル内には「TODO: to become an official formula we need to build from source」というコメントが残っています。
Intel Macのbrew install bunで必要になるソースビルド
homebrew-coreのbunに用意されたbottleはApple SiliconのmacOS(Sequoia・Tahoe・Golden Gate)とLinux(arm64・x86_64)だけで、Intel Mac向けはありません。Homebrew 7.0.10とmacOS 26.6.2のIntel Macで brew install --dry-run bun を実行すると、z3・llvm 23.1.4・libgit2・rust 1.99.1・nasmの5つの依存を新たに入れ、sqlite・[email protected]・pkgconfの3つを更新する計画が表示されました。同時にHomebrewは、Intel x86_64のmacOSがTier 3であることと、この構成向けのbottleをもう作らないことを警告します。Intel Macでは、tap版かcurlスクリプトを選ぶとビルドを待たずに済みます。
Homebrew版Bunの更新コマンドとbun upgradeの競合
公式ドキュメントは「To avoid conflicts with Homebrew, use brew upgrade bun instead.」と案内しています。1.4.4の upgrade_command.rs を見ても、bun upgrade は実行中のバイナリの場所(self_exe_path)を新しいファイルで置き換える実装で、Homebrew経由かどうかを判定する処理はありません。Homebrew管理下のファイルを bun upgrade で書き換えると、Homebrewが記録している版と実体の版が一致しなくなります。旧版に固定したいときは、tapの版別formulaを brew install oven-sh/bun/[email protected] のように指定します。
bun installで依存パッケージを入れる手順
bun install は package.json の依存を node_modules に入れるコマンドで、短縮形は bun i です。dependencies・devDependencies・optionalDependencies に加え、peerDependencies も既定で入ります。ロックファイルはテキスト形式の bun.lock です。
既存npmプロジェクトのbun installへの移行手順
npm install is-number@7 # npmでpackage-lock.jsonを作った状態
bun install
# bun install v1.4.4 (38afee6c8)
# [1.62ms] migrated lockfile from package-lock.json
# Saved lockfile
1.4.4で試すと、bun.lock の無いプロジェクトでは package-lock.json から版を引き継いで bun.lock を作りました。公式ドキュメントによれば yarn.lock と pnpm-lock.yaml も移行の対象で、1.4.4ではYarn Berryのロックファイルにも対応しました。移行後も package-lock.json は消えずに残るため、チームでnpmと併用しない方針なら削除してコミットし、ロックファイルを1つに揃えます。
依存の置き方(リンカ)は、新しいワークスペース(モノレポ)ではpnpmに近い isolated、単一パッケージの新規プロジェクトと1.3.2より前に作ったプロジェクトでは従来どおりの hoisted が既定です。移行した上の例は bun.lock の configVersion が0になり、hoisted で入りました。隔離リンカの詳細はBun 1.4の解説記事、ストア設計の比較はpnpmの共有ストアの仕組みで扱っています。
ライフサイクルスクリプトとtrustedDependencies
npmと違い、Bunは依存パッケージの postinstall などのライフサイクルスクリプトを、許可リストに載ったものしか実行しません。公式ドキュメントによれば、package.json に trustedDependencies が無ければ、npmから入れた人気パッケージの既定許可リストが使われます。trustedDependencies を書くと既定リストは足されずに置き換わり、載せたパッケージだけが実行対象になります。空配列にすると、既定リストのパッケージも実行されません。インストール時にネイティブバイナリを取得するパッケージが動かないときは、ここを疑います。許可を足したら、もう一度 bun install を実行します。
{
"trustedDependencies": ["my-trusted-package"]
}
CIで使う--frozen-lockfileと--production
CIでは bun install --frozen-lockfile を使います。bun.lock と package.json が食い違うとエラーで止まり、ロックファイルを書き換えません。BunはCI環境を検知しても自動では有効にしないので、フラグを付けるか bun ci を使います。本番用の新規インストールで devDependencies を入れないときは bun install --production で、これは --frozen-lockfile を含みます。
グローバルインストールの置き場所
コマンドラインツールは bun install -g パッケージ名(bun add -g も同じ)で入れます。実行ファイルの置き場所は bun pm bin -g で確認でき、curlで入れた環境では ~/.bun/bin、パッケージ本体は ~/.bun/install/global に入ります。~/.bun/bin がPATHに入っていないと、グローバルに入れたコマンドも見つかりません。
bun initでプロジェクトを作る手順
mkdir my-app && cd my-app
bun init -y # 既定値(Blank)で作る
bun run index.ts
# テンプレートを対話で選ぶ場合は -y を付けずに実行する
# bun init
bun init -y で作ったプロジェクトは、bun run index.ts を実行すると Hello via Bun! と表示します。最後に bun install が走り、@types/bun と typescript(1.4.4では7.0.2)が入ります。
bun initのテンプレート3種と生成ファイル
対話で選べるテンプレートはBlank・React・Libraryの3つです。フラグで指定する場合は --react、--react=tailwind、--react=shadcn、型定義だけを入れる --minimal があります。1.4.4で bun init -y を実行すると、package.json・tsconfig.json・index.ts・README.md・.gitignore・bun.lock が生成されました。bunfig.toml は作られません。package.json には "type": "module" と、型チェック用の "typecheck": "bun check" というスクリプトが入り、peerDependencies は "typescript": "^7" でした。TypeScript 7はGoで書き直された型チェッカーで、詳細はTypeScript 7.0のGoネイティブ移植で扱っています。
CLAUDE.mdが自動で作られる条件
公式ドキュメントによると、bun init はClaude CLIを検出すると CLAUDE.md を、Cursorを検出すると .cursor/rules/ 以下にルールファイルを作ります。1.4.4で生成された CLAUDE.md は「Default to using Bun instead of Node.js.」で始まり、「Use bun check instead of tsc --noEmit」という行も入っていました。環境変数 BUN_AGENT_RULE_DISABLED=1 を付けて実行すると、CLAUDE.md は作られませんでした(Claude用だけを止める CLAUDE_CODE_AGENT_RULE_DISABLED、Cursor用だけを止める CURSOR_AGENT_RULE_DISABLED もあります)。チームで既に CLAUDE.md の運用ルールがあるリポジトリでは、生成された内容をそのままコミットせず確認してください。Claude Code側の扱いはClaude Codeの使い方とCLAUDE.md設定で説明しています。
bun checkによるTypeScriptの型検査
bun run や bun ファイル名 は、.ts の型を取り除いて実行するだけで型を検査しません。型の検査は、1.4.3(2026年10月10日公開)で入った bun check で行います。1.4.3のリリースノートによると、typescript-goを移植した型チェッカーで、tsconfig.json を読んで tsc と同じエラーを出し、typescript パッケージを入れなくても動きます。JavaScriptや .d.ts は出力しません。前節の bun init -y で作成し、依存関係をインストール済みのプロジェクトで、次の2行を bad.ts として保存し、実行と型チェックの違いを確かめます。
const n: number = "abc";
console.log("ran:", n);
bun bad.ts
# ran: abc(終了コード0)
bun check
# bad.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.
# Found 1 error in 1 file, checked 2 files(終了コード1)
bun run --check bad.ts
# 型エラーを表示して終了コード1。bad.ts は実行されない
1.4.4で実行した結果です。型エラーだけで実行時エラーの無いコードは、bun bad.ts では最後まで動いて終了コード0を返します。CIでは bun check を、実行やテストの前に止めたいなら --check フラグを使います。
tscから置き換えるコマンドの対応
bun checkの公式ドキュメントは、次のように置き換えを案内しています。.d.ts の生成には tsc を残します。また、bun test --check や bun build --check の検査対象は実行対象に依存するため、プロジェクト全体の検査を保証したいCIでは bun check も実行します。
| これまで | Bunでの置き換え |
|---|---|
tsc --noEmit |
bun check |
tsc -b |
bun check -b |
tsc --noEmit && bun test |
bun test --check |
tsc --noEmit && bun build ./app.ts |
bun build --check ./app.ts |
CIで知っておきたい挙動も同じページにあります。.tsbuildinfo を書かないので毎回プロジェクト全体を検査すること、検査対象が1つも無いと終了コード1で失敗すること、CPUコア数ぶんのスレッドを使うので共有ランナーでは --threads 4 などで絞れることです。bun check はTypeScript 7として振る舞うので、TypeScript 5の設定のままでは strict が既定で有効になる、types が空になるといった既定値の違いでエラーが増えることがあります。
checkスクリプトとの衝突と--no-script
package.json に check という名前のスクリプトがあると、bun check は型チェックではなくそのスクリプトを実行します。1.4.4で "check": "echo MY_CHECK" を置いて実行すると、MY_CHECK を表示して終了コード0で終わりました。リントや整形に check という名前を付けているリポジトリでは、型チェックが走ったつもりで素通りします。bun check --no-script にすればスクリプトがあっても型チェッカーが動きます。bun init が作るスクリプト名は check ではなく typecheck です。bun checkの公式ドキュメントは、型チェッカーを持たない古いBun(node_modules/.bin に残った旧版を含む)では "check": "bun check" が自分自身を終わりなく呼び続けるとして、チーム全員が更新するまでは typecheck という名前にするよう勧めています。
AIエージェントから実行したときの出力形式
公式ドキュメントには、環境変数 AGENT=1・CLAUDECODE=1・REPL_ID=1 のいずれかがあると、bun check がエラーごとにタグで囲んだブロックを色なしで出すと書かれています。1.4.4で CLAUDECODE=1 だけを付けて実行すると、出力は <error file="bad.ts" line="1" column="7" code="TS2322"> で始まる形に変わりました。端末でないときの通常の出力は tsc --pretty false と同じ1エラー1行の形式です。Claude Codeの中で動かしたCIスクリプトが tsc 形式の出力を正規表現で拾っている場合、エラーを数え損ねるので注意してください。
bun fmtによるコード整形
bun fmt は1.4.4(2026年10月22日公開)で入ったPrettier互換のフォーマッターです。1.4.4のリリースノートによるとPrettierの移植で、JavaScriptとTypeScriptの整形はoxc_formatterの移植です。.prettierrc や .editorconfig、.prettierignore をそのまま読みます。JavaScript・TypeScript・JSXのほか、CSS・HTML・Vue・Svelte・JSON・YAML・Markdownなども対象です。
printf 'const x={a:1,b:[1,2,3]}\nexport default x\n' > ugly.ts
bun fmt --check
# ugly.ts
# 1 file needs formatting. Run bun fmt to fix it.(終了コード1)
bun fmt
# Formatted 1 file, 5 unchanged
cat ugly.ts
# const x = { a: 1, b: [1, 2, 3] };
# export default x;
公式ドキュメントによれば、--check の終了コードは整形が必要なファイルがあれば1、無ければ0、構文エラーなどで失敗すれば2です。CIでは bun fmt --check を置きます。コミット前に整形するなら、ステージしたファイルだけを整形して再ステージする bun fmt --staged があり、整形だけならlint-stagedを入れずに済みます。ただし、同じファイルにステージ済みと未ステージの変更が混在し、ステージ済みの内容に整形が必要な場合は、書き換えず終了コード2で停止します。オプションは bunfig.toml の [fmt] に書け、bun fmt --init がその節を作ります。
fmtスクリプトとの優先順位とbun lint
bun check と同じく、package.json に fmt というスクリプトがあると bun fmt はそちらを実行します。1.4.4で "fmt": "echo SCRIPT-FMT" を置くと、整形せずに SCRIPT-FMT を表示しました。組み込みのフォーマッターを確実に動かすには bun fmt --no-script を使います。なお bun format は組み込みではなく、format スクリプトを実行します。
リンターは1.4.4でも組み込まれていません。lint スクリプトが無いプロジェクトで bun lint を実行すると、error: Script not found "lint" と表示して終了コード1で終わります。ESLintやBiomeを lint という名前でscriptsに登録しておけば、bun lint で呼び出せます。
Bunのコマンド一覧|npm・npxとの対応
1.4.4の bun --help に載っている主なサブコマンドです。
| コマンド | 役割 | npmでの近いコマンド |
|---|---|---|
| bun install(bun i) | package.jsonの依存を入れる | npm install |
| bun add(bun a) | 依存を追加する | npm install パッケージ名 |
| bun remove(bun rm) | 依存を外す | npm uninstall |
| bun update | 古い依存を更新する | npm update |
| bun outdated | 更新できる依存を表示する | npm outdated |
| bun audit | 既知の脆弱性を調べる | npm audit |
| bun why | 依存が入っている理由を示す | npm explain |
| bun run | ファイルかscriptsを実行する | npm run |
| bunx(bun x) | パッケージのCLIを実行する | npx |
| bun check | 型チェックする | なし(tsc) |
| bun fmt | コードを整形する | なし(Prettier) |
| bun test | テストを実行する | npm test(Jest等) |
| bun build | バンドルする | なし(esbuild等) |
| bun create(bun c) | テンプレートから作る | npm create |
| bun upgrade | Bun本体を更新する | なし |
ほかに dedupe・prune・link・unlink・publish・patch・pm・info・exec・repl があります。bun uninstall パッケージ名 も受け付けますが、実行すると bun remove として動き、依存を外すだけです。Bun本体は消えません。ファイルを保存するたびに再起動する --watch、プロセスを保ったまま再読み込みする --hot、package.jsonのscriptsをNode.jsではなくBunで動かす --bun は、bun run と組み合わせて使うフラグです。
Bun.fileとnode:fsによるファイル操作
import { readFile } from "node:fs/promises";
const file = Bun.file("package.json");
console.log(file.size); /* バイト数 */
const pkg = await file.json();
console.log(pkg.name);
await Bun.write("out.txt", "hi");
console.log(await Bun.file("out.txt").text()); /* hi */
const text = await readFile("package.json", "utf8");
console.log(text.length > 0);
Bun.file() が返す BunFile は遅延読み込みで、作成した時点ではディスクから読み込まず、.text()・.json() を呼んだ時点で中身を取得します。書き込みは Bun.write() です。node:fs も使えます。公式の互換表では node:fs は「Fully implemented」で、Node.jsのテストスイートの98%が通る一方、Stats オブジェクトに atimeInstant などTemporal.Instantを返すゲッターが無いと注記されています。SQLiteは Bun.sqlite ではなく、import { Database } from "bun:sqlite" で読み込みます(1.4.4で typeof Bun.sqlite は undefined)。
Bun本体のバージョン確認・更新・アンインストール
bun --version # 1.4.4
bun --revision # 1.4.4+38afee6c8(ビルド元のコミットまで表示)
bun upgrade # curl・PowerShellで入れた場合
bun upgrade --canary # mainの最新コミットから作られる未検証版へ
bun upgrade --stable # 安定版へ戻す
canaryはmainへのコミットごとに自動で公開される未検証のビルドで、クラッシュレポートを自動送信します。本番環境では安定版を使ってください。1.4系は1.4.0(2026年8月20日)、1.4.1(9月4日)、1.4.2(9月5日)、1.4.3(10月10日)、1.4.4(10月22日)と出ています。各版の変更点はBun 1.4の解説記事を参照してください。
本番とCIでBunの版を固定する方法
公式のインストールドキュメントが挙げる更新チャネルはstableとcanaryの2つだけで、Node.jsのようなLTSはありません。npmレジストリの公開履歴を見ても、1.3系は1.3.14(2026年5月13日)が最後で、1.4.0の公開後に1.3系の修正版は出ていません。旧系列への修正提供を前提にせず、長く動かすシステムでは使用する版を固定し、セキュリティ修正を確認しながら更新時期を決めます。
# インストーラーにタグを渡す(macOS・Linux)
curl -fsSL https://bun.com/install | bash -s "bun-v1.4.4"
# GitHub Actions(oven-sh/setup-bun)
- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.4.4"
setup-bunのREADMEによると、版を指定しなければ package.json の packageManager("[email protected]" の形)、次に engines.bun を読み、どちらも無ければ latest を入れます。bun-version-file には package.json・.bun-version・.tool-versions を渡せます。
注意したいのは、これらの指定を読むのはsetup-bunで、Bun本体ではない点です。1.4.4で "packageManager": "[email protected]" と "engines": { "bun": ">=1.5.0" } を書いた package.json に対して bun install を実行すると、警告も出さずに終了コード0で完了しました。開発者の手元では版の食い違いに気づけないので、CIとDockerイメージ(oven/bun:1.4.4 のようなタグ)で版を揃え、bun --revision の出力をビルドログに残しておくと、不具合の切り分けで版を追えます。
アンインストールは、入れた経路に合わせて次のコマンドを使います。
# curlスクリプトで入れた場合(macOS・Linux)
rm -rf ~/.bun
# Windows(PowerShellスクリプトで入れた場合)
powershell -c ~\.bun\uninstall.ps1
# パッケージマネージャーで入れた場合
brew uninstall bun
npm uninstall -g bun
scoop uninstall bun
rm -rf ~/.bun はバイナリと、~/.bun/install/global に入るグローバルパッケージをまとめて消しますが、シェルの設定ファイルに追記したPATHの行は残ります。~/.zshrc などから BUN_INSTALL の2行も削除してください。
よくある質問
Bunの読み方は?
英単語の bun と同じ綴りで、英語の発音に沿って「バン」と読むのが一般的です。「Bun.js」と書かれることもありますが、公式の名称はBunです。
brew install bun と brew install oven-sh/bun/bun はどちらを使えばよいですか?
公式ドキュメントが案内しているのは brew install oven-sh/bun/bun です。brew install bun はhomebrew-coreのformulaで、Intel Macなどbottleのない環境ではソースからビルドします。
BunはV8エンジンで動いていますか?
動いていません。BunのエンジンはSafari由来のJavaScriptCoreで、公式READMEも「powered by JavaScriptCore」と明記しています。process.versions.v8 に版らしい文字列が入るのは、Node.js向けライブラリとの互換のためです。
bun installは既存のnpmプロジェクトで使えますか?
使えます。package-lock.json があれば読み取って bun.lock に移行し、node_modules に展開します。依存パッケージの postinstall は、trustedDependencies を指定した場合はそのリストのパッケージだけが実行対象です。省略した場合は、npm由来のパッケージに既定許可リストが適用されます。
Bunを完全に削除するには?
curlで入れた場合は rm -rf ~/.bun を実行したうえで、シェル設定ファイルに追記したPATHの行を消します。Homebrewやnpmで入れた場合は、それぞれ brew uninstall bun・npm uninstall -g bun を使います。bun uninstall は依存パッケージを外すコマンドで、Bun本体は削除しません。