この記事について
mise(旧 rtx)を使い始めたとき、(&mise activate pwsh) | Out-String | Invoke-Expression という呪文のような一行を見て「これは一体何をしているのか」と戸惑う人は多いと思います。
この記事では、その mise activate が何をしているのか、なぜ「有効化」という手続きが必要なのか、そして PowerShell / cmd での使い分けまでを、順を追って整理します。特に、mise activate の一番の便利機能である「フォルダを移動するだけで、そのフォルダに合ったバージョンに自動で切り替わる」という点にフォーカスして解説します。
対象環境は Windows(PowerShell / cmd)ですが、考え方は macOS / Linux でも同じです。
mise activate の一番おいしい機能:フォルダ切替で自動バージョン切り替え
まず結論から。mise activate を有効化しておくと、次のことが自動で起きます。
C:\projectA\ ← このフォルダに入ると node は 18
C:\projectB\ ← このフォルダに入ると node は 22
cd C:\projectA した瞬間に node が 18 に、cd C:\projectB した瞬間に 22 に、あなたが何もコマンドを打たなくても自動で切り替わります。各プロジェクトに置いた mise.toml(または .tool-versions)に書かれたバージョンを mise が読み取り、そのフォルダにいる間だけそのバージョンを使えるようにしてくれるのです。
これが mise activate の最大の価値です。プロジェクトごとに nvm use 18 などと手で打つ必要がなくなります。
そもそも「有効化(activate)」とは何なのか
git や curl のような普通のツールに「有効化」という概念はありません。呼び出せば動く、それだけです。ではなぜ mise には「有効化」が必要なのでしょうか。
答えは、mise が「呼ばれたときだけ働くツール」であると同時に、「あなたが何もしていないときにも裏で働き続けてほしいツール」でもあるからです。後者、つまり「フォルダ移動に反応して自動でバージョンを切り替える」機能のために、有効化が必要になります。
鍵は「子プロセスは親プロセスの環境変数を書き換えられない」という制約
バージョンの切り替えは、実体としては環境変数 PATH の書き換えです。「今いるフォルダに応じて PATH を書き換える」ことで、node と打ったときに呼ばれる実体が変わります。
ところがここに OS レベルの壁があります。子プロセスは、親プロセス(=あなたのシェル)の環境変数を書き換えられません。
mise.exe は、あなたが実行すると「子プロセス」として起動し、仕事を終えると消えます。その子プロセスがいくら「PATH をこう変えたい」と思っても、親である PowerShell の PATH に手を出すことはできません。つまり、mise.exe を普通に呼び出すだけでは、一番やりたい「自動バージョン切り替え」が原理的にできないのです。
解決策:シェル自身に書き換えさせる
そこで mise は発想を変えます。「自分(mise.exe)が環境変数を書き換えられないなら、シェル自身に書き換えさせればいい」と。
具体的には、次の 2 段階で動きます。
- 親シェルが特定のタイミング(
cdした時やプロンプト表示時)でmise.exeを呼ぶ -
mise.exeは「$env:PATHをこう書き換えろ」という指示(シェルのコード)を文字列として出力するだけ - その指示を、親シェル自身が受け取って実行し、自分の環境変数を書き換える
ポイントは、実際に PATH を書き換えているのが mise.exe(子プロセス)ではなく、親シェル自身だという点です。だから親の環境変数を変えられます。mise.exe は「どう変えるべきか」の指示書を渡すだけ、実際に手を動かすのはシェル、という分業です。
この「cd やプロンプト表示のたびに自動で mise を呼び、返ってきた指示を実行する仕掛けをシェルに埋め込む作業」こそが 有効化(activate) です。
たとえるなら
普通のツールは「呼べば来てくれる出張業者」。用があるときだけ呼ぶ。
一方 mise の有効化は「業者をオフィスに常駐スタッフとして配置する」ようなもの。一度配置すれば、部屋(フォルダ)を移動するたびに、そのスタッフが黙って部屋に合わせた準備(バージョン切り替え)をしてくれる。
nvm・pyenv・asdf・direnv なども、同じ理由で有効化(eval "$(...)" など)を必要とします。「環境変数を親シェルに反映させたいツールは、ほぼ例外なく有効化が必要」と覚えておくと応用が効きます。
あの一行を分解する
PowerShell での有効化コマンドはこれです。
(&mise activate pwsh) | Out-String | Invoke-Expression
各部分の意味は次の通りです。
| 部分 | 役割 |
|---|---|
&mise activate pwsh |
mise が PowerShell 用の有効化スクリプト(文字列)を出力する。この時点では実行されない |
Out-String |
行ごとの配列になりがちな出力を、1 つのまとまった文字列に結合する |
Invoke-Expression |
その文字列を PowerShell コードとして実際に実行する(他シェルの eval 相当) |
Out-String がなぜ必要か
mise activate pwsh は複数行のスクリプト(関数定義など)を出力します。PowerShell はコマンド出力を「行ごとの文字列の配列」として扱うことが多く、そのまま Invoke-Expression に渡すと関数定義が途中でぶつ切りになり正しく解釈できません。Out-String で 1 つの文字列にまとめてから渡すことで、スクリプト全体が 1 かたまりのコードとして評価されます。
() の意味
(&mise activate pwsh) の丸括弧は「グループ化演算子」で、中の式を先に評価してひとまとまりとして扱います。このケースでは括弧はあってもなくても動作は変わりませんが、「ここまでが 1 つのコマンド」と視覚的に明確にするために付けられています。
他シェルでは次のように書きます。中身は同じ「有効化」です。
eval "$(mise activate bash)" # bash
eval "$(mise activate zsh)" # zsh
mise activate fish | source # fish
有効化はセッション(プロセス)限り → プロファイルに書く
有効化で仕込んだフック関数や環境変数の変更は、すべてそのシェルプロセスのメモリ内にだけ存在します。プロセスを閉じれば消えます。新しいシェルを開くと、そこには何も仕込まれていないので、cd しても自動切り替えは起きません。
そこで、新しいシェルを開くたびに自動で有効化されるよう、プロファイル(起動時に自動実行される初期化ファイル)にあの一行を書いておきます。
mise 公式が案内している追記コマンドはこれです(echo で一行を出力し、>> でプロファイル末尾に追記しているだけ)。
echo '(&mise activate pwsh) | Out-String | Invoke-Expression' >> $HOME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
ただし、プロファイルの実際の場所は環境によって異なります。パスを直書きするより、$PROFILE 変数を使うほうが確実です。
# プロファイルの親ディレクトリがなければ作成
if (-not (Test-Path (Split-Path $PROFILE))) {
New-Item -ItemType Directory -Path (Split-Path $PROFILE) -Force
}
# 有効化コマンドをプロファイルに追記
'(&mise activate pwsh) | Out-String | Invoke-Expression' | Add-Content $PROFILE
💡 副作用に関する注記
上記の>>やAdd-Contentは、プロファイルファイルへの書き込みを伴います。既存のプロファイルに追記する形なので、実行前に現在の$PROFILEの中身を確認しておくと安心です。
【重要】PowerShell のバージョンに注意(5.1 では自動切り替えが効かない)
ここが Windows ユーザーの大きな落とし穴です。
mise の PowerShell 実装は、cd に反応する機能(chpwd フック)に System.Management.Automation.LocationChangedEventArgs などの C# API を使っており、これには PowerShell 7.2 以上が必要です。Windows に古くから入っている Windows PowerShell 5.1 では、cd した瞬間の自動切り替えが動きません。
自分のバージョンは次で確認できます。
$PSVersionTable.PSVersion
# Major が 5 → Windows PowerShell 5.1(自動切り替え不可)
# Major が 7 → PowerShell 7 系(OK)
5.1 で activate すると、cd 直後には切り替わらず、プロンプトが再描画される(Enter を一度押す)と切り替わる、という半端な挙動になりがちです。自動切り替えをフルに使いたいなら PowerShell 7 系(pwsh)を導入してください。 5.1 とは別物で共存できます。
winget install --id Microsoft.PowerShell --source winget
導入後は powershell ではなく pwsh で起動し、その pwsh の $PROFILE(5.1 とはパスが別)に有効化の一行を書きます。
cmd はどうする? → activate は効かない。シム方式を使う
「PowerShell のプロファイルに書けば cmd でも効くのか?」という疑問がよくありますが、効きません。
有効化とは「そのシェルのメモリにフックを埋め込むこと」であり、PowerShell のプロファイルは PowerShell 起動時にしか読まれません。cmd は PowerShell とは完全に別のシェル(別プロセス)なので、PowerShell のプロファイルを読むことはありません。そもそも (&mise activate pwsh) | ... は PowerShell 専用の構文で、cmd では文法として解釈すらできません。加えて、mise は cmd 用の activate を提供していません。
cmd でフォルダごとの切り替えを効かせたい場合は、シム(shims)方式を使います。
シム方式とは
シムは mise が用意する「中継役の実行ファイル」です。node などの中継役を 1 か所のフォルダに置き、それを OS の PATH に通しておきます。node を呼ぶと、まず中継役が起動し、「今いるフォルダではどのバージョンを使うべきか」をその場で mise に問い合わせて本物へ橋渡しします。
シェルのフックに依存しないので、cmd でも PowerShell でも、PowerShell のバージョンを問わず動くのが利点です。
# シムフォルダのパス(PowerShell で確認する場合はダブルクォートで囲む)
"$env:LOCALAPPDATA\mise\shims"
このフォルダを Windows のユーザー/システム環境変数 PATH に登録すれば、そこから起動する cmd・PowerShell 双方に効きます。
activate 方式とシム方式の違い
| activate 方式 | シム方式 | |
|---|---|---|
| 切り替わるタイミング |
cd した瞬間(PS 7 系) |
その node を実行した瞬間にフォルダを見て解決 |
| cd 時のバージョン表示 | あり | なし |
| 対応シェル | bash/zsh/fish/pwsh など | シェル非依存(cmd 含む) |
| PowerShell バージョン依存 | 7.2 以上が必要 | 依存しない |
「PowerShell 7 では activate、cmd も含めたいならシム」という使い分け、あるいは両方の併用が可能です。
主要コマンドの整理
mise use と mise install と mise exec
| コマンド | やること |
mise.toml への記録 |
|---|---|---|
mise install node@18 |
node 18 をダウンロードするだけ | しない |
mise use node@18 |
install に加え、mise.toml にバージョンを記録 |
する |
mise exec node@18 -- node -v |
その場限りで、明示指定したバージョンで実行 | しない |
⚠️
mise use/mise installの副作用に注意
mise use node@18やmise install node@18は、指定バージョンが未インストールなら、ネットワーク経由で Node のバイナリを自動でダウンロード・展開(インストール)します。「mise.tomlに書くだけ」ではありません。実行時にextract node-vXX-win-x64.zipのような表示が出るのはこのためです。「設定ファイルへの記録だけ」のつもりで打つと、意図せずネットワークアクセスとインストールが走る点に注意してください。ダウンロードは初回だけで、インストール済みのバージョンなら次回以降は記録だけで済みます。取り消したい場合は
mise uninstall node@18で実体を削除できます。
日常的に複数プロジェクトを行き来するなら、各プロジェクトで一度 mise use してバージョンを紐づけておき、あとは activate 方式(PS 7 系)かシム方式(cmd 含む)で自動適用させるのが楽です。単発利用なら mise exec が便利です。
設定を一覧で確認する
mise use は「設定の台帳」を持っているわけではなく、設定の実体は各フォルダの mise.toml に分散しています。今いるフォルダで効いているバージョンと、その出どころ(Source)を見るには次を使います。
mise ls # mise が把握しているツールと、そのソース
mise ls node # node だけに絞る
mise ls --current # 今アクティブなものだけ
mise config # 認識している設定ファイルの場所
いずれも「今いる場所から見える範囲」が原則です。全プロジェクト横断で一覧したい場合は、mise.toml をファイル検索するのが確実です。
Get-ChildItem -Path C:\projects -Recurse -Filter mise.toml -ErrorAction SilentlyContinue |
ForEach-Object { Write-Host "`n=== $($_.FullName) ==="; Get-Content $_.FullName }
まとめ
-
mise activateの最大の価値は、フォルダを移動するだけで、そのフォルダのmise.tomlに応じたバージョンへ自動で切り替えてくれること。 - 「有効化」が必要なのは、子プロセス(mise.exe)が親シェルの環境変数を書き換えられないという制約のため。親シェルにフックを埋め込み、mise が返す指示を親自身に実行させる仕掛けが必要になる。
- 有効化はプロセス限り。恒久化するにはプロファイル(
$PROFILE)に一行を追記する(=プロファイルへの書き込みという副作用を伴う)。 -
Windows PowerShell 5.1 では
cd時の自動切り替えが効かない。 フル活用には PowerShell 7 系が必要。 - cmd では activate が使えないため、シムフォルダを
PATHに通すシム方式を使う。 -
mise use/mise installは、未インストールのバージョンをネットワーク経由で自動ダウンロード・インストールする副作用がある点に注意。
以上を押さえておけば、あの呪文のような一行が「フォルダ移動に反応してバージョンを自動で切り替えるための、シェルへの仕込み」だと腑に落ちるはずです。