bunxはBunのパッケージランナーであり、bun xのエイリアスです。グローバルインストールなしにnpmからパッケージのバイナリをダウンロードして実行します。これはnpxやyarn dlxと同じ役割を果たします。
1日に何度も実行するスキャフォールドコマンドでnpxの起動を待ち続けた経験があるなら、その小さな遅延こそがbunxが解消しようとしているものです。日常的にnpx create-next-appやnpx shadcn@latestを使っているなら、Bunをインストールした後はbunxがほぼそのまま代替として使えます。ただし、切り替える前に理解しておくべき点が2つあります。ランタイムに関する注意点(--bunフラグ)と、文字列npxをハードコードしているツールへの対処です。
この記事では、bunxの概念モデルを解説します。bunxとは何か、パッケージをどのように解決するか、なぜnpxより起動が速いのか、--bunフラグが実際に何をするのか、そしていつ使うべきかの判断基準を説明します。
重要なポイント
bunxはBunのパッケージランナーでありbun xのエイリアスです。npxやyarn dlxと同様に、グローバルインストールなしにnpmパッケージのバイナリを実行します。npxと同様に、bunxはまずローカルにインストールされたパッケージを確認し、見つからない場合のみnpmから自動インストールします。どちらのツールも解決済みパッケージをキャッシュするため、本質的な違いはBunの低オーバーヘッドなランタイム上で動作し、Bun独自のグローバルキャッシュにパッケージを保存する点にあります。--bunフラグは、Vite、Next、PrismaなどのCLIをNodeの代わりにBunランタイム上で実行させるものであり、実行ファイル名の前に記述する必要があります(bunx --bun vite)。- 一度限りのスキャフォールディングやCLIツールには
bunxを使い、ツールがnpxという文字列をハードコードしているか、Bunのランタイムで動作しない場合のみnpxを使い続けてください。 alias npx=bunxのようなシェルエイリアスは対話的な操作では機能しますが、非対話的な起動では無効です。代わりに実際の実行ファイルをPATHに配置してください。
bunxとは何か
bunxはnpmパッケージの実行ファイルをグローバルインストールなしに実行するもので、Bunに自動的に同梱されています。公式ドキュメントによると、bunxはbun xのエイリアスであり、bunのインストール時に自動的にインストールされます。npxやyarn dlxに相当するBunのツールです。
呼び出し方法はnpxと同一です:
# npx
npx create-next-app@latest my-app
# bunx
bunx create-next-app@latest my-app
パッケージはpackage.jsonの"bin"フィールドにバイナリを宣言します。bunx <package>はそのバイナリを見つけて実行します。バージョンの固定方法もnpxと同じです。パッケージ名に@バージョンを付加するだけです:
bunx uglify-js@3.14.0 app.js
bunx shadcn@latest add button
バイナリ名がパッケージ名と異なる場合は、-p/--packageでパッケージ名を明示的に指定してからバイナリ名を記述します:
bunx -p @angular/cli ng new my-app
bunxはどのようにパッケージを解決するか
Discover how at OpenReplay.com.
bunxはまずローカルにインストールされたパッケージを確認し、見つからない場合はnpmから自動インストールします。インストールしたものはBunのグローバルキャッシュに保存して再利用します。これはドキュメントに記載されている動作です:「npxと同様に、bunxはまずローカルにインストールされたパッケージを確認し、見つからない場合はnpmから自動インストールします。」解決済みのパッケージはBunのグローバルキャッシュに保存されるため、以降の実行ではダウンロードをスキップできます。
ここで一点訂正しておく価値があります。モダンなnpx(npm v7以降、つまりnpm exec)は実行のたびにダウンロードして破棄するわけではありません。こちらもユーザーごとの永続的なキャッシュを持ち、繰り返し実行時にパッケージを再利用します。つまり「npxは捨て、bunxは保持する」という違いではなく、どちらもキャッシュします。本質的な違いはキャッシュの場所(Bunのグローバルストア)と、呼び出しから実行までのランタイムオーバーヘッドにあります。
bunxがnpxより速い理由
bunxの起動が速い理由は、Nodeを起動する代わりにBunのランタイム上で動作するためです。BunはNodeではなくJavaScriptCore(Safariのエンジン)上に構築されており、パッケージランナーの起動にかかる固定コストが低くなっています。Bunチームはこの利点を具体的な数値で示しています。bunxの導入時には「npmから実行ファイルをインストールして実行する速度がnpxの100倍」と謳っており、この数値はドキュメントで特にローカルにインストール済みのパッケージの場合に言及されています。
この数値はBunが公表している、ウォームキャッシュ(すでにインストール済み)の場合の主張として捉えてください。普遍的なベンチマークではありません。一般化できる部分は起動速度の話です。コールドスタートのCLI呼び出し(プロジェクトのスキャフォールディングで1日に何度も行う操作)において、Bunの低いプロセス起動オーバーヘッドが時間を節約します。初回インストールでネットワークアクセスが必要な場合は、どちらのツールもダウンロードコストを支払うため、速度差はインストールスループットと起動時間の差に縮まり、100倍の差にはなりません。
自信を持って言える数値が欲しければ、コールドキャッシュとウォームキャッシュの実行を分けて自分で計測してください:
# ウォームキャッシュ(両方解決済み)とコールドの比較 — 推測せず計測する
hyperfine 'npx cowsay hi' 'bunx cowsay hi'
—bunフラグ
--bunフラグは、Vite、Next、PrismaなどのCLIをNodeの代わりにBunランタイム上で実行させるものです。ツールが通常使用する#!/usr/bin/env nodeシェバンを上書きします。デフォルトでは、Bunはそのシェバンを尊重してファイルを実行するためにnodeプロセスを起動します。--bunはBunのランタイムを代わりに使用するよう指示します:
bunx --bun vite dev
このフラグは位置に敏感です。実行ファイル名の前に記述する必要があります。名前の後に続くものはすべてツール自身の引数としてそのまま渡されます:
bunx --bun my-cli # 正しい — my-cliをBun上で実行する
bunx my-cli --bun # 誤り — --bunがmy-cliに渡される
--bunは、Bunの高速な起動やネイティブTypeScriptサポートを活用するために、ツール自体をBun上で実行したい場合に使用します。ツールがNode固有の動作に依存している場合はデフォルト(フラグなし)のままにしてください。一部のビルドツールやCLIはNodeの内部実装を前提としており、Bunのランタイムに強制的に切り替えると互換性の問題が発生することがあります。実際によく見られる失敗パターンは、bunx toolnameでは正常に動作するCLIが、--bunでランタイムを切り替えると例外をスローするケースです。解決策は通常、--bunを外してNodeのシェバンをそのまま使用することです。
bunxを使うべき場面(とnpxを使い続けるべき場面)
判断基準: 一度限りのスキャフォールディングやCLIツール(bunx create-next-app my-app、bunx prisma migrate、bunx prettier foo.js)にはbunxを使い、ツールやスクリプトが文字列npxをリテラルとしてハードコードしているか、Bunのランタイムで動作しない場合のみnpxを使い続けてください。
| タスク | npx | bunx |
|---|---|---|
| アプリのスキャフォールド | npx create-next-app my-app | bunx create-next-app my-app |
| 開発サーバーの起動 | npx vite | bunx vite |
| マイグレーションの実行 | npx prisma migrate | bunx prisma migrate |
| コンポーネントの追加 | npx shadcn@latest add button | bunx shadcn@latest add button |
| ファイルのフォーマット | npx prettier foo.js | bunx prettier foo.js |
本当の落とし穴は、npxという名前を直接呼び出すツールです。alias npx=bunxのようなシェルエイリアスは対話的にコマンドを入力する場合には機能しますが、シェルエイリアスは対話的シェル内にのみ存在します。非対話的な起動では見えません。npxを内部的に呼び出すツール(例えばuv runが内部で呼び出す場合)はエイリアスをまったく認識しません。
解決策は、npxという名前の実際の実行ファイルをPATHに配置し、npxを起動するあらゆるプロセスがシムに解決されるようにすることです。htdocsのワークアラウンドは3行で済みます:
mkdir -p ~/.local/bin
printf '#!/bin/sh\nexec bunx "$@"\n' > ~/.local/bin/npx
chmod +x ~/.local/bin/npx
~/.local/binがPATHの早い位置に来るようにしてください。これはシェルエイリアスではなくディスク上の実際のファイルなので、非対話的な起動でも解決されます。Bunがインストールされている場合のみBun経由でルーティングするフォールバックが必要なら、--realエスケープハッチ付きの条件付きラッパー関数(nrjdalal氏の実装例を参照)が同じアイデアのより精巧なバリエーションです。
まとめ
bunxは高速なランタイム上のnpxとして捉えてください。解決順序、バージョン固定の構文、コマンドの形式は同じで、起動オーバーヘッドが低くBun独自のストアにパッケージがキャッシュされます。--bunフラグはツール自体をBun上で実行したい場合のみ追加し、実行ファイル名の前に記述し、文字通りのコマンドを要求する少数のツールのために実際のnpxシムをPATHに配置してください。Bunをインストールして、次のスキャフォールドでnpxを1つbunxに置き換えて、自分で速度差を計測してみてください。
よくある質問
bunxはnpxの完全な代替品ですか?
bunxはnpxのほぼ完全な代替品です。コマンドの形式、@バージョンサフィックスによるバージョン固定の構文、ローカル優先の解決順序はすべて同じです。唯一の例外は、内部的に文字列npxをリテラルとして呼び出すツールやスクリプトで、PATHに実際のnpxという名前の実行ファイルを配置しない限りbunxを認識しません。そのような場合、bunxは自動的に代替されません。
bunxはBunを別途インストールしなくても使えますか?
いいえ、bunxにはBunが必要です。bunxはbun xコマンドのエイリアスであり、Bun自体をインストールする際に自動的にインストールされるため、スタンドアロンのbunxパッケージは存在しません。Bunがマシンにインストールされていれば、追加のセットアップなしにbunxが使用できます。Bunがインストールされていない場合、bunxコマンドは存在せず、npxや他のパッケージランナーを使用する必要があります。
bun xとbunxの違いは何ですか?
機能的な違いはありません。bunxは単にbun xのエイリアスであり、2つのコマンドはまったく同じように動作します。どちらもBunのパッケージランナーを呼び出し、グローバルインストールなしにパッケージのバイナリを実行します。好みの方を使用してください。bunxは主に、npmから来た開発者がすぐに認識できる、npxに馴染みのある短い形式として存在しています。
--bunを付けると一部のCLIが壊れるのはなぜですか?
--bunはCLIをNodeの代わりにBunのランタイムに強制的に切り替え、ツールが使用するNodeのシェバンを上書きするためです。一部のビルドツールやCLIはNodeの内部実装に依存しているため、ランタイムを切り替えると互換性の問題が発生します。plain bunx toolnameでは動作するツールが--bunを追加すると例外をスローすることがあります。解決策は--bunを外して、シェバンが意図する通りにツールをNode上で実行させることです。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k