Skip to content

feat(system): add mise system use and mise system upgrade#10346

Merged
jdx merged 3 commits into
mainfrom
claude/system-use-upgrade
Jun 12, 2026
Merged

feat(system): add mise system use and mise system upgrade#10346
jdx merged 3 commits into
mainfrom
claude/system-use-upgrade

Conversation

@jdx

@jdx jdx commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Follow-up to #10326, adding the two commands discussed there: mise system use and mise system upgrade.

mise system use

mise use for system packages — writes entries to [system.packages] and installs whatever is missing in one step:

mise system use apt:curl brew:jq     # local mise.toml
mise system use -g brew:ffmpeg       # global config
mise system use apt:curl@8.5.0-2     # @version pins, like mise use
  • @version mirrors mise use tool@version (@latest = no pin). brew is exempt from @ parsing since @ is part of brew formula names (brew:postgresql@17 is the formula, not a pin) — and brew bottles can't be pinned anyway.
  • Config writing goes through a new MiseToml::update_system_package (toml_edit, preserves formatting/comments, implicit [system] header so only [system.packages] is rendered).
  • File selection reuses resolve_target_config_path like mise set (-g, -p PATH, -e ENV).
  • A manager that isn't available on this machine is added to the config without installing (with a note) rather than erroring — writing apt: lines from a Mac into a shared repo config is the point of a declarative file. Typo'd managers and bad specs still fail before anything is written.

mise system upgrade

Refreshes metadata and upgrades configured packages that are already installed; missing ones are skipped with a pointer at mise system install:

manager invocation
apt apt-get update + apt-get install -y --only-upgrade -- …
dnf dnf upgrade -y --refresh -- …
pacman pacman -Sy + pacman -S --noconfirm --needed -- … (partial-upgrade caveat documented)
brew default = install: pours the formula's current bottle, replaces the old keg, repoints links

Implemented as a new SystemPackageManager::upgrade() trait method defaulting to install() (exactly right for brew), with apt/dnf/pacman overrides.

Refactor

The per-manager loop (manager filter, disabled/unavailable handling, pin filtering for managers without pin support, confirmation prompt) is factored out of SystemInstall into a shared cli/system/driver.rs used by install, upgrade, and use — no behavior change for install.

Tests

  • Unit: parse_use_spec (incl. brew @ exemption, apt arch qualifiers, @latest), update_system_package TOML snapshot. 27 system/config tests pass.
  • E2E: new e2e/cli/test_system_use (cross-platform, dry-run based); test_system_install_apt extended with real use + upgrade runs.
  • Smoke-tested on macOS: system use apt:bc brew:xz wrote both entries, noted apt as config-only, poured xz; system upgrade -n no-ops when current.

🤖 Generated with Claude Code


Note

Medium Risk
New commands can run elevated package-manager operations (sudo/apt/dnf/pacman) and modify mise.toml; behavior is gated behind experimental mise system but mistakes could affect system packages on the host.

Overview
Adds mise system use and mise system upgrade to the experimental [system.packages] workflow, plus docs, usage specs, man pages, shell completion metadata, and e2e coverage.

mise system use mirrors mise use: it writes "manager:package" = "version" into mise.toml (via new MiseToml::update_system_package), with -g / -p / -e targeting like other write commands, then runs install for what’s missing. CLI specs use manager:package[@version]; brew keeps @ in formula names only. Unavailable managers on the current OS are recorded in config without failing install (cross-platform shared configs).

mise system upgrade refreshes metadata and upgrades only packages already installed; missing ones are skipped. apt/dnf/pacman get manager-specific upgrade commands; SystemPackageManager::upgrade() defaults to install() (brew).

Refactor: per-manager filtering, prompts, and pin handling move from SystemInstall into shared cli/system/driver.rs for install, upgrade, and use.

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

Summary by CodeRabbit

  • New Features

    • Added mise system upgrade and mise system use; use pins packages to config (local/global/env) and installs missing packages; upgrade refreshes manager metadata and upgrades only already-installed configured packages.
  • Documentation

    • New CLI docs, man page updates, examples, and updated apt/brew/dnf/pacman guides describing behavior and flags.
  • Tests

    • New end-to-end tests for system use and system upgrade.
  • Completion

    • Shell completion updated for the new subcommands and options.

`mise system use` is `mise use` for system packages: writes
"manager:package" = "version" entries to mise.toml (local by default,
global with -g, @Version pins like mise use) and installs whatever is
missing. Managers unavailable on the current machine are added to the
config without installing, so shared cross-platform configs can be
authored from any OS.

`mise system upgrade` (alias `up`) refreshes package manager metadata
and upgrades the configured packages that are already installed:
apt-get install --only-upgrade, dnf upgrade --refresh, pacman -Sy +
-S --needed, and brew pours the formula's current bottle replacing the
old keg. Missing packages are skipped with a pointer at install.

The install/upgrade per-manager loop is factored into a shared driver
used by all three commands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 673331ff-1213-4ef6-bc61-faeab613075a

📥 Commits

Reviewing files that changed from the base of the PR and between 5549334 and ce506a4.

📒 Files selected for processing (7)
  • docs/cli/system/upgrade.md
  • docs/system-packages/index.md
  • man/man1/mise.1
  • mise.usage.kdl
  • src/cli/system/driver.rs
  • src/cli/system/upgrade.rs
  • src/cli/system/use.rs
✅ Files skipped from review due to trivial changes (2)
  • docs/cli/system/upgrade.md
  • docs/system-packages/index.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • man/man1/mise.1
  • mise.usage.kdl
  • src/cli/system/upgrade.rs
  • src/cli/system/use.rs
  • src/cli/system/driver.rs

📝 Walkthrough

Walkthrough

Adds mise system upgrade and mise system use commands, a shared driver to run installs/upgrades, per-manager upgrade implementations, spec parsing and config-write helpers for use, install refactoring to use the driver, CLI wiring, docs, completions, and e2e tests.

Changes

System Package Upgrade and Use Features

Layer / File(s) Summary
Documentation and CLI Contracts
docs/.vitepress/cli_commands.ts, docs/cli/index.md, docs/cli/system.md, docs/cli/system/upgrade.md, docs/cli/system/use.md, docs/system-packages/apt.md, docs/system-packages/brew.md, docs/system-packages/dnf.md, docs/system-packages/pacman.md, docs/system-packages/index.md, man/man1/mise.1, mise.usage.kdl, xtasks/fig/src/mise.ts
CLI reference pages, manpage, usage KDL, and shell completion specs document system upgrade and system use syntax, flags, examples, and manager-specific upgrade behavior.
Shared Driver Infrastructure
src/cli/system/driver.rs
New module defines Action enum (Install/Upgrade), DriverOpts struct, and async run function that orchestrates manager filtering, availability checks, target computation, confirmation, and per-manager install/upgrade execution.
Upgrade Command and Manager Implementations
src/cli/system/upgrade.rs, src/system/packages/mod.rs, src/system/packages/apt.rs, src/system/packages/dnf.rs, src/system/packages/pacman.rs
SystemUpgrade clap struct parses packages and manager filter. SystemPackageManager::upgrade added (default delegating to install). Apt, Dnf, and Pacman provide upgrade implementations that refresh metadata and run targeted upgrades respecting pins.
Use Command with Config and Parsing
src/cli/system/use.rs, src/system/mod.rs, src/config/config_file/mise_toml.rs
SystemUse CLI accepts manager:package[@Version] specs and config target options. parse_use_spec parses specs (brew @ semantics), packages_from_requests aggregates per-manager requests, and MiseToml::update_system_package updates TOML and in-memory config.
Command Dispatch and Wiring
src/cli/system/mod.rs
New modules declared; Commands enum extended with Upgrade and Use variants; System::run dispatches to their runners.
Install Command Refactoring
src/cli/system/install.rs
SystemInstall::run now constructs DriverOpts and delegates to driver::run instead of duplicating manager filtering, pin handling, and prompting logic.
End-to-End Testing
e2e/cli/test_system_install_apt, e2e/cli/test_system_use
E2E tests validate upgrade metadata refresh and only-upgrade semantics, use dry-run/config-writing semantics, and integration between config and install flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • jdx/mise#10326: Introduces the [system.packages] config section and base mise system install/status commands that this PR extends with use/upgrade and driver-based refactoring.

Poem

🐰 Packages hop into place, pinned by @version!
Upgrades refresh the cache before each action,
A driver steers install and upgrade alike—
use writes config, upgrade refreshes fast,
Completion made simple, one shared path for all. 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding two new CLI subcommands (mise system use and mise system upgrade) under the system command.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d1dd5ec. Configure here.

Comment thread src/cli/system/driver.rs
Comment thread src/cli/system/use.rs
Comment thread src/cli/system/use.rs
@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds mise system use and mise system upgrade to the experimental [system.packages] workflow, plus a shared driver.rs that factors the per-manager execution loop out of install for reuse across all three sub-commands.

  • mise system use validates manager specs before touching the file, writes [system.packages] entries via MiseToml::update_system_package (preserves comments/formatting), then runs the driver in install mode — unavailable managers are written to config with an info note rather than erroring, enabling declarative cross-platform configs.
  • mise system upgrade refreshes metadata and upgrades only already-installed packages per manager; apt and dnf have dedicated upgrade() impls with --only-upgrade/--refresh; pacman and brew reuse their respective semantics; the driver re-queries installed versions post-upgrade and reports what actually changed.
  • The install refactor delegates to driver::run with no intended behavior change; the explicit flag correctly distinguishes CLI-specified packages (hard error on unavailable) from config-only runs (silent skip).

Confidence Score: 5/5

Safe to merge; the new commands write config and invoke OS package managers correctly, with dry-run, confirmation prompts, and skip-missing guards limiting blast radius

The implementation is thorough and consistent: manager validation fires before any config write, deduplication logic is uniform between the entries list and the by_mgr map, post-upgrade version diffing correctly tracks installed (not pinned) versions, and the brew @ exemption is tested. The only gap is the missing --update flag on use, which can cause a 'package not found' failure on systems with stale apt/dnf lists — a real but easily worked-around inconvenience rather than correctness breakage.

src/cli/system/use.rs — lacks the --update/-U flag that mise system install exposes

Important Files Changed

Filename Overview
src/cli/system/driver.rs New shared execution loop for install/upgrade/use; correctly handles filters, disabled/unavailable managers, pin support, and confirmation prompts; post-upgrade diff reporting looks sound
src/cli/system/use.rs New mise system use command; deduplication is consistent between entries and by_mgr (both last-wins); missing --update/-U flag means stale package lists won't be refreshed before the implicit install step
src/cli/system/upgrade.rs New mise system upgrade command; delegates cleanly to driver with Action::Upgrade; metadata refresh is handled inside each manager's upgrade() impl rather than via update: true, which is correct
src/system/mod.rs Adds parse_use_spec and packages_from_requests; brew @ exemption is correctly handled; @latest normalization to None is consistent with packages_from_config's 'latest' -> None mapping
src/system/packages/apt.rs New upgrade() always refreshes lists before installing; --only-upgrade prevents races; dry-run correctly prints both update and install commands
src/config/config_file/mise_toml.rs New update_system_package uses established toml_edit patterns; preserves key decorations (comments/whitespace) on update; in-memory SystemTomlConfig is also kept in sync

Reviews (2): Last reviewed commit: "fix(system): address review findings in ..." | Re-trigger Greptile

Comment thread src/cli/system/use.rs Outdated
Comment thread src/cli/system/use.rs Outdated

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/system-packages/index.md (1)

47-49: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the install-only wording.

mise system use also installs missing packages after writing config, so this sentence is now false.

♻️ Suggested fix
- mise install will print a one-time hint when packages are missing, but only `mise system install` ever installs anything.
+ mise install will print a one-time hint when packages are missing, but only `mise system install` and `mise system use` ever install anything.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/system-packages/index.md` around lines 47 - 49, Update the misleading
sentence that says "Manual installation only — mise never installs system
packages..." in docs/system-packages/index.md: change it to note that while
`mise install` only prints a one-time hint, both `mise system install` and `mise
system use` can install missing system packages (with `mise system use`
installing after writing config), so rephrase to reflect that `mise system
install` and `mise system use` will perform installation while `mise install`
does not.
mise.usage.kdl (1)

2856-2860: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update parent system help text to include system use installs.

Line 2859 says system packages are only installed via mise system install, but mise system use now also installs missing packages. This creates a user-facing contract contradiction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mise.usage.kdl` around lines 2856 - 2860, Update the parent "system" help
text to reflect that missing system packages can be installed by both commands:
change the sentence that currently states "they are only ever installed when
explicitly requested with `mise system install`" to mention `mise system use` as
well (e.g., "they are installed when explicitly requested with `mise system
install` or when `mise system use` installs missing packages"). Ensure the
message references the "system" help block and the command names `mise system
install` and `mise system use` so users see the accurate contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/system-packages/index.md`:
- Around line 83-87: The docs currently state that `mise system upgrade` will
respect version pins for configured packages, which is too broad; update the
text around `mise system upgrade` in the system-packages doc and the
corresponding man page to clarify that only package managers which support
pinned upgrades will honor pins (the shared driver will skip pin requests for
managers that don't, e.g., pacman), and phrase it like “Packages pinned in
config are honored only by managers that support pinned upgrades; managers
without pin support will skip pinned requests.” Ensure the same qualified
wording replaces the current unqualified claim in both places.

In `@src/cli/system/use.rs`:
- Around line 58-69: The current loop over self.packages deduplicates config
entries by key but keeps all PackageRequest objects in by_mgr, causing
inconsistent behavior for duplicate package names with different versions;
update the logic so both entries and by_mgr deduplicate by package name and
apply last-wins: when computing key (format!("{mgr}:{}", request.name)) if an
existing entry exists replace its version instead of skipping, and for by_mgr
replace any existing PackageRequest with the same request.name (or same
name+mgr) with the new request rather than pushing a duplicate. Ensure you
update the code paths that use entries and by_mgr so they now reflect the
last-specified version consistently.

---

Outside diff comments:
In `@docs/system-packages/index.md`:
- Around line 47-49: Update the misleading sentence that says "Manual
installation only — mise never installs system packages..." in
docs/system-packages/index.md: change it to note that while `mise install` only
prints a one-time hint, both `mise system install` and `mise system use` can
install missing system packages (with `mise system use` installing after writing
config), so rephrase to reflect that `mise system install` and `mise system use`
will perform installation while `mise install` does not.

In `@mise.usage.kdl`:
- Around line 2856-2860: Update the parent "system" help text to reflect that
missing system packages can be installed by both commands: change the sentence
that currently states "they are only ever installed when explicitly requested
with `mise system install`" to mention `mise system use` as well (e.g., "they
are installed when explicitly requested with `mise system install` or when `mise
system use` installs missing packages"). Ensure the message references the
"system" help block and the command names `mise system install` and `mise system
use` so users see the accurate contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a807120c-eb3e-4fd3-998f-5445cb18645c

📥 Commits

Reviewing files that changed from the base of the PR and between 1631080 and d1dd5ec.

📒 Files selected for processing (26)
  • docs/.vitepress/cli_commands.ts
  • docs/cli/index.md
  • docs/cli/system.md
  • docs/cli/system/upgrade.md
  • docs/cli/system/use.md
  • docs/system-packages/apt.md
  • docs/system-packages/brew.md
  • docs/system-packages/dnf.md
  • docs/system-packages/index.md
  • docs/system-packages/pacman.md
  • e2e/cli/test_system_install_apt
  • e2e/cli/test_system_use
  • man/man1/mise.1
  • mise.usage.kdl
  • src/cli/system/driver.rs
  • src/cli/system/install.rs
  • src/cli/system/mod.rs
  • src/cli/system/upgrade.rs
  • src/cli/system/use.rs
  • src/config/config_file/mise_toml.rs
  • src/system/mod.rs
  • src/system/packages/apt.rs
  • src/system/packages/dnf.rs
  • src/system/packages/mod.rs
  • src/system/packages/pacman.rs
  • xtasks/fig/src/mise.ts

Comment thread docs/system-packages/index.md Outdated
Comment thread src/cli/system/use.rs
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.3 x -- echo 23.5 ± 3.5 19.5 36.8 1.00
mise x -- echo 23.5 ± 2.7 20.1 51.3 1.00 ± 0.19

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.3 env 21.6 ± 1.2 19.2 27.8 1.00
mise env 22.8 ± 1.3 19.8 28.6 1.06 ± 0.08

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.3 hook-env 21.8 ± 1.6 18.7 29.8 1.02 ± 0.10
mise hook-env 21.4 ± 1.5 18.7 29.2 1.00

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.3 ls 16.3 ± 1.0 14.4 22.6 1.00
mise ls 17.3 ± 1.3 15.2 24.5 1.06 ± 0.11

xtasks/test/perf

Command mise-2026.6.3 mise Variance
install (cached) 135ms 135ms +0%
ls (cached) 59ms 60ms -1%
bin-paths (cached) 63ms 65ms -3%
task-ls (cached) 126ms 127ms +0%

Jeff Dickey and others added 2 commits June 12, 2026 05:15
clap-sort requires short flags in declaration order; -g/-p/-e/-n/-y
failed test_subcommands_are_sorted. Also remove .test.mise.toml at the
end of the [system.packages] unit tests like the surrounding tests do —
leaving it behind races config::tests::test_load's snapshot of loaded
config files (the cause of the unit-macos failure).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- duplicate specs in one `mise system use` now last-wins consistently
  for both the config entry and the install request (previously the
  config kept the first version while both were installed)
- the 'added to config without installing' note no longer fires in
  dry-run, where nothing was written
- `mise system upgrade` re-queries package state after upgrading and
  reports only the packages whose version actually changed (or
  'already up to date') instead of claiming every target was upgraded
- docs: scope pinned-version upgrades to apt/dnf — pacman and brew
  skip pins with a warning

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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