bat でファイルを開くと、中身は出るのにプロンプトが返ってきません。zi は移動だけして無言で固まる。どちらも Ctrl-C では抜けられます。

同じ実行ファイルを直接叩くと、両方とも普通に動きました。

shim はプロセス 3 個

mise\shims\bat.exe は bat ではありません。mise を起動し、mise がこのディレクトリで使うべき bat を解決し、それを起動する。そういう小さなプログラムです。コマンド 1 つにプロセス生成が 3 回。

このマシンはウイルス対策が集中管理されていて、プロセスを作るたびに検査が入ります。bat --version を 15 回ずつ:

経路
shim127 ms (115–144)
実行ファイルへの symlink15 ms (11–28)

ツール本体は 15 ms。残りの 112 ms は、増えた 2 プロセス分の検査です。

遅いだけならプロンプトは返ってくる

shim は、起動したツールが終わるまで自分も終了しません。端末とツールの間に、コンソールプロセスがもう 1 つ挟まった状態が最後まで続きます。

止まった 2 つは、どちらも端末そのものを使うコマンドでした。bat は画面をless に渡し、zi は移動先を標準出力へ書いてシェルに読ませます。相手が端末である前提で書かれているところに、shim が 1 枚入っていたわけです。

mise activate を選ばなかった理由

mise activate は解決をシェル側に移します。プロンプトのたびにフックが走り、今いるディレクトリで見えるべきツールへ PATH を書き換える。これなら間に何も挟まりません。

ただし、そのフック mise hook-env 自体がプロセス 1 個です。同じ検査を受けて 130 ms。次に打つのが mise のツールでなくても、プロンプトを出すたびに 130 ms 払います。PATH も 7,265 文字まで伸びる。上限は 8,191 で、残り 894 文字の使い道はPATH の予算のほうにあります。

farm

%LocalAppData%\mise\bin に、実行ファイルを指す symlink をツールごとに 1 本置いています。プロセス 1 個、PATH エントリ 43 文字 1 本、フック無し。

windows/Sync-MiseBinFarm.ps1 が shims ディレクトリから組み立てます。shim 204 本のうち、リンクを張るのは 144 本:

  • 名前で除外、44 本。 python と pip は標準ライブラリを自分の実行ファイルからの相対で探すので、symlink 経由だと farm の中を探しにいって空振りします。 rust 系は ~/.cargo/bin から既に届くため対象外。
  • リンク先が PE ファイルでない、10 本。 .cmd を指す npm.exe はローダーが弾きます。残る 8 本は拡張子そのものが無く、名前を見ても判別できません。
  • mise がもう解決しない、6 本。

この 60 本は shim のまま動きます。遅いだけで、壊れてはいません。

リンクが切れたとき

symlink はパスを 1 本だけ名指しします。mise up でインストール先がtools/node/22.14.0 から 22.15.0 へ動けば、リンクはそこで切れる。farm はこの構成で唯一、定期的な手入れが要る部分です。

  • シェルを開くたびに、PowerShell のプロファイルが同期を走らせます。
  • リンク先の消えた本数は windows/doctor.ps1 が数えて出します。
  • windows/path-order.toml が farm を shims より前に固定しています。リンクの無いツールは 127 ms の経路へ落ちるだけで、実行はできます。