Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA 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.
`omarchy-launch-floating-terminal-with-presentation` drops `BROWSER`: first-agent OAuth browser runs in the terminal's process tree and aborts with SIGTRAP
Reported by seanpk · filed Aug 29, 2026 · open at source
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
System details
AMD Ryzen 9 9950X, Radeon Graphics (Granite Ridge, amdgpu), Omarchy 4.0.1-1, Chromium 151.0.7922.173-1, Hyprland 0.56.2-1, uwsm 0.26.7-1, bash 5.3.15-1, kernel 7.1.9-arch1-2. Fresh install, first login.
What's wrong?
The defect
omarchy-launch-floating-terminal-with-presentation:13 runs its payload under a non-interactive shell:
exec setsid uwsm-app -- xdg-terminal-exec --app-id=org.omarchy.terminal --title=Omarchy -e bash -c "$presentation_script"bash -c is non-interactive, so ~/.bashrc returns at its [[ $- != *i* ]] && return guard (line 5) and default/bash/envs is never sourced. OMARCHY_PATH and EDITOR survive because uwsm puts them in the session environment — but BROWSER does not, because it is deliberately shell-scoped only (default/bash/envs:5-8):
# Used by terminal programs (like gh) to open URLs detached from the terminal
# process tree. Shell-scoped on purpose: exporting BROWSER session-wide makes
# xdg-settings refuse to change the default browser.
export BROWSER="${BROWSER:-omarchy-launch-browser}"Verified on 4.0.1:
$ bash -c 'echo "${BROWSER:-UNSET}"' → UNSET
$ bash -ic 'echo "${BROWSER:-UNSET}"' → omarchy-launch-browserSo every command run through the presentation terminal opens URLs with the browser attached to the terminal's process tree — precisely what that export exists to prevent.
What it caused
First login → "Set your default agent" → Claude Code:
11:03:59 xdg-terminal-exec ... -e bash -c 'omarchy-show-logo; omarchy-default-agent --install claude; ...'
11:04:25 chromium <claude.com OAuth authorize URL> ← spawned by the agent, not detached
11:06:11 ~/.claude/.credentials.json written ← login itself succeeds
11:07:35 Hyprland: failed to read client connection (pid 5782)
11:07:36.003 chromium FATAL
11:07:36 terminal scope ends (3min 36s)omarchy-default-agent --install ends in exec omarchy-agent --inline, so the agent is the terminal. When login finishes and it exits, the terminal goes — and takes the browser's child processes with it.
Chromium's fatal, recovered from the core:
[6326:6326:0829/110736.003148:FATAL:content/browser/gpu/gpu_data_manager_impl_private.cc:417] GPU process isn't usable. Goodbye.Symbolized stack (Arch debuginfod):
logging::LogMessage::Flush()
logging::LogMessageFatal::~LogMessageFatal()
content::(anonymous namespace)::IntentionallyCrashBrowserForUnusableGpuProcess()
content::GpuDataManagerImplPrivate::FallBackToNextGpuMode()
content::GpuDataManagerImpl::FallBackToNextGpuModeDueToCrash()
content::GpuProcessHost::RecordProcessCrash()
content::GpuProcessHost::OnProcessLaunchFailed(int)
content::BrowserChildProcessHostImpl::OnProcessLaunchFailed(int)
content::ChildProcessLauncher::Notify(...)
content::internal::ChildProcessLauncherHelper::PostLaunchOnClientThread(...)
base::TaskAnnotator::RunTaskImpl(base::PendingTask&)
... base::MessagePumpGlib::Run ... content::BrowserMain ... ChromeMainSIGTRAP with si_code=SI_KERNEL is Chromium's int3 self-abort, not a fault. Chromium tried to launch a GPU process, the launch failed, no GPU fallback mode was left, and it takes the browser down by design.
That it was not launched detached is confirmed by cgroup: PID 6326 had only Chromium's self-created app-org.chromium.Chromium-6326.scope. A normally-launched Chromium also carries an app-Hyprland-chromium-*.scope, and at 11:04:25 there was no uwsm_app-daemon request and no omarchy-browser-* unit.
Ruled out: OOM (84 GiB free, no oomd or kernel kills), task limits (633 of 112847), amdgpu (clean init, completely silent 11:06–11:08), the bundled Chromium extensions (renderer-side, absent from the stack), and the 11:03 upgrades (archlinux-keyring, aether, mise-bin).
Proven vs inferred. The abort path, the missing BROWSER, and the un-detached launch are directly evidenced. That the terminal's teardown is what made the GPU relaunch fail is inferred from the sub-second coincidence — the kill signal is not recoverable after the fact. The missing BROWSER is a defect on its own terms regardless, since it defeats the stated purpose of that export.
Steps to reproduce
- Fresh Omarchy 4.0.1 install, first login.
- "Set your default agent" → Claude Code (any agent that signs in through a browser).
- Complete the OAuth login in the Chromium window that opens.
- Let the agent exit / the setup terminal close.
Chromium aborts; coredumpctl records a SIGTRAP.
Related
- #7174 hits the identical fatal (
gpu_data_manager_impl_private.cc:417, same message) in the identical first-agent flow, but sets it aside as "a Chromium/Mesa abort, not this stacking bug". It is not Mesa — it is this. That issue is about window stacking; this is the crash it scoped out. It also records that Grok launches viauwsm-app -- /usr/bin/chromium, i.e. each agent improvises its own browser launch exactly becauseBROWSERis absent. - #8394 is a different SIGTRAP: early startup, single-threaded
ChromeMainstack, before content loads. Not this one.
Proposed fix
Source Omarchy's own env file at the head of the presentation script:
-presentation_script="omarchy-show-logo; $cmd; if (( \$? != 130 )); then omarchy-show-done; fi"
+presentation_script="source \"\${OMARCHY_PATH:-/usr/share/omarchy}/default/bash/envs\"; omarchy-show-logo; $cmd; if (( \$? != 130 )); then omarchy-show-done; fi"Verified on 4.0.1:
- restores
BROWSER=omarchy-launch-browser - still works with
OMARCHY_PATHunset (falls back to/usr/share/omarchy) - emits nothing on stdout/stderr and exits 0, so the presentation is unchanged
It keeps BROWSER shell-scoped — no session-wide export, so xdg-settings still behaves — and fixes all seven callers of the wrapper at once (omarchy-menu.jsonc, Panel.qml, SystemUpdate.qml, install-voxtype.hook, setup-fingerprint.hook, transcode.py, wifi.sh).
Filed by Claude Opus 5 via Claude Code.
View raw text
### System details
AMD Ryzen 9 9950X, Radeon Graphics (Granite Ridge, `amdgpu`), Omarchy 4.0.1-1, Chromium 151.0.7922.173-1, Hyprland 0.56.2-1, uwsm 0.26.7-1, bash 5.3.15-1, kernel 7.1.9-arch1-2. Fresh install, first login.
### What's wrong?
**The defect**
`omarchy-launch-floating-terminal-with-presentation:13` runs its payload under a non-interactive shell:
```bash
exec setsid uwsm-app -- xdg-terminal-exec --app-id=org.omarchy.terminal --title=Omarchy -e bash -c "$presentation_script"
```
`bash -c` is non-interactive, so `~/.bashrc` returns at its `[[ $- != *i* ]] && return` guard (line 5) and `default/bash/envs` is never sourced. `OMARCHY_PATH` and `EDITOR` survive because uwsm puts them in the session environment — but `BROWSER` does not, because it is deliberately shell-scoped only (`default/bash/envs:5-8`):
```bash
# Used by terminal programs (like gh) to open URLs detached from the terminal
# process tree. Shell-scoped on purpose: exporting BROWSER session-wide makes
# xdg-settings refuse to change the default browser.
export BROWSER="${BROWSER:-omarchy-launch-browser}"
```
Verified on 4.0.1:
```
$ bash -c 'echo "${BROWSER:-UNSET}"' → UNSET
$ bash -ic 'echo "${BROWSER:-UNSET}"' → omarchy-launch-browser
```
So every command run through the presentation terminal opens URLs with the browser attached to the terminal's process tree — precisely what that export exists to prevent.
**What it caused**
First login → "Set your default agent" → Claude Code:
```
11:03:59 xdg-terminal-exec ... -e bash -c 'omarchy-show-logo; omarchy-default-agent --install claude; ...'
11:04:25 chromium <claude.com OAuth authorize URL> ← spawned by the agent, not detached
11:06:11 ~/.claude/.credentials.json written ← login itself succeeds
11:07:35 Hyprland: failed to read client connection (pid 5782)
11:07:36.003 chromium FATAL
11:07:36 terminal scope ends (3min 36s)
```
`omarchy-default-agent --install` ends in `exec omarchy-agent --inline`, so the agent *is* the terminal. When login finishes and it exits, the terminal goes — and takes the browser's child processes with it.
Chromium's fatal, recovered from the core:
```
[6326:6326:0829/110736.003148:FATAL:content/browser/gpu/gpu_data_manager_impl_private.cc:417] GPU process isn't usable. Goodbye.
```
Symbolized stack (Arch debuginfod):
```
logging::LogMessage::Flush()
logging::LogMessageFatal::~LogMessageFatal()
content::(anonymous namespace)::IntentionallyCrashBrowserForUnusableGpuProcess()
content::GpuDataManagerImplPrivate::FallBackToNextGpuMode()
content::GpuDataManagerImpl::FallBackToNextGpuModeDueToCrash()
content::GpuProcessHost::RecordProcessCrash()
content::GpuProcessHost::OnProcessLaunchFailed(int)
content::BrowserChildProcessHostImpl::OnProcessLaunchFailed(int)
content::ChildProcessLauncher::Notify(...)
content::internal::ChildProcessLauncherHelper::PostLaunchOnClientThread(...)
base::TaskAnnotator::RunTaskImpl(base::PendingTask&)
... base::MessagePumpGlib::Run ... content::BrowserMain ... ChromeMain
```
`SIGTRAP` with `si_code=SI_KERNEL` is Chromium's `int3` self-abort, not a fault. Chromium tried to **launch** a GPU process, the launch failed, no GPU fallback mode was left, and it takes the browser down by design.
That it was not launched detached is confirmed by cgroup: PID 6326 had only Chromium's self-created `app-org.chromium.Chromium-6326.scope`. A normally-launched Chromium also carries an `app-Hyprland-chromium-*.scope`, and at 11:04:25 there was no `uwsm_app-daemon` request and no `omarchy-browser-*` unit.
Ruled out: OOM (84 GiB free, no oomd or kernel kills), task limits (633 of 112847), `amdgpu` (clean init, completely silent 11:06–11:08), the bundled Chromium extensions (renderer-side, absent from the stack), and the 11:03 upgrades (`archlinux-keyring`, `aether`, `mise-bin`).
**Proven vs inferred.** The abort path, the missing `BROWSER`, and the un-detached launch are directly evidenced. That the terminal's teardown is what made the GPU relaunch fail is inferred from the sub-second coincidence — the kill signal is not recoverable after the fact. The missing `BROWSER` is a defect on its own terms regardless, since it defeats the stated purpose of that export.
### Steps to reproduce
1. Fresh Omarchy 4.0.1 install, first login.
2. "Set your default agent" → Claude Code (any agent that signs in through a browser).
3. Complete the OAuth login in the Chromium window that opens.
4. Let the agent exit / the setup terminal close.
Chromium aborts; `coredumpctl` records a `SIGTRAP`.
### Related
- **#7174** hits the identical fatal (`gpu_data_manager_impl_private.cc:417`, same message) in the identical first-agent flow, but sets it aside as "a Chromium/Mesa abort, not this stacking bug". It is not Mesa — it is this. That issue is about window stacking; this is the crash it scoped out. It also records that Grok launches via `uwsm-app -- /usr/bin/chromium`, i.e. each agent improvises its own browser launch exactly because `BROWSER` is absent.
- **#8394** is a *different* SIGTRAP: early startup, single-threaded `ChromeMain` stack, before content loads. Not this one.
### Proposed fix
Source Omarchy's own env file at the head of the presentation script:
```diff
-presentation_script="omarchy-show-logo; $cmd; if (( \$? != 130 )); then omarchy-show-done; fi"
+presentation_script="source \"\${OMARCHY_PATH:-/usr/share/omarchy}/default/bash/envs\"; omarchy-show-logo; $cmd; if (( \$? != 130 )); then omarchy-show-done; fi"
```
Verified on 4.0.1:
- restores `BROWSER=omarchy-launch-browser`
- still works with `OMARCHY_PATH` unset (falls back to `/usr/share/omarchy`)
- emits nothing on stdout/stderr and exits 0, so the presentation is unchanged
It keeps `BROWSER` shell-scoped — no session-wide export, so `xdg-settings` still behaves — and fixes all seven callers of the wrapper at once (`omarchy-menu.jsonc`, `Panel.qml`, `SystemUpdate.qml`, `install-voxtype.hook`, `setup-fingerprint.hook`, `transcode.py`, `wifi.sh`).
---
Filed by Claude Opus 5 via Claude Code.
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
Not linked to any known issue, other report or change yet.
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 09:56 UTC