bat printed the file and the prompt never came back. zi changed
directory and printed nothing. Ctrl-C returned the shell both times.
The binaries were not at fault. Launched directly, both behaved.
A shim is three processes
mise\shims\bat.exe is not bat. It is a small program that starts mise,
which works out which bat this directory should get, and starts that one.
Three process creations answer one command.
Every creation is inspected, because the machine runs
centrally managed endpoint protection. Fifteen runs of bat --version:
| launched through | |
|---|---|
| the shim | 127 ms (115–144) |
| a symlink to the executable | 15 ms (11–28) |
Fifteen milliseconds is the tool. The rest is the arrangement around it.
It also stays in the middle
Latency does not explain a prompt that never returns. A shim does not hand
over and exit. It remains for the whole run as a console process between
the terminal and the tool, and both of the commands that broke are
conversations with the console: bat hands paging to less, and zi
writes a directory for the shell to read back. Each of those crossed an
extra process that was never built to relay it.
Why not mise activate
mise activate moves the resolution into the shell. A hook runs at every
prompt and rewrites PATH to the tools the current directory should see.
Nothing relays anything, and no shim is in the way.
That hook is mise hook-env, which is itself one more process creation —
130 ms here, at every prompt, whether or not the next command is a mise
tool at all. It also expands PATH to 7,265 characters against a limit of
8,191, and the PATH budget has other plans for the
remainder.
The farm
%LocalAppData%\mise\bin holds one symlink per tool, pointing at the real
executable. One process, one 43-character PATH entry, no hook.
windows/Sync-MiseBinFarm.ps1 builds it from the shim directory. Of 204
shims it links 144 and skips the rest:
- 44 by name. Python and pip find the standard library relative to their
own executable, so through a symlink they would look inside the farm and
find nothing. The rust family is already reachable from
~/.cargo/bin. - 10 whose target is not a PE file. A link named
npm.exepointing at a.cmdis something the loader refuses; the eight extensionless targets are the same problem without an extension to give it away. - 6 that mise no longer resolves.
Those sixty keep their shims and keep working.
The link goes stale
A symlink names one path, and an upgrade moves the install directory out from under it. So the farm is the one part of this that needs maintenance, and three things carry it:
- The PowerShell profile runs the sync at shell start.
windows/doctor.ps1counts links whose target no longer exists.windows/path-order.tomlasserts that the farm resolves before the shims, so a tool with no link falls through to the slow path rather than failing.