Skip to content

fix(github): preserve tool options like filter_bins when version specified via CLI#8888

Merged
jdx merged 4 commits intomainfrom
fix/bin-paths-preserve-tool-options
Apr 4, 2026
Merged

fix(github): preserve tool options like filter_bins when version specified via CLI#8888
jdx merged 4 commits intomainfrom
fix/bin-paths-preserve-tool-options

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 4, 2026

Summary

  • When a tool version is provided as a CLI argument (e.g. mise bin-paths tool@version), the ToolsetBuilder was creating a new ToolRequest without options, then destructively merging it over the config entry — losing filter_bins and other tool options.
  • Now carries over options from the existing config when the CLI arg doesn't specify its own.

Closes #8885

Test plan

  • Added e2e assertion to test_github_filter_bins verifying mise bin-paths github:jgm/pandoc@3.8.2 returns the .mise-bins path
  • cargo check passes
  • All pre-commit lints pass

🤖 Generated with Claude Code


Note

Medium Risk
Touches tool resolution/merging and bin-path discovery for the GitHub/Aqua backends, which could subtly change PATH/bin exposure for some tools. Changes are small and covered by an added e2e assertion, but impact core CLI behavior.

Overview
Fixes a regression where CLI-specified tool versions (e.g. mise bin-paths tool@version) could drop configured tool options like filter_bins by copying options from the config request when the CLI request doesn’t specify its own.

Updates GitHub and Aqua backends’ list_bin_paths to also return the .mise-bins directory whenever it already exists on disk (not only when the relevant option is present), and adds an e2e check ensuring bin-paths returns the filtered .mise-bins path for github:jgm/pandoc@3.8.2.

Reviewed by Cursor Bugbot for commit 94fb91c. Bugbot is set up for automated code reviews on this repo. Configure here.

…ified via CLI

When a tool version is provided as a CLI argument (e.g. `mise bin-paths
tool@version`), the ToolsetBuilder was creating a new ToolRequest without
options, then destructively merging it over the config entry — losing
filter_bins and other tool options. Now carries over options from the
existing config when the CLI arg doesn't specify its own.

Closes #8885

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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 ensures that tool options, such as filter_bins, are carried over from the configuration when tools are specified via CLI arguments. It also adds an E2E test to verify this functionality. The review feedback identifies a potential bug where CLI-provided options could be overwritten by configuration defaults and suggests an optimization to avoid unnecessary operations when configuration options are empty.

Comment thread src/toolset/builder.rs
Comment on lines +172 to +174
if let Some(opts) = &config_options {
tvr.set_options(opts.clone());
}
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.

high

This block unconditionally overwrites the tool options with those from the configuration. This will cause any options provided via the CLI (e.g., mise x "tool[opt=val]") to be lost if the tool is also defined in a configuration file. It should only apply the configuration options if the CLI-provided options are empty, consistent with the logic on line 148. Additionally, the "latest" version case below (lines 178-182) is missing this carry-over logic entirely and should also be updated to respect configuration options.

Suggested change
if let Some(opts) = &config_options {
tvr.set_options(opts.clone());
}
if let Some(opts) = &config_options {
if tvr.options().is_empty() {
tvr.set_options(opts.clone());
}
}

Comment thread src/toolset/builder.rs
Comment on lines +140 to +144
let config_options = ts
.versions
.get(&args[0].ba)
.and_then(|tvl| tvl.requests.first())
.map(|tvr| tvr.options());
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

Consider filtering out empty options here. This avoids unnecessary clones and set_options calls later in the loop if the configuration entry exists but has no options defined.

            let config_options = ts
                .versions
                .get(&args[0].ba)
                .and_then(|tvl| tvl.requests.first())
                .map(|tvr| tvr.options())
                .filter(|o| !o.is_empty());

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 4, 2026

Greptile Summary

This PR fixes a bug where specifying a tool version via CLI (e.g. mise bin-paths github:jgm/pandoc@3.8.2) would drop config-specified tool options like filter_bins, causing the wrong binary path to be returned. The fix is two-pronged: ToolsetBuilder::load_runtime_args now carries config options into CLI requests when the CLI request has none, and github.rs/aqua.rs add a mise_bins_dir.is_dir() filesystem fallback so that tools already installed with filter_bins correctly surface .mise-bins even when the request carries no options.

Confidence Score: 5/5

Safe to merge — targeted, well-scoped fix with a matching e2e regression test.

Both fix strategies (option propagation in builder and filesystem fallback in backends) are correct and complementary. No P0/P1 issues found. The is_dir() fallback is a safe, idempotent read-only check, and the options carry-over only applies when the CLI request carries no options of its own.

No files require special attention.

Important Files Changed

Filename Overview
src/toolset/builder.rs Adds option carry-over from config into CLI ToolRequests; logic is correct and only triggers when CLI arg has no options of its own.
src/backend/github.rs Adds mise_bins_dir.is_dir() fallback so already-filtered installs return the correct bin path even when the ToolRequest carries no filter_bins option.
src/backend/aqua.rs Applies the same mise_bins_dir.is_dir() fallback pattern as github.rs for aqua's symlink-bins installations.
e2e/backend/test_github_filter_bins Adds a regression assertion verifying mise bin-paths github:jgm/pandoc@3.8.2 returns the .mise-bins path when the tool was installed with filter_bins.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[CLI arg: tool@version] --> B{arg has options?}
    B -- Yes --> C[Use CLI options as-is]
    B -- No --> D{config has options\nfor this tool?}
    D -- Yes --> E[Copy config options\nonto CLI ToolRequest]
    D -- No --> F[No options]
    E --> G[ToolRequest with\ncarried-over options]
    F --> G
    C --> G
    G --> H[Backend list_bin_paths]
    H --> I{github: get_filter_bins\nis some?}
    I -- Yes --> J[Return .mise-bins dir]
    I -- No --> K{.mise-bins dir\nexists on disk?}
    K -- Yes --> J
    K -- No --> L[discover_bin_paths]
Loading

Reviews (3): Last reviewed commit: "fix(github): detect .mise-bins directory..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 4, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 x -- echo 23.6 ± 0.7 22.0 27.2 1.03 ± 0.05
mise x -- echo 23.0 ± 0.9 22.0 33.5 1.00

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 env 23.0 ± 0.7 21.4 26.0 1.00
mise env 24.7 ± 0.5 23.7 29.9 1.07 ± 0.04

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 hook-env 23.7 ± 0.8 22.0 27.2 1.00
mise hook-env 24.3 ± 0.6 22.7 26.5 1.02 ± 0.04

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.3 ls 21.2 ± 0.6 19.9 27.4 1.00
mise ls 22.4 ± 0.4 21.4 24.9 1.06 ± 0.04

xtasks/test/perf

Command mise-2026.4.3 mise Variance
install (cached) 156ms 157ms +0%
ls (cached) 81ms 82ms -1%
bin-paths (cached) 86ms 86ms +0%
task-ls (cached) 854ms 829ms +3%

@jdx jdx enabled auto-merge (squash) April 4, 2026 14:02
…er_bins

When `mise bin-paths github:tool@version` is called without the tool being
in a config file, filter_bins options aren't available from config. Fall back
to checking if .mise-bins directory exists on disk (created during install).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jdx jdx merged commit f326d2f into main Apr 4, 2026
36 checks passed
@jdx jdx deleted the fix/bin-paths-preserve-tool-options branch April 4, 2026 14:58
jdx pushed a commit that referenced this pull request Apr 5, 2026
### 🚀 Features

- **(ci)** auto-convert external PRs to draft mode by @jdx in
[#8896](#8896)
- **(deps)** add `depends` field for user-specified tool dependencies by
@cprecioso in [#8776](#8776)
- **(dotnet)** support runtime-only installs by @fragon10 in
[#8524](#8524)
- **(npm)** apply install_before to transitive dependencies by @risu729
in [#8851](#8851)
- **(task)** allow passing arguments to task dependencies via
{{usage.*}} templates by @jdx in
[#8893](#8893)
- add options field to BackendListVersionsCtx by @esteve in
[#8875](#8875)

### 🐛 Bug Fixes

- **(backend)** filter PEP 440 .dev versions in fuzzy version matching
by @richardthe3rd in [#8849](#8849)
- **(ci)** update COPR BuildRequires rust version to match MSRV 1.88 by
@jdx in [#8911](#8911)
- **(ci)** add Ruby build dependencies to e2e Docker image by @jdx in
[#8910](#8910)
- **(ci)** add missing build dependencies to e2e Docker image by @jdx in
[#8912](#8912)
- **(ci)** add missing build dependencies to e2e Docker image by @jdx in
[#8914](#8914)
- **(ci)** use Node 24 LTS for corepack e2e test by @jdx in
[#8915](#8915)
- **(ci)** add libxml2 and pkg-config to e2e Docker image by @jdx in
[#8917](#8917)
- **(ci)** add libxml2-dev to e2e image and disable Swift SPM tests by
@jdx in [#8918](#8918)
- **(docs)** use sans-serif font for badges by @jdx in
[#8887](#8887)
- **(env)** parse --env=VALUE and -E=VALUE flag forms correctly by @jdx
in [#8889](#8889)
- **(exec)** use i64::from() for seccomp syscall numbers to survive
autofix by @jdx in [#8882](#8882)
- **(github)** preserve tool options like filter_bins when version
specified via CLI by @jdx in
[#8888](#8888)
- **(github)** use alias-specific options when tool_alias has its own
config by @jdx in [#8892](#8892)
- **(install)** add locked_verify_provenance setting and detect github
attestations at lock time by @jdx in
[#8901](#8901)
- **(lock)** prune stale version entries during filtered `mise lock
<tool>` runs by @altendky in
[#8599](#8599)
- **(python)** use lockfile URL for precompiled installs by @hehaoqian
in [#8750](#8750)
- **(release)** verify all build targets succeed before releasing by
@jdx in [#8886](#8886)
- **(ruby)** support build revisions for precompiled binaries in
mise.lock by @jdx in [#8900](#8900)
- **(swift)** fall back to Ubuntu 24.04 for unsupported Ubuntu versions
by @jdx in [#8916](#8916)
- **(zsh)** avoid duplicate trust warning after cd by @timothysparg in
[#8898](#8898)
- update flake.lock and add fix for rust-bindgen to default.nix by
@esteve in [#8874](#8874)
- when direnv diff is empty, do not try to parse it by @yaleman in
[#8857](#8857)
- skip trust check for plain .tool-versions in task list by @dportalesr
in [#8876](#8876)

### 🚜 Refactor

- **(go)** rename go_* settings to go.* namespace by @jdbruijn in
[#8598](#8598)

### 📚 Documentation

- **(tasks)** clarify task_config.includes behavior by @risu729 in
[#8905](#8905)

### 🧪 Testing

- **(ci)** run e2e tests inside Docker containers by @jdx in
[#8899](#8899)

### 📦️ Dependency Updates

- bump ubi from 0.8 to 0.9 by @jdx in
[#8906](#8906)
- bump zip from 3 to 8 by @jdx in
[#8908](#8908)
- update lockfile deps (hold back rattler) by @jdx in
[#8909](#8909)
- update bun.lock by @jdx in
[#8913](#8913)

### 📦 Registry

- add turso
([github:tursodatabase/turso-cli](https://github.com/tursodatabase/turso-cli))
by @kenn in [#8884](#8884)
- remove carp test by @jdx in
[#8894](#8894)

### Chore

- **(ci)** add workflow to warn PRs modifying vendored aqua-registry by
@jdx in [#8897](#8897)
- **(ci)** use github.token for draft conversion in auto-draft workflow
by @jdx in [#8903](#8903)
- remove deprecated settings older than 12 months by @jdx in
[#8904](#8904)

### New Contributors

- @dportalesr made their first contribution in
[#8876](#8876)
- @timothysparg made their first contribution in
[#8898](#8898)
- @hehaoqian made their first contribution in
[#8750](#8750)
- @jdbruijn made their first contribution in
[#8598](#8598)
- @cprecioso made their first contribution in
[#8776](#8776)
- @yaleman made their first contribution in
[#8857](#8857)
- @kenn made their first contribution in
[#8884](#8884)
- @fragon10 made their first contribution in
[#8524](#8524)

## 📦 Aqua Registry Updates

#### New Packages (6)

- [`ahkohd/oyo`](https://github.com/ahkohd/oyo)
- [`bellicose100xp/jiq`](https://github.com/bellicose100xp/jiq)
- [`kurama/dealve-tui`](https://github.com/kurama/dealve-tui)
- [`micahkepe/jsongrep`](https://github.com/micahkepe/jsongrep)
- [`textfuel/lazyjira`](https://github.com/textfuel/lazyjira)
- [`ubugeeei/vize`](https://github.com/ubugeeei/vize)

#### Updated Packages (1)

- [`sigstore/cosign`](https://github.com/sigstore/cosign)
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.

1 participant