Skip to content

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Dec 5, 2025

Summary

  • Add a new --bootstrap flag to mise generate tool-stub that wraps the generated tool stub in a shell script that automatically installs mise if not already present
  • Add stdin support to mise tool-stub command (reading TOML from -)

When --bootstrap is enabled:

  • Fetches and embeds the official mise installer (with minisign verification)
  • Generates a bash wrapper that checks for mise and installs if needed
  • Uses heredoc to pass the TOML configuration to mise tool-stub -

This allows tool stubs to be used on systems that don't have mise installed yet - the stub will bootstrap mise automatically.

Test plan

  • New e2e test test_generate_tool_stub_bootstrap verifies the bootstrap output structure
  • Tested manually: mise generate tool-stub ./bin/test --url "https://example.com/tool.tar.gz" --skip-download --bootstrap

🤖 Generated with Claude Code


Note

Adds --bootstrap/--bootstrap-version to mise generate tool-stub to create self-bootstrapping bash stubs that install mise if needed, with runtime support, docs, completions, and tests.

  • CLI (generate/tool-stub):
    • Add --bootstrap and --bootstrap-version flags to generate a bash wrapper that installs mise (via verified install.sh) and then runs the stub through mise.
    • Preserve bootstrap format when appending platforms or fetching checksums.
    • Embed TOML in comment block delimited by # MISE_TOOL_STUB:/# :MISE_TOOL_STUB.
  • Runtime (tool-stub execution):
    • Support parsing embedded TOML from bootstrap stubs (extract_toml_from_bootstrap) and default bin/tool detection unchanged.
  • Docs & UX:
    • Update docs/cli/generate/tool-stub.md, man/man1/mise.1, mise.usage.kdl with new flags and examples.
    • Update Fig completions (xtasks/fig/src/mise.ts) for new options.
  • Tests:
    • Add e2e e2e/generate/test_generate_tool_stub_bootstrap validating wrapper structure, append behavior, and execution.

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

Copilot AI review requested due to automatic review settings December 5, 2025 16:53
Copy link

@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.

Bug: Missing bin field causes wrong binary name from stdin

The generator omits the bin field from TOML when it matches the stub filename (as an optimization). However, when the bootstrap script executes mise tool-stub - with stdin input, from_stdin() uses "tool-stub" as the stub name. Since the TOML lacks a bin field, the code defaults stub.bin to "tool-stub" instead of the actual binary name. This causes the tool to search for and execute the wrong binary. The issue particularly affects --skip-download usage since no automatic bin detection occurs.

src/cli/generate/tool_stub.rs#L172-L178

// Update bin if provided and different from stub filename
if let Some(bin) = &self.bin
&& bin != stub_filename
{
doc["bin"] = toml_edit::value(bin);
}

src/cli/tool_stub.rs#L129-L133

mise/src/cli/tool_stub.rs

Lines 129 to 133 in 8d68351

// Set bin to filename if not specified
if stub.bin.is_none() {
stub.bin = Some(stub_name.to_string());
}

Fix in Cursor Fix in Web



// For stdin, use a placeholder path (caching won't work but that's fine)
let stub_path = if is_stdin {
PathBuf::from("-")
Copy link

Choose a reason for hiding this comment

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

Bug: Stdin path causes metadata lookup failure in caching

When reading tool stub configuration from stdin (file is -), the code sets stub_path to PathBuf::from("-") with a comment saying "caching won't work but that's fine." However, the code then unconditionally calls BinPathCache::cache_key(stub_path)? which attempts stub_path.metadata()?.modified()?. Since the file - doesn't exist, this will return an IO error and fail the entire operation. The bootstrap-generated scripts use mise tool-stub - "$@" to pass TOML via stdin, so this bug breaks the core functionality of the new --bootstrap flag.

Additional Locations (1)

Fix in Cursor Fix in Web

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.0 x -- echo 19.1 ± 0.3 18.5 20.1 1.00
mise x -- echo 19.3 ± 0.4 18.6 21.0 1.01 ± 0.03

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.0 env 18.5 ± 0.4 17.8 21.8 1.00
mise env 18.8 ± 0.6 18.1 22.9 1.02 ± 0.04

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.0 hook-env 18.6 ± 0.3 18.0 19.6 1.00
mise hook-env 18.7 ± 0.4 18.1 21.2 1.01 ± 0.03

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.0 ls 15.8 ± 0.3 15.3 17.0 1.00
mise ls 16.0 ± 0.4 15.4 17.9 1.01 ± 0.03

xtasks/test/perf

Command mise-2025.12.0 mise Variance
install (cached) 107ms 107ms +0%
ls (cached) 64ms 65ms -1%
bin-paths (cached) 70ms 71ms -1%
task-ls (cached) 419ms 420ms +0%

Copy link
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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@jdx jdx changed the title feat(cli): add --bootstrap flag to mise generate tool-stub feat(tool-stubs): add --bootstrap flag to mise generate tool-stub Dec 8, 2025
jdx and others added 6 commits December 8, 2025 11:09
Add a new --bootstrap flag that wraps the generated tool stub in a shell
script that automatically installs mise if it's not already present.

When enabled:
- Fetches and embeds the official mise installer (with minisign verification)
- Generates a bash wrapper that checks for mise and installs if needed
- Uses heredoc to pass the TOML configuration to `mise tool-stub -`

Also adds stdin support to `mise tool-stub` command (reading from `-`).

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

Co-Authored-By: Claude <[email protected]>
…support editing

- Use temp file instead of stdin heredoc so tools can read stdin
- Add --bootstrap-version flag to pin mise version
- Check PATH for mise first, fall back to ~/.local/bin/mise
- Support editing existing bootstrap stubs (extracts/preserves TOML)
- Add extract_toml_from_stub() and is_bootstrap_stub() helpers
- Update e2e test to verify append and execution

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

Co-Authored-By: Claude <[email protected]>
Move --bootstrap and --bootstrap-version flags before --fetch to satisfy
the clap-sort test requirement for alphabetically ordered flags.

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

Co-Authored-By: Claude <[email protected]>
When appending platforms to an existing bootstrap stub without
explicitly passing --bootstrap flag, the bootstrap wrapper was lost.
Now check if the existing file is a bootstrap stub and preserve that
format automatically.

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

Co-Authored-By: Claude <[email protected]>
@jdx jdx force-pushed the feat/tool-stub-bootstrap branch from 7326923 to 7f9c447 Compare December 8, 2025 17:11
jdx and others added 5 commits December 8, 2025 11:17
The bootstrap wrapper uses a temp file approach, not stdin, so stdin
support is unnecessary. This also fixes the metadata lookup failure
that occurred when trying to generate cache keys for stdin paths.

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

Co-Authored-By: Claude <[email protected]>
Instead of temp files or stdin, store TOML in a comment block that
mise tool-stub can parse directly from the bootstrap script:

  # MISE_TOOL_STUB:
  # version = "1.7.1"
  # [platforms.linux-x64]
  # url = "..."
  # :MISE_TOOL_STUB

The script passes $0 (itself) to mise tool-stub, which extracts
and parses the TOML from the comment markers.

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

Co-Authored-By: Claude <[email protected]>
@jdx jdx enabled auto-merge (squash) December 8, 2025 17:44
The fix for preserving bootstrap format when appending platforms was
already in place, but the test still used --bootstrap flag. Update
test to verify that format is preserved even without the flag.

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

Co-Authored-By: Claude <[email protected]>
];
// Check if original was a bootstrap stub and preserve that format
if is_bootstrap_stub(&content) {
self.wrap_with_bootstrap(&toml_content).await
Copy link

Choose a reason for hiding this comment

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

Bug: Pinned bootstrap version lost when regenerating bootstrap stub

When a bootstrap stub is regenerated (either via --fetch or when appending platforms to an existing bootstrap stub), the originally pinned --bootstrap-version is silently lost. The code correctly detects that the existing file is a bootstrap stub and calls wrap_with_bootstrap, but self.bootstrap_version is always None in these cases because --bootstrap-version requires --bootstrap to be explicitly passed. This causes the stub to be regenerated with the latest mise installer instead of preserving the originally pinned version, potentially breaking version reproducibility.

Additional Locations (1)

Fix in Cursor Fix in Web

@jdx jdx merged commit 894d502 into main Dec 8, 2025
29 checks passed
@jdx jdx deleted the feat/tool-stub-bootstrap branch December 8, 2025 18:04
jdx pushed a commit that referenced this pull request Dec 8, 2025
### 🚀 Features

- **(npm)** support pnpm as a package manager for npm backend by
@risu729 in [#7214](#7214)
- **(tool-stubs)** add --bootstrap flag to mise generate tool-stub by
@jdx in [#7203](#7203)

### 🐛 Bug Fixes

- **(alpine)** increase alpine release timeout to 60 minutes by @jdx in
[#7188](#7188)
- **(bun)** use x64-baseline for aarch64 on Windows by @roele in
[#7190](#7190)
- **(tools)** allow using env vars in tools by @antonsergeyev in
[#7205](#7205)
- add cfg(feature = "self_update") to statics only used by that feature
by @jdx in [#7185](#7185)

### 📚 Documentation

- Update registry.md by @jdx in
[ad11ad1](ad11ad1)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:alpine docker digest to 2909cce by
@renovate[bot] in [#7196](#7196)
- update fedora:43 docker digest to 6cd815d by @renovate[bot] in
[#7195](#7195)
- update ghcr.io/jdx/mise:deb docker digest to 1893530 by @renovate[bot]
in [#7198](#7198)
- update ghcr.io/jdx/mise:copr docker digest to 0447a85 by
@renovate[bot] in [#7197](#7197)

### 📦 Registry

- add Supabase CLI to registry.toml by @bodadotsh in
[#7206](#7206)
- add cmake aqua backend by @mangkoran in
[#7186](#7186)

### New Contributors

- @antonsergeyev made their first contribution in
[#7205](#7205)
- @bodadotsh made their first contribution in
[#7206](#7206)

## 📦 Aqua Registry Updates

#### New Packages (3)

- [`skanehira/ghost`](https://github.com/skanehira/ghost)
- [`square/certigo`](https://github.com/square/certigo)
- [`steveyegge/beads`](https://github.com/steveyegge/beads)

#### Updated Packages (8)

- [`apache/maven`](https://github.com/apache/maven)
- [`apple/container`](https://github.com/apple/container)
- [`aquasecurity/trivy`](https://github.com/aquasecurity/trivy)
- [`charmbracelet/crush`](https://github.com/charmbracelet/crush)
- [`goreleaser/goreleaser`](https://github.com/goreleaser/goreleaser)
- [`goreleaser/nfpm`](https://github.com/goreleaser/nfpm)
- [`ninja-build/ninja`](https://github.com/ninja-build/ninja)
- [`twpayne/chezmoi`](https://github.com/twpayne/chezmoi)
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