Bash tool spawns a login shell whose state it then discards — ~830ms per call
The Bash tool appears to invoke commands through a login shell (bash -lc). On this machine that costs roughly 830ms on every single Bash call, and the state it pays for is discarded before the next one.
Measured on Windows 11, Intel Ultra 9 285K, each variant spawned individually, process time (not wall clock), median of repeated runs:
cat pyproject.toml 24.1ms the work itself
bash -c 'cat pyproject.toml' 48.7ms + a non-login shell
bash -lc 'cat pyproject.toml' 881.7ms + sourcing the profile (max observed 1674ms)
That is roughly 18x the work being wrapped, and it recurs per call.
What makes this look like waste rather than a cost worth paying: the Bash tool's own documented contract states both that the shell is initialized from the user's profile and that shell state does not persist between calls. Both are true simultaneously — the profile is sourced on every invocation and then thrown away. The things a login shell exists to establish (exported environment, PATH assembly, shell functions) are precisely what the contract says will not survive to the next call.
Supporting datapoint from a separate instrumented codebase: Bash and PowerShell tool calls accounted for 87.8% of total instrumented wall clock, against approximately 0% for the native file-read tool. On agent workloads this is where the time goes, not a rounding error.
The ask: is the login shell load-bearing for something not visible from outside? If it is not, using -c rather than -lc would return most of that ~830ms to every user on every platform. If it is, knowing what depends on it would help — the "state does not persist" contract makes the dependency hard to locate from the outside.
To reproduce: time bash -c against bash -lc for any trivial command on a machine with a non-trivial shell profile. The gap scales with whatever the profile does, which is why it may not show up on a clean test image.