Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.

Inbox
ReportR-1671GitHub issuePublicFixed

mise tool wrappers print mise's status line to stdout, corrupting captured command output (gh auth token → 401)

Reported by pl0xuee · filed Aug 18, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 days ago.

At a glance

1 · What is claimed?
Only the report text below — no validator has restated it as checkable claims yet.
2 · What does it affect?
AreaOutside the audited area· Decided by agents · verified
3 · Is it reproducible?
No validation has been run yet.
4 · What remains unclear?
  • Not validated yet: no claims, no reproducer.
5 · What happens next?
Decided by agents and verified by a second, independent agent — see the decision.

Original report

mise tool wrappers print mise's status line to stdout, corrupting captured command output (gh auth token → 401)revision 1 · captured 2026-09-28 21:29 UTC via poll

omarchy-mise-install wrappers print mise's status line to stdout, corrupting every captured command output

Omarchy: 4.0.0-1 · mise: 2026.8.3 · Hyprland: 0.56.2

What happens

omarchy-mise-install writes a wrapper per tool into ~/.local/bin:

#!/bin/bash
export MISE_MINIMUM_RELEASE_AGE=0
mise use -g "gh" || exit 1
exec mise x "gh" -- "gh" "$@"

mise use -g prints its status line to stdout, not stderr:

$ gh auth token 2>/dev/null | cat -n
     1  mise ~/.config/mise/config.toml tools: [email protected]
     2  gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

So every one of these wrappers prepends a line to its own output, and any script
doing value="$(tool ...)" gets the banner instead of — or glued onto — the
value it asked for. On this box that is 13 commands: claude, codex, copilot,
crush, gemini, gh, ghui, grok, hunk, omp, opencode, pi, playwright.

Why it's worth fixing rather than working around

The failure is silent and it misdirects. A setup script of mine does the
ordinary thing:

token="$(gh auth token 2>/dev/null)"
curl -H "Authorization: Bearer $token" https://api.github.com/...

The captured value is two lines. Strip the newline (as any careful script does,
since a newline would terminate the header) and you get the banner concatenated
onto a perfectly valid token. GitHub answers 401, which reads as "your token
is bad" — while gh auth status reports the login as fine, because gh itself
never goes through the wrapper's stdout. Hours can go into checking a token that
was never the problem.

Anything that parses a wrapped tool's output is exposed the same way: `gh api |
jq, gh pr view --json, $(codex --version), any --format json` call.

Reproduce

omarchy-mise-install gh          # or just use a stock install
gh auth token | wc -l            # 2, not 1
[ "$(gh auth token)" = "$(mise x gh -- gh auth token)" ] && echo same || echo CORRUPTED

Cause

/usr/share/omarchy/bin/omarchy-mise-install, the heredoc at line ~24 — the
mise use -g "$package" line inherits the wrapper's stdout.

Suggested fix

Send that line's output where diagnostics belong, keeping the exit check:

mise use -g "$package" >&2 || exit 1

>/dev/null, or adding export MISE_QUIET=1 next to the existing
MISE_MINIMUM_RELEASE_AGE=0, would do it too. MISE_QUIET=1 has the advantage
of also covering anything else mise decides to print there later.

Worth a second look separately: mise use -g runs on every invocation, so
merely running gh rewrites ~/.config/mise/config.toml. Skipping it when the
tool is already installed would make the wrappers cheaper as well as quieter.

Workaround for anyone hitting this

quiet = true under [settings] in ~/.config/mise/config.toml silences it for
all the wrappers at once, and survives them being regenerated on update.

View raw text
## `omarchy-mise-install` wrappers print mise's status line to stdout, corrupting every captured command output

**Omarchy:** 4.0.0-1 · **mise:** 2026.8.3 · **Hyprland:** 0.56.2

### What happens

`omarchy-mise-install` writes a wrapper per tool into `~/.local/bin`:

```bash
#!/bin/bash
export MISE_MINIMUM_RELEASE_AGE=0
mise use -g "gh" || exit 1
exec mise x "gh" -- "gh" "$@"
```

`mise use -g` prints its status line to **stdout**, not stderr:

```console
$ gh auth token 2>/dev/null | cat -n
     1  mise ~/.config/mise/config.toml tools: [email protected]
     2  gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

So every one of these wrappers prepends a line to its own output, and any script
doing `value="$(tool ...)"` gets the banner instead of — or glued onto — the
value it asked for. On this box that is 13 commands: claude, codex, copilot,
crush, gemini, gh, ghui, grok, hunk, omp, opencode, pi, playwright.

### Why it's worth fixing rather than working around

The failure is silent and it misdirects. A setup script of mine does the
ordinary thing:

```bash
token="$(gh auth token 2>/dev/null)"
curl -H "Authorization: Bearer $token" https://api.github.com/...
```

The captured value is two lines. Strip the newline (as any careful script does,
since a newline would terminate the header) and you get the banner concatenated
onto a perfectly valid token. GitHub answers **401**, which reads as "your token
is bad" — while `gh auth status` reports the login as fine, because gh itself
never goes through the wrapper's stdout. Hours can go into checking a token that
was never the problem.

Anything that parses a wrapped tool's output is exposed the same way: `gh api |
jq`, `gh pr view --json`, `$(codex --version)`, any `--format json` call.

### Reproduce

```bash
omarchy-mise-install gh          # or just use a stock install
gh auth token | wc -l            # 2, not 1
[ "$(gh auth token)" = "$(mise x gh -- gh auth token)" ] && echo same || echo CORRUPTED
```

### Cause

`/usr/share/omarchy/bin/omarchy-mise-install`, the heredoc at line ~24 — the
`mise use -g "$package"` line inherits the wrapper's stdout.

### Suggested fix

Send that line's output where diagnostics belong, keeping the exit check:

```bash
mise use -g "$package" >&2 || exit 1
```

`>/dev/null`, or adding `export MISE_QUIET=1` next to the existing
`MISE_MINIMUM_RELEASE_AGE=0`, would do it too. `MISE_QUIET=1` has the advantage
of also covering anything else mise decides to print there later.

Worth a second look separately: `mise use -g` runs on *every* invocation, so
merely running `gh` rewrites `~/.config/mise/config.toml`. Skipping it when the
tool is already installed would make the wrappers cheaper as well as quieter.

### Workaround for anyone hitting this

`quiet = true` under `[settings]` in `~/.config/mise/config.toml` silences it for
all the wrappers at once, and survives them being regenerated on update.

Validation

Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.

Linked

  • Fixed bypr/11514· confirmed

Decision

Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.

  • Out of scopeDecided by agents · verified · 2026-10-09 04:44 UTC