jpm

高速・小型・デフォルトで安全な JavaScript パッケージマネージャー

curl -fsSL https://getjpm.sh | sh

コードは一行残らず Claude Code が書いた。指揮したのは一人のエンジニア。検証にはほかのプロジェクトのテストを使った。

  • ~2 MB単一バイナリ、ランタイムのインストール不要
  • 1.22 sGitHub CI での nuxt のコールドインストール
  • 34 MBGitHub CI で nuxt のインストールに使うメモリ

速度

CI が時間を使うところで速い

実在する 3 つのプロジェクト、4 つのインストールフェーズ、8 つのパッケージマネージャーを、本番の npm レジストリに対して計測しました。GitHub CI では 12 セル中 9 セルで jpm が最速です。残り 3 セルも計測結果のまま掲載しています。

マシン
フェーズ
プロジェクト

キャッシュなし、ロックファイルなし、node_modules なし。

インストールの実時間(短いほど高速)GitHub CI、Linux · nuxt · 591 パッケージ
GitHub CI、Linux, コールド, nuxt · 591 パッケージ
パッケージマネージャー実時間
jpm1.22 s
bun 1.4.21.28 s
pnpm 12.8.11.72 s
aube 2.6.03.00 s
upm 1.3.13.52 s
deno 2.9.67.64 s
yarn 4.18.19.63 s
npm 12.1.018.54 s

ここでは jpm が最速で、npm の 15× の速さです。

実時間の中央値:4 コアの ubuntu-latest(5 回実行)と Defender を有効にした Windows 11(3 回実行)、2026-09-30。CPU 時間を含む全データは docs/benchmarks.md にあります。

はじめる

コマンドひとつで乗り換え

プロジェクトで jpm install を実行します。jpm は今あるロックファイルを、同じバージョンのまま独自の jpm.lock に取り込みます。

  • package-lock.json と npm-shrinkwrap.json(npm 7+)、pnpm-lock.yaml(pnpm 9+)、bun.lock はそのまま引き継がれます。バージョンもツリーも同じで、レジストリへの問い合わせもありません。
  • yarn.lock は yarn 1 でも yarn 2 以降でも、yarn が選んだバージョンをすべて保持します。jpm がレジストリに問い合わせるのは、yarn.lock に記録されていない情報(peer、プラットフォーム、bin)だけです。
  • 古いロックファイルには手を加えません。準備ができたら削除してください。
  • 乗り換え中も CI は動き続けます。jpm.lock をコミットするまでは、jpm ci と jpm install --frozen-lockfile が古いロックファイルをそのまま使ってインストールします。
  • ワークスペース、pnpm-workspace.yaml、カタログ、オーバーライドと resolutions、パッチも読み込みます。

古い形式や最新でないロックファイルなどについては docs/migrating.md を参照してください。

$ cd your-project
$ jpm install   # package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock を読み込み → jpm.lock を書き出す

軽量

存在を忘れるほど小さい

背後に何も必要としない単一バイナリ、メモリをほとんど使わないインストール、そして各ファイルを一度だけ保存するストア。

すべての数字が jpm に有利なわけではありません。npm と yarn は圧縮された tarball を保持するため、キャッシュはそちらのほうが小さくなります。jpm はファイルを展開した状態で保持し、すぐにリンクできるようにしています。

GitHub CI、Linux、2026-09-30。バイナリサイズは README に記載の概数です。

バイナリサイズ(概算)
バイナリサイズ(概算)
jpm~2 MB
pnpm~60 MB
bun~80 MB
aube~150 MB
ピークメモリ、nuxt の ci インストール
ピークメモリ、nuxt の ci インストール
jpm34 MB
bun89 MB
pnpm184 MB
npm387 MB
nuxt のコールドインストール後のディスク使用量(node_modules とストア)
nuxt のコールドインストール後のディスク使用量(node_modules とストア)
jpm244 MB
bun261 MB
pnpm290 MB
npm443 MB
next のコールドインストール後の CI キャッシュ
next のコールドインストール後の CI キャッシュ
npm194 MB
yarn328 MB
jpm347 MB
pnpm433 MB
bun466 MB

ストレージ

ファイルは一度だけ保存。パッケージは一度だけビルド。

jpm はマシンごとに 1 つのストアを持ち、各パッケージのディレクトリを一度だけビルドして、それを使うすべてのプロジェクトで共有します。再インストールは、ほとんどリンクを張るだけです。

  1. コンテンツアドレス型ストア

    各 tarball は integrity を検証したうえで、~/.jpm/store に一度だけ展開されます。すべてのファイルはハッシュをキーに、読み取り専用で一度だけ保存されます。

  2. グローバル仮想ストア

    各パッケージはエントリとして一度だけビルドされます。エントリ名は name@version で、依存がある場合は依存グラフの短いダイジェストが付きます。ファイルはストアからハードリンクされ、依存はその隣にリンクされるので、宣言したものしかインポートできません。

  3. あなたの node_modules

    プロジェクトの node_modules はこれらのエントリにリンクします。ウォームインストールで作るのは、このわずかなリンクだけです。GitHub CI 上の nitro なら 4 ms。

  4. ほかのすべてのプロジェクト

    同じマシン上の次のプロジェクトも、同じエントリにリンクします。何も変わっていなければ、再実行インストールはいくつかのリンクを確認するだけで、1–2 ms で終わります。

~/.jpm/storeファイル(ハッシュ単位)3fa19c07e4b271d80b5ec6a3ハードリンク~/.jpm/store/v1/linksエントリ(一度だけビルド)[email protected]node_modules/debugnode_modules/ms[email protected]node_modules/msapp-one/app-two/node_modules/debugnode_modules/debugリンク

Next.js と Nuxt:プロジェクト内に配置

Next の Turbopack はプロジェクト外のものをコンパイルせず、Nuxt は宣言していないパッケージをインポートします。そのため next や nuxt に依存するプロジェクトでは、jpm は代わりに node_modules/.jpm にエントリをビルドします。ストアからハードリンクする点は変わりません。

node_modules/next -> .jpm/[email protected]…/node_modules/next
node_modules/.jpm/[email protected]…/node_modules/next/
node_modules/.jpm/[email protected]/node_modules/react/

全体像はこちら:docs/how-it-works.md。

セキュリティ

デフォルトで安全

安全な設定は、頼まなくても最初から有効です。それを緩めるかどうかは、パッケージやクローンしたリポジトリではなく、あなたが自分の設定で決めることです。

  • インストールスクリプトはあなたの承認待ち

    npm マルウェアの大半が実行される経路である依存パッケージのインストールスクリプトは、そのパッケージとバージョンを jpm approve するまで実行されません。新しいバージョンには改めて承認が必要です。

  • 新バージョンは 1 日待つ

    公開から 1 日以内のバージョンは選ばれません(min-release-age)。ツリーの奥深くにあるパッケージがそのバージョンを厳密に固定していても同じなので、乗っ取られたリリースが固定指定に便乗して入り込むことはできません。

  • 想定外の取得元はなし

    公開済みパッケージは、git や tarball の依存も、自身の外にあるパスも取り込めません。コードの取得元を決められるのは、あなたのプロジェクトとそのワークスペースだけです。

  • 見える前に検証

    すべてのパッケージは、そのファイルがプロジェクトから見えるようになる前に、ロックファイルの integrity と照合されます。

  • ロックファイルに秘密情報なし

    認証情報が jpm.lock に書き込まれることはありません。トークンは .npmrc に残り、パスワードを含む git url は拒否されます。

  • クローンしたリポジトリに基準は下げられない

    プロジェクト自身の .npmrc では、TLS チェックの無効化、CA やプロキシの差し替え、リリース経過期間の緩和はできません。jpm はそこにあるこれらの設定を無視し、警告で名前を挙げます。

  • 独自の TLS、OpenSSL は不使用

    jpm は独自のコードで TLS を実装しており、Project Wycheproof と各 RFC のテストベクターで検証しています。証明書は Mozilla のルート証明書とシステムのルート証明書で検証します。

  • ランタイムは署名で検証

    パッケージが要求する Node.js ランタイムは、リリースの SHASUMS256.txt と照合され、その署名が Node のリリース鍵と一致した場合にのみ信頼されます。

  • 攻撃対象が少ない

    ~2 MB の単一バイナリで、インストールが必要なランタイムも独自の依存ツリーもありません。あなたとレジストリの間にあるコードが、それだけ少なくなります。

デフォルトで安全でも、サンドボックスではありません。承認したスクリプトはあなたの権限で実行されます。詳しくは docs/install-scripts.md と docs/configuration.md を参照してください。

ストーリー

Claude Code が書き、ほかのプロジェクトのテストで検証した。

きっかけは Syntax ポッドキャストのあるエピソードでした。そこでは upm がほかより速くて小さいと紹介されていました。小さいのは、Node.js 上で動くからです。では、Rust に移植して本当に小さくしたらどうなるか? そして、AI が一発で書いたものを CI で信頼できるものにするには、何が必要なのか?

Claude Opus 5.5 で動く Claude Code が、独自の TLS と暗号処理まで含めてすべての行を書きました。判断を下したのは、エンジニア歴 27 年の JT Turner です。Claude が独自 TLS の実装に難色を示したとき、出した条件は「信用していないつもりでテストすること」。だから「動いた」はすべて他者のテストで確かめています。Wycheproof、各 RFC、そして npm、pnpm、yarn、bun のテストスイートです。

決めるのは数字です。HTTP/2 クライアントを作り、GitHub のランナーとデスクトップでベンチマークしたところ、遅くて CPU も多く食うと分かったので、削除しました。

jpm は完璧か? いいえ。完璧なんて存在しません。あるのは「十分」と「素晴らしい」、そして自分の手元にあるのがどちらなのかを知るのに十分なテストです。

JT Turner

ストーリーをすべて読む

jpm を CI で試してみてください。そして、時間がないと思っていたあれを作りに行きましょう。

jpm をインストール