Skip to content

feat(plugins): warn when env plugin shadows a registry tool#7953

Merged
jdx merged 5 commits intomainfrom
feat/warn-env-plugin-shadow
Feb 1, 2026
Merged

feat(plugins): warn when env plugin shadows a registry tool#7953
jdx merged 5 commits intomainfrom
feat/warn-env-plugin-shadow

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Feb 1, 2026

Summary

  • Adds a warning when a vfox env-only plugin is installed with a name that matches a registry entry
  • Env-only plugins are detected by having hooks/mise_env.lua but not hooks/available.lua
  • Warning fires at install time only (not on every resolution) to avoid noise
  • Covers both CLI install (mise plugins install) and auto-install via VfoxPlugin::ensure_installed

Test plan

  • Added e2e test test_env_plugin_shadow_warning that creates a fake vfox env plugin named "jq" and verifies the warning appears
  • Unit tests pass (444/444)
  • Lint passes

🤖 Generated with Claude Code


Note

Medium Risk
Medium risk because it changes tool-stub resolution/installation behavior by injecting per-platform lock data and adds new mutation paths for existing stub files; it also touches plugin install flows (new warning) and adds new e2e coverage.

Overview
Tool stubs can now be “locked” for reproducible installs. mise generate tool-stub --lock updates an existing stub by resolving the exact version and writing a [lock.platforms.*] table with pinned URLs/checksums (and supports bumping via --version), and mise tool-stub consumes this lock data during installation.

Plugin installs now warn on name collisions. When installing an env-only vfox plugin (has hooks/mise_env.lua but no hooks/available.lua) whose name matches a registry tool, mise emits a one-time warning during install.

Docs/man/completions are updated for --lock, and e2e tests are expanded (new lock/warning tests, more reliable HTTP upgrade test via random port, and git author env for test commits).

Written by Cursor Bugbot for commit c5eff4a. This will update automatically on new commits. Configure here.

Add a --lock flag that resolves and embeds lockfile data (exact version +
platform URLs/checksums) directly into tool stub files. This makes stubs
fully reproducible without runtime API calls, which is especially useful
for avoiding GitHub API rate limits.

Also supports --version with --lock to bump versions in locked stubs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 1, 2026 20:19
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @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 significantly enhances the mise tool's reliability and user experience. It introduces a robust locking mechanism for tool stubs, ensuring consistent and reproducible tool installations by embedding all necessary download information directly. Concurrently, it improves user feedback by proactively warning about potential naming conflicts when installing vfox env-only plugins, thereby preventing unexpected behavior and guiding users towards better plugin management practices.

Highlights

  • Tool Stub Locking: Introduced a new --lock flag for mise generate tool-stub which resolves and embeds exact version, platform-specific URLs, and checksums directly into the stub file. This enables reproducible installations and reduces reliance on runtime API calls, especially useful for avoiding GitHub API rate limits.
  • Vfox Env Plugin Shadow Warning: Implemented a warning mechanism that triggers when an env-only vfox plugin is installed with a name that conflicts with an existing tool in the registry. This warning helps users avoid potential shadowing issues and is displayed only at install time to prevent excessive noise.
  • Improved Documentation and Testing: Updated the docs/dev-tools/tool-stubs.md to explain the new locking feature with examples. New end-to-end tests were added to cover both the tool stub locking functionality and the env plugin shadowing warning.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a warning when vfox env-only plugins shadow registry tools, and implements a locking mechanism for tool stubs to enable reproducible installs without runtime API calls.

Changes:

  • Detects env-only vfox plugins (having mise_env.lua but not available.lua) and warns when their name matches a registry entry
  • Adds --lock flag to mise generate tool-stub for pinning exact versions and platform-specific URLs/checksums
  • Implements lock data injection from tool stubs into the toolset resolution process

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/plugins/vfox_plugin.rs Adds warning method for env plugins shadowing registry tools, called after plugin installation
src/cli/plugins/install.rs Adds duplicate warning function for asdf plugins and calls it after installation
src/cli/tool_stub.rs Adds lock data structures and injection logic to populate tool versions with locked platform info
src/cli/generate/tool_stub.rs Implements --lock flag to resolve versions and generate lock sections with platform URLs/checksums
e2e/plugins/test_env_plugin_shadow_warning E2E test verifying warning appears when installing env plugin matching registry name
e2e/generate/test_generate_tool_stub_lock E2E tests for tool stub locking functionality including version bumping and idempotency
docs/dev-tools/tool-stubs.md Documents the new locking feature with examples of usage and benefits

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +193 to +202
fn warn_if_env_plugin_shadows_registry(name: &str, plugin_path: &Path) {
let hooks = plugin_path.join("hooks");
let is_env_only = hooks.join("mise_env.lua").exists() && !hooks.join("available.lua").exists();
if is_env_only && REGISTRY.contains_key(name) {
warn!(
"plugin '{name}' is an env plugin and is shadowing the '{name}' registry tool - \
consider renaming the plugin or removing it with: mise plugins rm {name}"
);
}
}
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function duplicates the logic from VfoxPlugin::warn_if_env_plugin_shadows_registry. Consider extracting the common warning logic into a shared utility function to avoid code duplication and ensure consistent behavior across both plugin types.

Copilot uses AI. Check for mistakes.
Ok(info) if info.url.is_some() => {
lock_platforms.insert(target.to_key(), info);
}
_ => {} // Skip platforms without lock info
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent failures for platforms without lock info could make debugging difficult. Consider logging a debug or trace message indicating which platforms were skipped and why.

Copilot uses AI. Check for mistakes.

// Inject lock data from stub into tool versions
if let Some(lock) = &stub.lock {
for (_ba, tvl) in toolset.versions.iter_mut() {
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name _ba is unclear. Consider renaming it to _backend_alias or _tool_backend to better indicate what it represents, even though it's unused.

Suggested change
for (_ba, tvl) in toolset.versions.iter_mut() {
for (_backend_alias, tvl) in toolset.versions.iter_mut() {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces two main features: a warning for environment-only vfox plugins that shadow registry tools, and a new --lock flag for mise generate tool-stub to create reproducible tool stubs. The changes are well-implemented and include corresponding documentation and tests. My review focuses on improving code maintainability by addressing a small amount of code duplication. Overall, this is a solid contribution.

Comment on lines +76 to +88
/// Warn if this is an env-only plugin whose name matches a registry entry.
fn warn_if_env_plugin_shadows_registry(&self) {
let hooks = self.plugin_path.join("hooks");
let is_env_only =
hooks.join("mise_env.lua").exists() && !hooks.join("available.lua").exists();
if is_env_only && REGISTRY.contains_key(self.name.as_str()) {
warn!(
"plugin '{}' is an env plugin and is shadowing the '{}' registry tool - \
consider renaming the plugin or removing it with: mise plugins rm {}",
self.name, self.name, self.name
);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This function warn_if_env_plugin_shadows_registry duplicates logic also found in src/cli/plugins/install.rs. To adhere to the DRY (Don't Repeat Yourself) principle and improve maintainability, this logic should be extracted into a single, shared utility function.

A new function like pub fn warn_if_vfox_env_plugin_shadows_registry(name: &str, plugin_path: &Path) could be created in a shared module (e.g., src/plugins/util.rs) and then called from both this location and install.rs.

When a vfox env-only plugin (has hooks/mise_env.lua but not
hooks/available.lua) is installed with a name that matches a registry
entry, emit a warning at install time. This helps prevent users from
accidentally shadowing registry tools with env plugins.

The warning fires in two places:
- CLI plugin install (mise plugins install)
- VfoxPlugin::ensure_installed (auto-install from config)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx force-pushed the feat/warn-env-plugin-shadow branch from 0e762ae to 7d86492 Compare February 1, 2026 20:23
@jdx
Copy link
Copy Markdown
Owner Author

jdx commented Feb 1, 2026

bugbot run

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 1, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.0 x -- echo 20.4 ± 0.4 19.7 23.4 1.00
mise x -- echo 21.0 ± 0.5 20.0 22.9 1.03 ± 0.03

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.0 env 20.1 ± 0.6 19.2 24.6 1.00
mise env 20.4 ± 0.4 19.4 21.9 1.02 ± 0.04

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.0 hook-env 20.7 ± 0.3 20.0 22.1 1.00
mise hook-env 21.4 ± 0.5 20.4 23.8 1.03 ± 0.03

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.0 ls 18.6 ± 0.4 17.8 19.8 1.00
mise ls 19.0 ± 0.4 18.1 20.8 1.02 ± 0.03

xtasks/test/perf

Command mise-2026.2.0 mise Variance
install (cached) 112ms 113ms +0%
ls (cached) 71ms 71ms +0%
bin-paths (cached) 75ms 76ms -1%
task-ls (cached) 535ms 537ms +0%

The test_env_plugin_shadow_warning test creates a git repo and needs
to commit, which fails in CI where no git identity is configured.
Set GIT_AUTHOR_NAME/EMAIL and GIT_COMMITTER_NAME/EMAIL in the e2e
test harness so all tests can use git commit without extra config.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx force-pushed the feat/warn-env-plugin-shadow branch from a969c71 to 449e1d1 Compare February 1, 2026 20:56
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is ON, but a Cloud Agent failed to start.

if let Some(lock) = &stub.lock {
for (_ba, tvl) in toolset.versions.iter_mut() {
for tv in &mut tvl.versions {
if tv.ba().short == stub.tool_name {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lock injection fails for aliased tool names silently

Medium Severity

The comparison tv.ba().short == stub.tool_name uses inconsistent aliasing. stub.tool_name is stored directly from the stub's tool field without unaliasing (e.g., "nodejs", "golang", "core:node"). However, tv.ba().short is derived from a BackendArg that applies unalias_backend() during construction (converting "nodejs" to "node", "golang" to "go", stripping "core:" prefix). This causes the comparison to fail silently for any aliased tool name, preventing lock data injection.

Fix in Cursor Fix in Web

Extract the shared warning function into plugins/mod.rs and use it from
both install.rs and vfox_plugin.rs. Also move the warning call inside
the `if !dry_run` block in vfox_plugin.rs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx enabled auto-merge (squash) February 1, 2026 21:21
@jdx jdx merged commit cd32e5b into main Feb 1, 2026
36 checks passed
@jdx jdx deleted the feat/warn-env-plugin-shadow branch February 1, 2026 21:21
mise-en-dev added a commit that referenced this pull request Feb 2, 2026
### 🚀 Features

- **(generate)** implement --index flag and use task names for task-docs
--multi by @jdx in [#7944](#7944)
- **(plugins)** warn when env plugin shadows a registry tool by @jdx in
[#7953](#7953)
- **(tool-stub)** add --lock flag to generate tool-stub by @jdx in
[#7948](#7948)
- **(vfox)** add log module for Lua plugins by @jdx in
[#7949](#7949)
- **(vfox)** switch Lua runtime from Lua 5.1 to Luau by @jdx in
[#7954](#7954)

### 🐛 Bug Fixes

- **(build)** upgrade cross images to :main for C++17 support by @jdx in
[#7958](#7958)
- **(build)** update glibc check to match new cross image baseline by
@jdx in
[fc1247e](fc1247e)
- **(registry)** handle file:// URLs in normalize_remote by @jdx in
[#7947](#7947)
- **(vfox)** fix LuaLS warnings in test fixtures and add linting by @jdx
in [#7946](#7946)

### 🚜 Refactor

- unify deprecated_at! macro with warn and remove versions by @jdx in
[#7957](#7957)

### 🧪 Testing

- remove unnecessary end-of-test cleanup from e2e tests by @jdx in
[#7950](#7950)

### ◀️ Revert

- Revert "fix(build): update glibc check to match new cross image
baseline" by @jdx in
[0774bf9](0774bf9)
- Revert "fix(build): upgrade cross images to :main for C++17 support "
by @jdx in
[8dcca08](8dcca08)
- Revert "feat(vfox): switch Lua runtime from Lua 5.1 to Luau " by @jdx
in
[8b4322d](8b4322d)
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
## Summary
- Adds a warning when a vfox env-only plugin is installed with a name
that matches a registry entry
- Env-only plugins are detected by having `hooks/mise_env.lua` but not
`hooks/available.lua`
- Warning fires at install time only (not on every resolution) to avoid
noise
- Covers both CLI install (`mise plugins install`) and auto-install via
`VfoxPlugin::ensure_installed`

## Test plan
- [x] Added e2e test `test_env_plugin_shadow_warning` that creates a
fake vfox env plugin named "jq" and verifies the warning appears
- [x] Unit tests pass (444/444)
- [x] Lint passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes tool-stub resolution/installation
behavior by injecting per-platform lock data and adds new mutation paths
for existing stub files; it also touches plugin install flows (new
warning) and adds new e2e coverage.
> 
> **Overview**
> **Tool stubs can now be “locked” for reproducible installs.** `mise
generate tool-stub --lock` updates an existing stub by resolving the
exact version and writing a `[lock.platforms.*]` table with pinned
URLs/checksums (and supports bumping via `--version`), and `mise
tool-stub` consumes this lock data during installation.
> 
> **Plugin installs now warn on name collisions.** When installing an
env-only vfox plugin (has `hooks/mise_env.lua` but no
`hooks/available.lua`) whose name matches a registry tool, mise emits a
one-time warning during install.
> 
> Docs/man/completions are updated for `--lock`, and e2e tests are
expanded (new lock/warning tests, more reliable HTTP upgrade test via
random port, and git author env for test commits).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c5eff4a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
### 🚀 Features

- **(generate)** implement --index flag and use task names for task-docs
--multi by @jdx in [jdx#7944](jdx#7944)
- **(plugins)** warn when env plugin shadows a registry tool by @jdx in
[jdx#7953](jdx#7953)
- **(tool-stub)** add --lock flag to generate tool-stub by @jdx in
[jdx#7948](jdx#7948)
- **(vfox)** add log module for Lua plugins by @jdx in
[jdx#7949](jdx#7949)
- **(vfox)** switch Lua runtime from Lua 5.1 to Luau by @jdx in
[jdx#7954](jdx#7954)

### 🐛 Bug Fixes

- **(build)** upgrade cross images to :main for C++17 support by @jdx in
[jdx#7958](jdx#7958)
- **(build)** update glibc check to match new cross image baseline by
@jdx in
[fc1247e](jdx@fc1247e)
- **(registry)** handle file:// URLs in normalize_remote by @jdx in
[jdx#7947](jdx#7947)
- **(vfox)** fix LuaLS warnings in test fixtures and add linting by @jdx
in [jdx#7946](jdx#7946)

### 🚜 Refactor

- unify deprecated_at! macro with warn and remove versions by @jdx in
[jdx#7957](jdx#7957)

### 🧪 Testing

- remove unnecessary end-of-test cleanup from e2e tests by @jdx in
[jdx#7950](jdx#7950)

### ◀️ Revert

- Revert "fix(build): update glibc check to match new cross image
baseline" by @jdx in
[0774bf9](jdx@0774bf9)
- Revert "fix(build): upgrade cross images to :main for C++17 support "
by @jdx in
[8dcca08](jdx@8dcca08)
- Revert "feat(vfox): switch Lua runtime from Lua 5.1 to Luau " by @jdx
in
[8b4322d](jdx@8b4322d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants