Repository navigation
fix: use the link farm when running stubs unactivated - #634
Merged
Merged
Conversation
Running `./bin/<tool>` without activation gave the tool's children `bin/` on PATH but not the link farm, so every tool they ran went back through a stub. Those stubs also took the slow unactivated path, resolving every installed package's manifest again (~0.27s each, against ~0.05s for an activated stub). In blox, `./bin/just fmt` started 59 Hermit processes this way and took ~22s, against ~6.6s when activated. Unactivated `hermit exec` now does what activation does: it checks linked channel packages for updates, creates the link farm and puts it on PATH directly ahead of `bin/`. The same command now starts 2 Hermit processes and takes ~6.1s. Activated execution is unchanged, and the child environment differs only by the farm on PATH and HERMIT_LINK_FARM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alecthomas
marked this pull request as ready for review
October 21, 2026 03:25
jvmakine
approved these changes
Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Running
./bin/<tool>without activating the environment, as git hooks, IDEs and agents often do, is far slower than the same command in an activated shell. In a large repository whosejust fmtrecipe calls many Hermit-managed tools,./bin/just fmttook about 22s unactivated against 6.6s activated (18.5s against 4.4s on a quieter machine).The tool's children got
bin/onPATHbut not the link farm, so every tool they ran went back through a stub. Those stubs also took the slow unactivated path, becauseACTIVE_HERMITis unset. On that path the stub resolves every installed package's manifest again. Per call, measured withbin/bash -c truein that repository:One unactivated
./bin/just fmtstarted 59 Hermit processes. 45 werebash, which that environment manages with Hermit andjustuses to run recipe lines. Most of the extra time is the repeated environment reload, not process startup: activated shells before 0.54.0, which had no link farm, were already close to the current activated time.Unactivated
hermit execnow does what activation does: it checks linked channel packages for updates, creates the link farm, and puts it onPATHdirectly ahead ofbin/. Activation andexecshare this through a newcreateLinkFarmhelper. Children then run other packages directly, as in an activated shell. The child environment differs from before only by the farm onPATHandHERMIT_LINK_FARM, and the farm is the same directory activation uses. Activated execution is unchanged.Results for
./bin/just fmtin that repository, three runs each, on a loaded machine:Hermit processes per unactivated run went from 59 to 2.
Known gap: a child that calls a stub by an explicit path, such as
xargs bin/go, still pays the full unactivated reload (about 0.28s against 0.05s activated). Fixing that needs a marker telling nested stubs the environment is already loaded, without making child shells think Hermit is activated, so it is left out of this change.Tests: two new integration tests, run under bash and zsh, cover a child of an unactivated stub running another package through the farm with its environment variables set, and a due channel update being picked up when the child runs a linked channel package. The first fails on the previous code; the second fails if the update check is removed from
exec.🤖 Generated with Claude Code