fix(hook-env): preserve PATH reordering done after activation#8190
Conversation
hook-env always used __MISE_ORIG_PATH order when reconstructing PATH, discarding any reordering done after activation (e.g., by ~/.zlogin which runs after ~/.zshrc where mise activate is placed). Now collect orig paths in their current order to preserve post-activation reordering. Fixes #8188 Fixes #8168 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical bug in Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request fixes an issue where hook-env would not preserve PATH reordering performed after shell activation. The changes in src/cli/hook_env.rs correctly reconstruct the PATH by respecting the current order of original path entries, which resolves the problem. A new end-to-end test has been added to verify this fix. The implementation looks solid. I have one suggestion to make the new test script more robust.
| MYTOOL_POS=$(echo "$PATH" | tr ':' '\n' | grep -n "mytool/bin" | head -1 | cut -d: -f1) | ||
| SYSTEM_POS=$(echo "$PATH" | tr ':' '\n' | grep -n "system-bin" | head -1 | cut -d: -f1) |
There was a problem hiding this comment.
The grep commands here could lead to incorrect matches if other paths in PATH contain "mytool/bin" or "system-bin" as substrings. To make the test more robust, it's better to perform an exact match on the full path strings.
You can use grep -F -x for an exact, full-line match. Since the command is in double quotes, $HOME will be expanded correctly.
MYTOOL_POS=$(echo "$PATH" | tr ':' '\n' | grep -n -F -x "$HOME/mytool/bin" | head -1 | cut -d: -f1)
SYSTEM_POS=$(echo "$PATH" | tr ':' '\n' | grep -n -F -x "$HOME/system-bin" | head -1 | cut -d: -f1)
There was a problem hiding this comment.
Pull request overview
Updates hook-env PATH reconstruction to preserve post-activation reordering of original PATH entries (e.g., changes made in ~/.zlogin after mise activate), fixing reported ordering regressions.
Changes:
- Collects original PATH entries in their current order (instead of restoring
__MISE_ORIG_PATHorder), while appending any missing original entries as a safety net. - Adds an e2e regression test covering PATH reordering after activation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/cli/hook_env.rs |
Adjusts PATH reconstruction to preserve reordered original PATH entries while keeping existing “pre”/“post_user” behavior. |
e2e/env/test_path_reorder_after_activate |
New regression test asserting that post-activation reordering of an original PATH entry is preserved. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # and https://github.com/jdx/mise/issues/8168 | ||
|
|
||
| # Save the mise binary path before we override PATH | ||
| MISE_BIN="$(which mise)" |
There was a problem hiding this comment.
which is non-POSIX and is flagged by ShellCheck (SC2230). Since hk.pkl runs shellcheck over e2e/**, this will break linting in CI. Prefer command -v mise (and fail with a clear message if it’s not found) when capturing the absolute path before overriding PATH.
| MISE_BIN="$(which mise)" | |
| MISE_BIN="$(command -v mise)" | |
| if [[ -z "$MISE_BIN" ]]; then | |
| echo "FAIL: mise binary not found in PATH" >&2 | |
| exit 1 | |
| fi |
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 x -- echo |
24.4 ± 0.7 | 23.0 | 29.5 | 1.02 ± 0.04 |
mise x -- echo |
23.9 ± 0.5 | 23.0 | 27.4 | 1.00 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 env |
23.4 ± 0.6 | 22.5 | 29.5 | 1.00 ± 0.03 |
mise env |
23.4 ± 0.4 | 22.6 | 25.1 | 1.00 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 hook-env |
23.9 ± 0.6 | 23.2 | 31.3 | 1.00 |
mise hook-env |
24.0 ± 0.4 | 23.4 | 25.7 | 1.00 ± 0.03 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 ls |
22.1 ± 0.3 | 21.5 | 23.7 | 1.00 |
mise ls |
22.3 ± 0.4 | 21.7 | 24.5 | 1.01 ± 0.02 |
xtasks/test/perf
| Command | mise-2026.2.13 | mise | Variance |
|---|---|---|---|
| install (cached) | 127ms | 127ms | +0% |
| ls (cached) | 79ms | 79ms | +0% |
| bin-paths (cached) | 83ms | 82ms | +1% |
| task-ls (cached) | 829ms | 825ms | +0% |
### 🚀 Features - **(task)** stream keep-order output in real-time per task by @jdx in [#8164](#8164) ### 🐛 Bug Fixes - **(aqua)** resolve lockfile artifacts for target platform (fix discussion #7479) by @mackwic in [#8183](#8183) - **(exec)** strip shims from PATH to prevent recursive shim execution by @jdx in [#8189](#8189) - **(hook-env)** preserve PATH reordering done after activation by @jdx in [#8190](#8190) - **(lockfile)** resolve version aliases before lockfile lookup by @jdx in [#8194](#8194) - **(registry)** set helm-diff archive bin name to diff by @jean-humann in [#8173](#8173) - **(task)** improve source freshness checks with dynamic task dirs by @rooperuu in [#8169](#8169) - **(task)** resolve global tasks when running from monorepo root by @jdx in [#8192](#8192) - **(task)** prevent wildcard glob `test:*` from matching parent task `test` by @jdx in [#8165](#8165) - **(task)** resolve task_config.includes relative to config root by @jdx in [#8193](#8193) - **(upgrade)** skip untrusted tracked configs during upgrade by @jdx in [#8195](#8195) ### 🚜 Refactor - use enum for npm.pacakge_manager by @risu729 in [#8180](#8180) ### 📚 Documentation - **(plugins)** replace node/asdf-nodejs examples with vfox plugins by @jdx in [#8191](#8191) ### ⚡ Performance - call npm view only once by @risu729 in [#8181](#8181) ### New Contributors - @jean-humann made their first contribution in [#8173](#8173) - @mackwic made their first contribution in [#8183](#8183) - @rooperuu made their first contribution in [#8169](#8169) ## 📦 Aqua Registry Updates #### New Packages (2) - [`BetterDiscord/cli`](https://github.com/BetterDiscord/cli) - [`glossia.ai/cli`](https://github.com/glossia.ai/cli)
## Summary - `hook-env` always restored `__MISE_ORIG_PATH` order when reconstructing PATH, discarding any reordering done after activation - This broke scenarios where `~/.zlogin` (runs after `~/.zshrc`) moves a PATH entry to the front for priority - Now collects orig paths in their current order to preserve post-activation reordering, while still appending any missing orig paths as a safety net Fixes jdx#8188 Fixes jdx#8168 Builds on the earlier fix in jdx#7919 (commit 9e021af) which handled paths *appended* after activation but didn't handle *reordering* of existing orig paths. ## Test plan - [x] Added `e2e/env/test_path_reorder_after_activate` regression test - [x] Verified test **fails** without the fix (mytool/bin pushed to position 5) and **passes** with it (stays at position 1) - [x] Existing `test_path_post_activate_append` still passes - [x] Existing `test_path_interleaved_regression` still passes - [x] All 477 unit tests pass - [x] All linting passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches PATH-building logic in `hook-env`, which affects shell environments broadly; bugs could reorder/omit PATH entries and break command resolution across shells. > > **Overview** > Fixes `hook-env` PATH reconstruction so it preserves the *current ordering* of entries that were present in `__MISE_ORIG_PATH`, instead of always restoring the original captured order; it still appends any missing original entries as a safety net. > > Adds an E2E regression test (`e2e/env/test_path_reorder_after_activate`) that simulates post-activation PATH reordering and asserts `hook-env` does not undo it. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8eed0ce. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
### 🚀 Features - **(task)** stream keep-order output in real-time per task by @jdx in [jdx#8164](jdx#8164) ### 🐛 Bug Fixes - **(aqua)** resolve lockfile artifacts for target platform (fix discussion jdx#7479) by @mackwic in [jdx#8183](jdx#8183) - **(exec)** strip shims from PATH to prevent recursive shim execution by @jdx in [jdx#8189](jdx#8189) - **(hook-env)** preserve PATH reordering done after activation by @jdx in [jdx#8190](jdx#8190) - **(lockfile)** resolve version aliases before lockfile lookup by @jdx in [jdx#8194](jdx#8194) - **(registry)** set helm-diff archive bin name to diff by @jean-humann in [jdx#8173](jdx#8173) - **(task)** improve source freshness checks with dynamic task dirs by @rooperuu in [jdx#8169](jdx#8169) - **(task)** resolve global tasks when running from monorepo root by @jdx in [jdx#8192](jdx#8192) - **(task)** prevent wildcard glob `test:*` from matching parent task `test` by @jdx in [jdx#8165](jdx#8165) - **(task)** resolve task_config.includes relative to config root by @jdx in [jdx#8193](jdx#8193) - **(upgrade)** skip untrusted tracked configs during upgrade by @jdx in [jdx#8195](jdx#8195) ### 🚜 Refactor - use enum for npm.pacakge_manager by @risu729 in [jdx#8180](jdx#8180) ### 📚 Documentation - **(plugins)** replace node/asdf-nodejs examples with vfox plugins by @jdx in [jdx#8191](jdx#8191) ### ⚡ Performance - call npm view only once by @risu729 in [jdx#8181](jdx#8181) ### New Contributors - @jean-humann made their first contribution in [jdx#8173](jdx#8173) - @mackwic made their first contribution in [jdx#8183](jdx#8183) - @rooperuu made their first contribution in [jdx#8169](jdx#8169) ## 📦 Aqua Registry Updates #### New Packages (2) - [`BetterDiscord/cli`](https://github.com/BetterDiscord/cli) - [`glossia.ai/cli`](https://github.com/glossia.ai/cli)
### 🚀 Features - **(task)** stream keep-order output in real-time per task by @jdx in [jdx#8164](jdx#8164) ### 🐛 Bug Fixes - **(aqua)** resolve lockfile artifacts for target platform (fix discussion jdx#7479) by @mackwic in [jdx#8183](jdx#8183) - **(exec)** strip shims from PATH to prevent recursive shim execution by @jdx in [jdx#8189](jdx#8189) - **(hook-env)** preserve PATH reordering done after activation by @jdx in [jdx#8190](jdx#8190) - **(lockfile)** resolve version aliases before lockfile lookup by @jdx in [jdx#8194](jdx#8194) - **(registry)** set helm-diff archive bin name to diff by @jean-humann in [jdx#8173](jdx#8173) - **(task)** improve source freshness checks with dynamic task dirs by @rooperuu in [jdx#8169](jdx#8169) - **(task)** resolve global tasks when running from monorepo root by @jdx in [jdx#8192](jdx#8192) - **(task)** prevent wildcard glob `test:*` from matching parent task `test` by @jdx in [jdx#8165](jdx#8165) - **(task)** resolve task_config.includes relative to config root by @jdx in [jdx#8193](jdx#8193) - **(upgrade)** skip untrusted tracked configs during upgrade by @jdx in [jdx#8195](jdx#8195) ### 🚜 Refactor - use enum for npm.pacakge_manager by @risu729 in [jdx#8180](jdx#8180) ### 📚 Documentation - **(plugins)** replace node/asdf-nodejs examples with vfox plugins by @jdx in [jdx#8191](jdx#8191) ### ⚡ Performance - call npm view only once by @risu729 in [jdx#8181](jdx#8181) ### New Contributors - @jean-humann made their first contribution in [jdx#8173](jdx#8173) - @mackwic made their first contribution in [jdx#8183](jdx#8183) - @rooperuu made their first contribution in [jdx#8169](jdx#8169) ## 📦 Aqua Registry Updates #### New Packages (2) - [`BetterDiscord/cli`](https://github.com/BetterDiscord/cli) - [`glossia.ai/cli`](https://github.com/glossia.ai/cli)
Summary
hook-envalways restored__MISE_ORIG_PATHorder when reconstructing PATH, discarding any reordering done after activation~/.zlogin(runs after~/.zshrc) moves a PATH entry to the front for priorityFixes #8188
Fixes #8168
Builds on the earlier fix in #7919 (commit 9e021af) which handled paths appended after activation but didn't handle reordering of existing orig paths.
Test plan
e2e/env/test_path_reorder_after_activateregression testtest_path_post_activate_appendstill passestest_path_interleaved_regressionstill passes🤖 Generated with Claude Code
Note
Medium Risk
Touches PATH-building logic in
hook-env, which affects shell environments broadly; bugs could reorder/omit PATH entries and break command resolution across shells.Overview
Fixes
hook-envPATH reconstruction so it preserves the current ordering of entries that were present in__MISE_ORIG_PATH, instead of always restoring the original captured order; it still appends any missing original entries as a safety net.Adds an E2E regression test (
e2e/env/test_path_reorder_after_activate) that simulates post-activation PATH reordering and assertshook-envdoes not undo it.Written by Cursor Bugbot for commit 8eed0ce. This will update automatically on new commits. Configure here.