npxは、npmに同梱されているコマンドで、パッケージを依存関係に加えないまま取り寄せて実行します。npm v7.0.0で中身が書き換えられ、現在はnpm execを呼ぶ入口に整理されました。この記事では、npxがローカルのnode_modulesとnpmキャッシュをどの順で見るのか、バージョンを固定する書き方、--packageや-cの使いどころ、pnpmのpnx・bunx・yarn dlxとの挙動差、そしてCIから裸のnpxを外す手順までを扱います。バージョンと仕様は2026年9月23日時点の公式ドキュメントとレジストリの実測に基づきます。
まとめ:npxが実際に何をしているかとCIで固定すべき実行手順の結論
npxは独立したツールではありません。npm v7.0.0でスタンドアロンパッケージが廃止され、npm公式のnpxドキュメントにあるとおり内部はnpm execに置き換わりました。手元でnpxと打つ行為は、npmに実行を代行させる行為と同じです。
動きの核となるのは、パッケージの解決順序です。まずローカルに入っているパッケージの実行ファイルを探し、見つからなければレジストリから取り寄せてnpmキャッシュ内のフォルダへ展開し、そのフォルダをPATHに足してから実行します。つまり同じコマンドでも、node_modulesの状態次第で動くものが変わります。
ここがCIで効いてきます。公式ドキュメントは「標準入力がTTYでない場合、またはCI環境が検出された場合は--yesが仮定される」と明記しています。手元では確認プロンプトが出るのに、CIでは無言でレジストリから取得して実行される構造です。バージョンを書かないnpxをCIに置くと、その日のレジストリの中身がそのままビルドに入ります。
結論はひとつです。手元での使い捨てはnpxのままでよく、CIとリリース手順に入るものはdevDependenciesへ固定してnpm execで呼ぶ。2026年9月23日時点でnpmレジストリのlatestタグが返すnpmは12.1.0で、npxはそのnpm本体の一部として配られています。
npm v7で書き換えられたnpxの実体とnpm execとの対応関係
npxという名前は2017年から存在しますが、中身は一度入れ替わっています。この経緯を知らないまま古い記事のオプションを試すと、削除済みのフラグでつまずきます。
単独パッケージだった旧npxがnpm execのラッパへ変わった経緯
もともとnpxはnpxという独立したnpmパッケージで、npm v5.2.0のリリースノートに「Bundle npx with npm itself.」と記されたとおり、この版から同梱される形で配布されていました。npm公式ドキュメントは、npm v7.0.0でnpxが書き直され、スタンドアロンパッケージは廃止されてnpm execコマンドを使うようになったと記述しています。実装の履歴はnpm CLIのGitHubリポジトリで追えます。
この書き換えで消えたオプションがあります。--no-install、シェルフォールバック、--npm、--node-argと-n、そして--ignore-existingです。2020年より前の解説記事はこれらを前提に書かれているため、そのまま打つと未知のオプションとして弾かれます。npm本体の仕組みはnpmとは?CLIとレジストリの役割・package.jsonとv12の変更点を解説で整理しています。
npxとnpm execでフラグの位置が変わる理由と書き分けの基準
両者は同じ処理に降りますが、引数の解釈だけが違います。npm exec のドキュメントは「npxバイナリ経由で実行する場合、すべてのフラグとオプションは位置引数より前に置かなければならない」「npm execではダブルハイフン--でnpmのパースを抑止できる」と書き分けています。
実務上の判断はこうです。実行するコマンド側にもオプションを渡したいならnpm execを選びます。npxでnpx tsc --noEmitと書くと、--noEmitがnpx側のフラグとして読まれる余地のある書き方です。npm exec -- tsc --noEmitなら区切りが明示され、解釈のぶれが消えます。なおnpm execにはnpm xという別名もあります。
npxがパッケージを探す順序とnpmキャッシュへの一時展開の流れ
「インストールせずに実行できる」という説明は半分しか当たっていません。実際には取り寄せた実体がディスクに置かれます。どこに何が置かれるかを押さえると、後述のトラブルの切り分けが速くなります。
ローカルのnode_modules優先でPATHが組まれる解決順序
npm公式は、--packageで指定されたパッケージが、ローカルにインストール済みのパッケージ実行ファイルとともに実行コマンドのPATHへ提供されると説明しています。要求されたパッケージがローカルの依存関係に無い場合は、npmキャッシュ内のフォルダへインストールされ、そのフォルダがPATH環境変数に追加されます。
# ローカルに入っていれば node_modules/.bin のものが動く
npx tsc --version
# 入っていなければレジストリから取り寄せて実行される
npx [email protected] tsc --version
バージョン指定を書かないパッケージ名は、ローカルプロジェクトに存在するバージョンと照合されます。手元にv4が入っていれば、実行されるのはレジストリの最新版ではなくv4です。この挙動があるため、npxで動かした結果を「最新版の動作」として報告すると食い違いが起きます。土台となるランタイム側の版の選び方はNode.jsとは?仕組み・版の選び方・標準機能で動かす手順を実装目線で解説にまとめています。
レジストリ取得時に出るプロンプトとCI環境で–yesが仮定される条件
ローカルに無いパッケージを要求すると、npmはインストール前に確認プロンプトを出します。この確認プロンプトは--yesまたは--noで抑止可能です。--yesは許可側、--noは許可しない側に応答を固定します。
見落としやすいのはここからです。公式ドキュメントは「標準入力がTTYでない場合、またはCI環境が検出された場合は--yesが仮定される」と記しています。GitHub ActionsでもGitLab CIでも、確認は出ません。パイプラインに書いたnpx なにかは、誰の承認も経ずにレジストリから落ちてきて走ります。
npx実行時に指定できるバージョンと–packageで環境を組む書き方
npxの構文は4パターンに整理されています。npx -- <pkg>[@<version>] [args...]、npx --package=<pkg>[@<version>] -- <cmd> [args...]、npx -c '<cmd> [args...]'、npx --package=foo -c '<cmd> [args...]'の4つです。
パッケージ名とコマンド名が違う場合に–packageで橋渡しする書式
npmのパッケージ名と、そのパッケージが公開する実行ファイル名は一致しません。typescriptパッケージが出す実行ファイルはtscです。名前が違うときは--packageで取り寄せ先を指定し、実際に叩くコマンドを後ろに書きます。
# パッケージ名と実行バイナリ名が違うときは --package で指定する
npx --package=typescript -- tsc --version
# 複数パッケージを同じ環境に載せて 1 つのコマンドを動かす
npx --package=yo --package=generator-node -c "yo node"
--packageは複数回指定できます。公式ドキュメントによると、これは指定した全パッケージが利用可能な環境でコマンドを実行するためのオプションです。ジェネレータ系のように本体とプラグインが別パッケージへ分かれているツールで効きます。npxでCLIを配るツールの実例はskills.shとは?Vercel製エージェントスキルCLIの使い方とnpxコマンド一覧【2026年最新】で扱っています。
-cでシェル経由の実行に切り替えたときに変わる引数の渡り方と注意点
-c(--call)は、渡した文字列をシェルスクリプトとして実行します。パイプやリダイレクトを含む一行を丸ごと動かしたいときの入口です。引用符で囲んだ中身はnpmのオプション解析を通らないため、実行するコマンド側のフラグをそのまま書けます。
ただしシェルを経由する分、実行時には環境差の影響も受ける仕組みです。Windows のコマンドプロンプトとPOSIXシェルでは引用符の扱いが変わり、同じ一行が別々に解釈されます。チーム全員のOSが揃っていない案件では、-cに長い一行を書くのではなく、package.jsonのscriptsへ逃がすほうが再現します。
npx・npm exec・pnx・bunx・yarn dlxの挙動差と選び方の基準
一時実行の入口は、いまや各パッケージマネージャが持っています。名前が違うだけで同じと考えると、バージョン固定の手段を取り違えます。
pnpmのpnxとdlxとpnpxが同じコマンドの別名になっている現状
pnpmの公式ドキュメントは、レジストリからパッケージを取得し、依存関係としてインストールせずにホットロードして実行するコマンドとしてpnxを掲載しています。注目すべきはエイリアス欄で、pnpm dlxとpnpxが同じコマンドの別名として並びます。pnx自体はv12.0.0-rc.6で追加されました。
つまり古い記事のpnpm dlxはいまも通ります。移行の必要はありません。ただしドキュメントのURLは/cli/dlxから/cli/pnxへ移っているため、社内手順書に旧URLを貼っている場合はリンク先の差し替えが要ります。pnpm本体の仕組みはpnpmとは?共有ストアの仕組みとv12のRust実装・モノレポ運用を解説を参照してください。
bunxがローカル導入済みパッケージで速いと公式が示す根拠と条件
Bunの公式ドキュメントはbunxをbun xのエイリアスと定義し、npxやyarn dlxに相当するものだと位置づけています。速度については「ローカルにインストール済みのパッケージについては、bunxはnpxよりおよそ100倍速い」と書かれています。この条件付きが肝心です。レジストリから毎回取り寄せる使い方では、ネットワークが支配的になります。
実行ランタイムの扱いにも、npxとの違いがあるのです。bunxは既定でshebangを尊重し、#!/usr/bin/env nodeが書かれていればNode.jsで動きます。--bunを付けるとBunのランタイムで強制実行され、このフラグはパッケージ名より前に置く必要があります。
4つのコマンドを比較して選ぶときに見る取得元と版の固定手段の差
選定で見るべきは、ローカル優先かどうかと、版をどう固定するかの2点に絞られます。
| コマンド | 提供元 | ローカル優先 | 版の固定 |
|---|---|---|---|
| npx | npm同梱 | する | pkg@version |
| npm exec | npm同梱 | する | lockfile併用 |
| pnx / pnpm dlx | pnpm | しない | pkg@version |
| bunx | Bun同梱 | する | pkg@version |
| yarn dlx | Yarn | しない | pkg@version |
Yarnが提供するyarn dlxも、依存に入れずに取り寄せて実行する方針を明示しています。この違いが表れるのは、実務でコマンドを実行する場面です。ローカル優先のnpxやbunxは「手元の版が動いてしまう」事故が起き、ローカルを見ないpnxやdlxは「毎回取りに行って遅い」代わりに結果が揃います。どちらが良いかは案件によりますが、CIで走らせる前提なら後者の考え方に寄せるのが素直です。
受託開発の現場でnpxを裸で実行してはいけない場面とCIでの固定手順
ここからは判断を書きます。npxは手元の道具としては優秀ですが、納品物のビルド手順に置くべきものではありません。理由は好みではなく、再現性とサプライチェーンの2点にあります。
バージョン未指定のnpxがCIで再現性とサプライチェーンを壊す条件
バージョンを書かないnpx pkgは、ローカルに無ければレジストリの最新版を取りに行きます。CI環境では--yesが仮定されるため、確認は挟まりません。先月成功したビルドが今月落ちる原因がここに入り込みます。lockfileはdependenciesを固定しますが、npxが直接取り寄せたパッケージはlockfileの外側です。
もうひとつは取り違えです。パッケージ名を1文字打ち間違えたコマンドがCIにマージされると、そのまま別人のパッケージがインストールされて実行されます。npmのライフサイクルスクリプトはv12で既定ブロックへ変わりましたが、実行ファイルそのものは動く仕組みです。コードレビューでコマンド文字列まで読む体制が無い現場では、この経路が抜けます。
devDependenciesとnpm execへ寄せてCIから不確実性を外す手順
直し方は短いです。CIで使うツールをdevDependenciesへ入れ、lockfile込みでコミットし、実行はnpm execに寄せます。
# 開発依存として版を固定して入れる
npm install --save-dev [email protected]
# CI では lockfile どおりに入れてから npm exec で実行する
npm ci
npm exec -- tsc --noEmit
この形にすると、実行されるバイナリを決めるのはコミットしたlockfileです。npm ciはlockfileと不一致があれば失敗するため、依存の差し替えがビルド失敗として表に出ます。npxのままCIを回して「たまに落ちる」状態を抱えている案件は、まずこの置き換えから着手すると切り分けが進みます。開発環境とCIの整備を外部と組んで進める場合は、業務用・Webアプリ開発の相談窓口から現行のビルド構成ごと見てもらう形が近道です。
npxをそのまま使ってよい場面と受託案件で見送るべき条件の線引き
使ってよい場面は明確です。初回のプロジェクト生成、ツールの試用、手元での一回限りの調査。いずれも結果が成果物に残らず、失敗しても捨てられます。
見送るべき条件も同じくらい明確です。CIやCDのパイプライン、納品する手順書、定期実行されるスクリプト、そして複数人が同じ結果を得る前提の作業。この4つに入るなら、npxは使いません。判断に迷ったら「このコマンドの結果が来月も同じである必要があるか」を問うてください。必要があるなら固定側です。
npxが遅い・古い版が動くときに確認するキャッシュと解決順序の要点
npx絡みの不具合の大半は、解決順序かキャッシュのどちらかに起因します。原因の当たりを付ける順番を決めておくと、調査が5分で済みます。
古い版が実行され続けるときにnpmキャッシュと解決順序を疑う手順
最新版を指定したつもりが古い挙動のままなら、まずローカル優先の解決順序を疑います。npx pkg --versionで実際に動いている版を出し、node_modulesに同名パッケージが入っていないか確認します。同名パッケージが入っていれば、実際に動いているのはそのパッケージです。
# npx が展開するキャッシュの置き場所を確認する
npm config get cache
# 取り寄せたキャッシュを捨てて取り直す
npm cache clean --force
キャッシュの位置は、環境変数や設定ファイルを通じて変更可能です。設定の優先順位と各項目の既定値はnpmのconfigドキュメントに一覧があります。CIでキャッシュディレクトリを共有している構成では、ジョブをまたいで古い実体が残ります。
コマンドが見つからないエラーでパッケージ名と綴りを疑う切り分け
「command not found」が出る典型は、パッケージ名と実行ファイル名の取り違えです。npx typescriptは動きません。typescriptパッケージが公開する実行ファイルはtscだからです。前述の--packageで橋渡しするか、実行ファイル名を直接指定します。
もうひとつは綴り違いによる別パッケージの取得です。存在しない名前ならエラーで止まりますが、似た名前が実在すると何かが動いてしまいます。npmレジストリのページでパッケージの週間ダウンロード数と公開者を確認してから実行する習慣を付けると、この経路は塞げます。
よくある質問
npxの位置づけと使い分けについて、検索で繰り返し見かける質問に答えます。
npxとnpmコマンドは何が違い、どちらを先に覚えるべきですか?
npmは依存パッケージの取得と記録を担い、npxは取得したものを実行する入口です。npm installでpackage.jsonとlockfileに記録が残るのに対し、npxは依存関係に加えないまま実行します。先に覚えるのはnpmです。package.jsonとlockfileの役割を理解しないままnpxを使うと、どの版が動いているのか追えなくなります。
npxを使うためにnpmとは別にインストールする必要はありますか?
必要ありません。npm 5.2.0以降はnpmに同梱されており、npm v7.0.0で独立パッケージは廃止されました。Node.jsを入れればnpmが入り、npmが入ればnpxも使えます。むしろ古い独立版のnpxパッケージがグローバルに残っていると、同梱版より先に見つかって古い挙動になります。動作が説明と食い違うときは、その残骸を疑ってください。
npxで実行したパッケージは端末のどこかに残り続けるのですか?
残ります。ローカルの依存に無いパッケージはnpmキャッシュ内のフォルダへインストールされ、そのフォルダがPATHへ追加されて実行されます。「インストールせずに実行する」という表現は、プロジェクトの依存関係に加えないという意味であって、ディスクに何も置かないという意味ではありません。置き場所はnpm config get cacheで確認できます。
npxで実行するパッケージのバージョンを固定するにはどう書きますか?
npx [email protected] cmdのようにパッケージ名へ直接バージョンを付けます。[email protected]の形でもバージョンを指定可能です。逆に版を書かない場合、ローカルに同名パッケージがあればその版と照合され、無ければレジストリ側の版が使われます。CIで走らせるコマンドは、この2択を運任せにせず必ず版まで書いてください。
CIやCDのパイプラインでnpxを使うと危険だと言われるのはなぜですか?
公式ドキュメントが示すとおり、標準入力がTTYでない場合やCI環境が検出された場合は--yesが仮定され、インストール確認が出ません。版を書かなければ実行のたびにレジストリの内容が変わり得ます。lockfileの管理外で外部コードが取得されて走る構造になるため、再現性とサプライチェーンの両面で穴になります。devDependenciesへ固定してnpm execで呼ぶ形に置き換えてください。
関連記事
- npmとは?CLIとレジストリの役割・package.jsonとv12の変更点を解説:npxを同梱するnpm本体の構成とv12の破壊的変更を扱っています
- Node.jsとは?仕組み・版の選び方・標準機能で動かす手順を実装目線で解説:npmとnpxの土台となるランタイムの版選定を解説しています
- pnpmとは?共有ストアの仕組みとv12のRust実装・モノレポ運用を解説:pnxの提供元であるpnpm本体の仕組みを比較できます
- vltとは?npm互換パッケージマネージャの1.0到達点と移行判断を実装者向けに解説:npm互換を掲げる新興ツールの到達点と移行判断をまとめています
- skills.shとは?Vercel製エージェントスキルCLIの使い方とnpxコマンド一覧【2026年最新】:npxで配布されるCLIツールの実例として参照できます