codex cli は rust でつくられてるようですが、インストールは npm install -g @openai/codex だそうです。どういうこと?rust じゃないの?
Rustで書かれていても、配布(インストール)の“器”としてnpmを使うことはよくあります。つまり、
- 中身(実体のCLI)はRust製のネイティブバイナリ
- npmパッケージ(
@openai/codex)は配布・更新・OS判定・バイナリ取得のためのラッパー
という構造です。
典型的にはnpmパッケージ内に少量のNode.jsコードが入っていて、インストール時に次のどれかをします。
- OS/CPU(macOS/Linux/Windows、x64/arm64など)を判定
- その環境向けにビルド済みの Rustバイナリ を
- npmパッケージに同梱している、または
- GitHub Releases等からダウンロードしてくる
codexコマンドとしてパスが通るように配置する(node_modules/.binなど)
ユーザー視点では npm install -g で入るけど、実行されるのはRustの実行ファイル、ということが起きます。
- クロスプラットフォーム配布が楽(多くの開発者が既にNode/npmを入れている)
- アップデートが簡単(
npm update -g) - 依存関係が少なくて済む(Rustツールチェーン不要。ユーザーはビルドしなくてよい)
Rustで作られているのは本体で、npmは配布経路です。
Python製ツールがpipで配られるのと同様に、「実装言語」と「配布に使うパッケージマネージャ」は別物になり得ます。
必要なら、あなたの環境で実際にどのバイナリが動いているか(which codex や、インストール先の実体がnodeスクリプトかネイティブバイナリか)を確認する手順も案内できます。OS(mac/Linux/Windows)を教えてください。
この手法に名前はついてる? またこの手法を使ってる著名なオープンソースを挙げて
はい、だいたい名前が付いています。文脈によって呼び方がいくつかあります。
- npm wrapper / Node wrapper
npmパッケージは薄いJSで、本体は別言語のネイティブバイナリ、という意味で「npmのラッパー」と呼ばれます。 - binary npm package / native binary distribution via npm
「npmでネイティブバイナリを配る」方式全般の言い方。 - platform-specific packages(プラットフォーム別パッケージ) + meta package(メタパッケージ)
例:fooがメタで、foo-darwin-arm64/foo-linux-x64などを依存として切り替える構成。 - postinstall download pattern
postinstallスクリプトでOS/CPU判定→バイナリをダウンロード/配置するパターンをこう呼ぶことがあります。 - (Rust界隈の道具として)cargo-dist 方式
cargo-dist自体は概念名ではないですが、「GitHub Releases等に各OSのバイナリを作り、npm等へ配布する」一連の流れを指してこう言われることがあります。
※厳密に「これが唯一の正式名称」というより、上のどれか(特に npm wrapper / binary npm package)で通じます。
- Go製の高速バンドラですが、npmでは各プラットフォーム用のバイナリを配ります(
@esbuild/darwin-arm64等の形)。 - まさに「npmは配布、実体はネイティブバイナリ」の代表例。
- Rust製の高速トランスパイラ。npm上では
@swc/coreが各OS/CPU向けネイティブバイナリ(N-API)を使います。 - これは「CLIそのものがバイナリ」というより「Nodeから呼ぶネイティブ拡張」ですが、npmでRust成果物を配る代表格です。
- Rust製のformatter/linter。npm経由でCLIを配布します(中身はネイティブ実装)。
- 「npmで入るが、動くのはRustの実行ファイル」という構図の典型。
- Rollup本体はJSですが、パフォーマンスのためにネイティブ部品をnpmで配る構成が入っています(プラットフォーム別パッケージの組み合わせ)。
- “platform-specific packages + meta package” の例として分かりやすいです。
- 画像処理ライブラリ。Nodeアドオン(ネイティブ)をnpmで配り、必要に応じてビルド/取得します。
- これも「npmでネイティブ成果物を配布」の超有名例。
同じ「npmで配る」でも実装が2系統あります。
- A: CLIバイナリ配布型(codex、esbuildのCLIなど)
npmはラッパーで、binとしてネイティブ実行ファイルを置く。 - B: Nodeネイティブ拡張型(swc/sharpなど)
Nodeからrequireされる.node(N-API等)を配る。
codexは文脈的にA寄り(CLI配布型)で説明されることが多いです。
必要なら「@openai/codex が postinstall download型 なのか platform-specific package型 なのか」を、package.jsonの scripts.postinstall や依存関係の切り方から判定する見方も説明できます。バージョンやリポジトリURLが分かれば、より正確に言えます。
rust製アプリの文化なのかな? golang製アプリでも使われていたりする?
「Rust製アプリ特有の文化」というより、**“npmユーザー(JS/TS開発者)に届けたいCLI/ツールの文化”**です。Rustがたまたまその領域(高速CLI)で採用されやすいので目立つだけで、Goでも普通に使われます。
- 配布チャネル(npm)と実装言語(Rust/Go…)を切り離す発想
- 目的はだいたい同じで、
- 既にnpmが入っている人が多い
npm i -gで更新もアンインストールも簡単- OS/CPUごとの差(darwin/linux/win + x64/arm64)を吸収したい
- 利用者にビルド環境(Rust toolchain/Go toolchain)を要求したくない
という“開発者体験”の都合です。
結果として「中身はネイティブバイナリ、外側はnpm」という形になります。
使われています。代表例が esbuild(Go製) で、まさに
- 本体:Goでビルドしたネイティブバイナリ
- npm:プラットフォーム別パッケージ(またはインストール時取得)で配布 という構造です。
他にも「CLIはGo/Rust、配布はnpm」という例は珍しくありません(フロントエンド領域のツールほど多い)。
- Rustは単一バイナリで配りやすい・高速・クロスコンパイルしやすいので「npm経由で配りたいCLI」と相性が良い
- ただし同じ性質はGoにもあるので、Go勢も同様の配布をします
- platform-specific packages + meta package(esbuild型が有名)
- postinstallでバイナリをダウンロード
どちらもRust/Go/その他で普通に使われます。
必要なら @openai/codex が上のどっちの型かを、package.json(依存関係や postinstall)の見方で一緒に確認できます。バージョンやpackage.jsonの該当部分を貼ってください。