Skip to content

Regenerate mise wrappers that still print mise's output on every run - #11973

Open
jayrascodes wants to merge 1 commit into
omacom:quattrofrom
jayrascodes:regenerate-noisy-mise-wrappers
Open

jayrascodes wants to merge 1 commit into
omacom:quattrofrom
jayrascodes:regenerate-noisy-mise-wrappers

Conversation

@jayrascodes

Copy link
Copy Markdown

Fixes #11971.

The problem

omarchy-mise-install passes --quiet to mise use -g, but wrappers written before it gained that flag still run the loud form on every invocation — and mise use -g writes its confirmation to stdout:

$ gh auth status 2>/dev/null | head -1
mise ~/.config/mise/config.toml tools: gh@2.100.0

Anything reading one of these tools through a pipe gets that line first. The sharpest case is git: with credential.https://github.com.helper = !gh auth git-credential, the banner becomes the first line of the credential protocol and every HTTPS push fails:

warning: invalid credential line: mise ~/.config/mise/config.toml tools: gh@2.100.0
fatal: could not read Username for 'https://github.com': No such device or address

Eleven wrappers were stale on the machine this was found on: claude, copilot, crush, gemini, gh, ghui, hunk, omp, opencode, pi, playwright.

Why 1784909971 doesn't already cover it

migrations/1784909971.sh is the one place that rebuilds wrappers in bulk, but it was written against the older wrapper format and can no longer parse the format it itself produced:

Line in a current wrapper Its pattern Matches
mise use -g "gh" || exit 1 ^mise use -g "\(.*\)"$ no — no longer ends in "
exec mise x "gh" -- "gh" "$@" ^exec "\(.*\)" "\$@"$ no — no longer a bare exec "<path>"

Both captures come back empty, so the [[ -n $package && -n $bin ]] guard skips every wrapper, silently. Reusing that loop for this fix would produce a migration that appears to run and changes nothing.

This change

A migration that matches the shape omarchy-mise-install writes today, and regenerates only wrappers still missing --quiet.

The package is read back out of the wrapper rather than derived from the file name, because regenerating from the command name alone would install the wrong thing under the right name for npm:@kitlangton/ghui, aqua:modem-dev/hunk, github:can1357/oh-my-pi and the bracketed http: specs.

Deliberately narrow about what it will touch:

  • Wrappers already carrying --quiet are skipped, so it is a true no-op on current installs and idempotent on repeat runs.
  • Anything in ~/.local/bin that isn't a mise wrapper is left alone and never executed.
  • A wrapper whose arguments were %q-escaped rather than double-quoted is skipped: skipping one leaves a stale wrapper, misparsing one leaves a broken command.
  • The pre-mise x generation isn't handled, since 1784909971 already converted it and migrations are strictly ordered.

Testing

test/shell.d/noisy-mise-wrapper-migration-test.sh, 11 assertions, following hermes-cli-migration-test.sh. It runs the real omarchy-mise-install against a temporary HOME so it tests today's wrapper rather than a copy of one.

The stdout assertion runs the regenerated wrapper against a mock mise that is loud exactly where the real one is — on use without --quiet — so it verifies how the wrapper calls mise without reinstalling anything, and can't pass just because the wrapper failed. A negative control runs the same probe against a stale wrapper to prove the assertion is capable of failing.

Also covered: idempotency, backend-spec preservation, foreign commands left untouched and unexecuted, %q-escaped wrappers skipped, non-executable files skipped, and empty/missing ~/.local/bin.

./test/all on my machine

The new test passes. The suite as a whole reports 6 of 243 files failing, and all 6 fail identically on a pristine tree with this branch's two files removed — they're pre-existing and environmental here, not introduced by this change:

test/shell.d/bar-icon-geometry-test.sh
test/shell.d/config-test.sh
test/shell.d/locate-test.sh
test/shell.d/omarchy-kernel-migration-test.sh
test/shell.d/snapper-test.sh
test/shell.d/unowned-system-paths-test.sh

Three say why directly — omarchy-pkgs checkout found for PKGBUILD coverage, omarchy-pkgs checkout is available for packaging coverage, omarchy-pkgs checkout found for package ownership check — I don't have that sibling checkout. Happy to rerun against CI or a fuller environment if that set doesn't match what you'd expect.

🤖 Generated with Claude Code

omarchy-mise-install passes --quiet to `mise use -g`, but wrappers
written before it gained that flag still run the loud form on every
invocation, and `mise use -g` writes its confirmation to stdout. Any
tool read through a pipe is corrupted; with
credential.https://github.com.helper set to `!gh auth git-credential`
the banner becomes the first line of the credential protocol and every
HTTPS push fails with "invalid credential line" and then "could not read
Username".

1784909971 rebuilds wrappers in bulk but was written against the older
format and can no longer parse the one it produced: the package pattern
expects the line to end in a quote, which `|| exit 1` broke, and the bin
pattern expects a bare `exec "<path>"`, which `exec mise x` replaced.
Both captures come back empty, so its guard skips every wrapper in
silence -- reusing that loop here would look like it ran and change
nothing.

The package is read back out of the wrapper rather than taken from the
file name, so npm:@kitlangton/ghui, aqua:modem-dev/hunk and
github:can1357/oh-my-pi are not reinstalled as whatever matches their
command name.

Deliberately narrow about what it touches: wrappers already carrying
--quiet are skipped, so it no-ops on current installs and on reruns;
anything in ~/.local/bin that is not a mise wrapper is neither rewritten
nor executed; and a wrapper whose arguments were %q-escaped instead of
double-quoted is left alone, because skipping one leaves a stale wrapper
while misparsing one leaves a broken command.

The stdout assertion runs the regenerated wrapper against a mock mise
that is loud exactly where the real one is, so it checks how the wrapper
calls mise rather than reinstalling a tool, and cannot pass by the
wrapper simply failing. A negative control runs the same probe against a
stale wrapper to prove the assertion can fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sprajs

sprajs commented Sep 18, 2026

Copy link
Copy Markdown

This appears to be covered by merged #8041. Its migrations/1787573629.sh is still present on current quattro and recognizes the exact MISE_MINIMUM_RELEASE_AGE=0 / mise use -g ... || exit 1 / exec mise x ... form shown here, as well as older forms.

I ran that current migration against a temporary home containing the stale gh wrapper from this PR, with omarchy-mise-install replaced by a recording stub; it correctly selected gh gh gh for regeneration. Could this be closed in favor of #8041, or narrowed to a fixture demonstrating why the existing migration missed the affected wrappers? That would distinguish a missing migration run/customized wrapper from a parser gap needing another migration.

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.

mise wrappers made before --quiet pollute stdout, and the regeneration migration can no longer parse them

2 participants