Commit Graph
2288 Commits
Author SHA1 Message Date
Ryan Hughes 8f3ab025b8 Treat matching kernel headers as a base system guarantee
(cherry picked from commit 24417bf191)
2026-09-15 00:46:59 -04:00
Ryan Hughes 28d5251e23 Install matching kernel headers for every DKMS setup
(cherry picked from commit 662051ecde)
2026-09-15 00:07:19 -04:00
Ryan Hughes 4ea7ca2b8b Retire the stock user icon font missed by Quattro upgrades
(cherry picked from commit f5cd244ed0)
2026-09-08 02:37:35 -04:00
JP c5b59bcfff Add Muse Code as a default coding agent (#9915)
* Add Muse Code as a default coding agent

Meta ships Muse Code only as a binary, so it installs from the AUR
(muse-code-bin) instead of mise, and a fresh install runs the muse login
browser flow in the install terminal before the agent opens.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0148qKzr366p2Ubu2igCLvPg

* Refine Muse Code menu and prompt forwarding

* Install Muse Code from OPR

* Install Muse Code through mise's HTTP backend

* Preinstall the Muse mise stub

* Use the shared Muse installation flow

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
(cherry picked from commit 0d223fe820)
2026-09-07 21:16:59 -04:00
David Heinemeier Hansson a9e1c01ee9 Add Cursor CLI as a coding agent choice (#10465)
* Add Cursor CLI as a coding agent choice

* Launch Cursor CLI through its agent subcommand with --trust

Cursor CLI still dispatches a one-word prompt that names one of its
subcommands (update, login, help) even after a bare --, so name the agent
subcommand outright and pass the prompt behind -- there, where it also
keeps a prompt starting with a dash from being read as an option. --yolo
only auto-allows commands; the workspace trust dialog is skipped only by
--trust, and a launcher that must not stop to ask needs both.

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

* Leave an official Cursor CLI install alone

Cursor's own installer symlinks ~/.local/bin/cursor-agent, the same path the
mise wrapper takes. The migration now installs the wrapper only when no
cursor-agent command exists, and Remove Preinstalls deletes the path only
when it holds the wrapper omarchy-mise-install wrote, the way the Hermes
wrapper is handled. Selecting the agent treats an executable at that path
other than the wrapper as the user's own install and skips mise, since the
mise shims precede ~/.local/bin on PATH and a mise copy would only shadow
it. The wrapper resolves through mise's registry, which lists cursor-agent
from 2026.8.15 on.

The tests write a real cursor-agent stub before Remove Preinstalls runs,
cover the preinstall opt-out for the new migration, and check that a
symlinked official install survives removal and selection alike while a
dead file at the same path still installs.

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

* Give Cursor its brand mark and one name in the menu

Add Cursor's mark to the Omarchy icon font as U+E90D and point the agent
entry and both editor entries at it, so one brand is drawn one way across
the menu. Label the agent entry "Cursor CLI", the name the command and the
manual already use, and spell it the same in the migration and the tests.
Append the manual row after the others at the standard width.

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

* Keep an official Cursor CLI install through a user re-provision

User setup writes every mise wrapper unconditionally, which is fine on a
fresh install but replaces the symlink Cursor's own installer leaves at the
same path when omarchy-provision-user runs again with --force. Guard that
one line the way the migration does.

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

---------

Co-authored-by: John Cavanaugh <59479+cavanaug@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit a62e34ea8e)
(cherry picked from commit 1c05f141f158b3521c193b66f03350aa94719d95)
2026-09-07 21:15:42 -04:00
David Heinemeier Hansson 256bfeaa75 Start 1Password at a fixed device scale factor (#10673)
1Password reads the display scale itself, the way Electron apps do, so
on a scaled monitor it comes up oversized next to every other window.
Pin it with --force-device-scale-factor=1 and let the compositor scale
it.

The app menu is covered by the packaged .desktop, which we build
ourselves in omarchy-pkgs. This is the other route in: the hotkey runs
the binary directly and never reads that file.

Claude-Session: https://claude.ai/code/session_01JB9phxP56gnP7qSidkkUJE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 446fbc28b1)
(cherry picked from commit 2acfa32b0aac3e4613849e7b8e56968379971a51)
2026-09-07 20:57:03 -04:00
Ryan Hughes 36695fbe84 Merge pull request #8784 from omacom/t3-theme-support
Add theme support for T3 Code

(cherry picked from commit 5fb2cc7967)
(cherry picked from commit f1e9f5a4e14cb266c85b9956d64d3d0a7835a654)
2026-09-07 20:57:03 -04:00
Spencer Bull e919a64014 Merge pull request #10613 from spencerbull/hermes-desktop-in-app-updates
Enable Hermes in-app updates and guard removal

(cherry picked from commit a703092631)
(cherry picked from commit 2438293d775d679ce99364cdbced108596c5b2bc)
2026-09-07 20:57:03 -04:00
Ryan Hughes 866d994dcf Merge pull request #7994 from Adolanium/mise-install-name-guard
Quote mise-install arguments and refuse unusable command names

(cherry picked from commit e989b5b3ee)
(cherry picked from commit fabcc4e437614cdd20638b108ae59b04191752e6)
2026-09-07 20:57:03 -04:00
Ryan Hughes cf459ba752 Merge pull request #9387 from omacom/security/nopasswd-expiry-fail-closed
Fail closed when passwordless sudo expiry cannot arm

(cherry picked from commit a87d396f01)
(cherry picked from commit 88ba230e6affefe83899ea5cda228311c73b924b)
2026-09-07 20:57:03 -04:00
Spencer Bull 1fe83ff129 Merge pull request #10460 from codemonkey76/fix-openclaw-cmd-present
Use the command helper in the AI app removers

(cherry picked from commit 18410a0e48)
(cherry picked from commit 67125c330b36204356a92867b9c9120a4599afae)
2026-09-07 20:57:03 -04:00
Ryan Hughes 6a72d4236b Merge pull request #10605 from omacom/fix/kitty-system-defaults
Move Kitty defaults to the system config and restrict remote control

(cherry picked from commit f04366de79)
(cherry picked from commit 6dfbfa146b91bf310f2ff7147953afddef73de9a)
2026-09-07 20:57:03 -04:00
Ryan Hughes 7a35a8ee9b Merge pull request #10579 from omacom/fix/locate-service-defaults
Replace locate configuration script with packaged service defaults

(cherry picked from commit d7c783ecf5)
(cherry picked from commit 142ac21ed3d86fa3733b2a4fe41618eb67747ef8)
2026-09-07 20:57:03 -04:00
Ryan Hughes 6d327ce83c Merge pull request #10425 from acrogenesis/security/root-owned-sleep-hooks
Harden ownership of installed sleep hooks

(cherry picked from commit c82a0837b0)
(cherry picked from commit 3b5f4446f6022ad056fc06d320d157075841cde7)
2026-09-07 20:57:03 -04:00
Ryan Hughes f94c6db34d Merge pull request #10225 from mdisec/security/harden-quattro-fprintd-path
Harden lock authentication command lookup

(cherry picked from commit 3f91f06a62)
(cherry picked from commit 72116e5cefef29446d34d328badd3a3701928b3d)
2026-09-07 20:57:03 -04:00
powderluv 8d1a7ef00c Install libfprint-git for every fingerprint reader (#10442)
* Use updated libfprint-git for fingerprint setup on edge

* Pick the fingerprint driver from the reader, not the release channel

The channel gate blocked every edge and dev user until the newer
libfprint-git pin is published, misrouted dev checkouts on the stable
mirror, and left the stock-libfprint migration reverting the driver on
accounts without its marker. Key both the setup and the migration on
omarchy-hw-fingerprint-git, a USB ID table of readers stock libfprint
cannot drive, so the git snapshot only goes where it is needed on any
channel. Qualify the package with the omarchy repo, and skip pacman
entirely when the packages are already current so a rerun cannot become
a partial upgrade.

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

* Install libfprint-git for every fingerprint reader

Stock libfprint lags upstream on new readers, and gating the git
snapshot per reader or per channel only added machinery to keep in sync
with the package repo. Install libfprint-git unconditionally instead:
the omarchy-pkgs pin is the single place a new reader gets enabled. The
migration that swapped it back to stock goes away with the policy it
enforced; late updaters keep the driver they have and pick up the new
pin as a normal package upgrade.

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

---------

Co-authored-by: powderluv <powderluv@powderluv.org>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit adcc96a782)
(cherry picked from commit 8d0ca2a628fdeab5ce9f9c4a779630cd38223c85)
2026-09-07 20:57:03 -04:00
Spencer Bull 6cc561b8d3 Merge pull request #10381 from spencerbull/hermes-system-theme
Make Hermes follow the Omarchy theme as a skin

(cherry picked from commit 988da12cb0)
(cherry picked from commit 6d3ae7a811ecda54ca11bff0991c2a72878a29e3)
2026-09-07 20:57:03 -04:00
Spencer Bull 6cb5396dc7 Merge pull request #9625 from spencerbull/t3code/add-perplexity-ai-app
Add the Perplexity desktop app to Install > AI

(cherry picked from commit f1b065c292)
(cherry picked from commit 680930915eaba8c3741980c56ad160a40c50bcb9)
2026-09-07 20:57:03 -04:00
Spencer Bull 27594ba3f5 Merge pull request #10271 from spencerbull/hermes-remove-ask-user-data
Ask, default no, before Remove Hermes deletes the user's data

(cherry picked from commit 959e49dc52)
(cherry picked from commit 4e77199945a15ac194511b1af6317761fb813ba0)
2026-09-07 20:57:03 -04:00
Spencer Bull be6c401200 Merge pull request #10246 from omacom/add-openclaw-ai-app
Add OpenClaw as a desktop app and a coding agent

(cherry picked from commit eb56446c42)
(cherry picked from commit bde2584b5596412142d0a2039d44dd6a25949517)
2026-09-07 20:57:03 -04:00
Spencer Bull d49dd939b7 Merge pull request #9663 from spencerbull/fix/hermes-prompt-probe
Fix the Hermes CLI readiness probe, and tear the CLI down on uninstall

(cherry picked from commit f99d33a8dd)
(cherry picked from commit de739ea736563763150725ce33151001c5966add)
2026-09-07 20:57:03 -04:00
Spencer Bull 68e3d7a2ec Merge pull request #7469 from omacom/hermes-agent
Add Hermes as a desktop app and a coding agent

(cherry picked from commit b71dcad96e)
(cherry picked from commit b27908369ed5fa95ca24dca2c68b895032d879d2)
2026-09-07 20:57:03 -04:00
Ryan Hughes 82de446713 Port the selected AI removal scaffold for 4.0.3
Port only Remove > AI and T3 removal/tests from #7504 (023021ad2d). Keep Dictation in its baseline location and omit unrelated removers.

(cherry picked from commit 73480ffabc091b812a0cfbe7bc845799c6078a88)
2026-09-07 20:57:03 -04:00
Omarchybot f8e35ec654 Merge pull request #7984 from Chessing234/fix/webapp-name-slashes
Keep a web app name out of the launcher's directory structure

(cherry picked from commit 83881e979b)
2026-08-30 18:03:24 -04:00
Ryan Hughes 6f8b62f04c Merge pull request #9240 from omacom/fix/acceptance-security-coverage
Fix the bar visibility toggle and make the acceptance suite cover 4.0.2 security hardening

(cherry picked from commit 432b5e3e24)
2026-08-30 16:45:30 -04:00
Ryan Hughes ebd6480387 Merge pull request #9225 from omacom/fix/sshd-hardening-verification-case
Match sshd -T keywords case-insensitively when verifying SSH hardening

(cherry picked from commit a24064c720)
2026-08-30 15:14:32 -04:00
Ryan Hughes 07579f5e94 Merge pull request #9214 from omacom/rc-channel-pacman
Point the rc channel at the rc package repository

(cherry picked from commit 4271b880c3)
2026-08-30 13:54:21 -04:00
Ryan Hughes ff4cf8afbc Merge pull request #9200 from omacom/security/v4-0-2-input-asdcontrol-sshd
[4.0.2] Close unprivileged input and SSH escalation paths

(cherry picked from commit 21b27c5aed)
2026-08-30 13:05:45 -04:00
Ryan Hughes cf3d69c38d Merge pull request #9002 from acrogenesis/remove-legacy-installer-privileged-files
Repair legacy paths and privileged files left by retired installers

(cherry picked from commit 943d2fcbe9)
2026-08-30 12:08:00 -04:00
Adolanium 47ce81ebca Quote install-app and install-font names like install-and-launch (#7843)
* Quote install-app and install-font names like install-and-launch

* Quote the package list too, not just the display name

The display name was quoted but omarchy-pkg-add's own arguments were still interpolated into the bash -c string raw, so `omarchy install app Vim 'vim; id'` ran id. The list has to reach the helper as several words, so it cannot be quoted whole: it is split the way the unquoted expansion split it and each word is quoted on its own. Reading with -d '' keeps a newline-separated list intact instead of dropping every package after the first, which plain read -a would. install-font's package is singular and is quoted whole, and install-and-launch carried the same flaw.

Reported by acrogenesis in review of #7843.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

* Test that install-font skips font-set when pkg-add fails

The hostile-package case was asserting the family still got set, which only held because the mock always exits 0. pacman would reject that name and the && chain would skip font-set.

* Keep the installers working when errexit is inherited

read -d '' always ends at EOF rather than on its delimiter, so it reports failure on every input. Under an inherited errexit the installers exited there and built no command at all.

Reported by Codex XHigh in review of #7843.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

---------

Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Codex XHigh <noreply@openai.com>
(cherry picked from commit 625c4a1603)
2026-08-30 12:08:00 -04:00
Ryan Hughes 2421e76fb8 Merge pull request #8419 from AFOliveira/security/windows-vm-mount-boundary
[codex] Secure Windows VM host mounts

(cherry picked from commit 158e8cfb3a)
2026-08-30 12:08:00 -04:00
Ryan Hughes bffc6a2a5d Merge pull request #8934 from ErikMelton/security/plymouth-publication-race
Secure Plymouth and SDDM asset publication

(cherry picked from commit e229927671)
2026-08-29 18:46:11 -04:00
Ryan Hughes 7678e5b0d8 Merge pull request #8496 from Chessing234/security/webapp-http-only
(cherry picked from commit 0b3f1b7ead)
2026-08-29 15:40:44 -04:00
Ryan Hughes be730884f6 Merge pull request #8473 from bastidotnet/fix/webapp-desktop-value-escaping
(cherry picked from commit f20bf0a21b)
2026-08-29 15:40:44 -04:00
Ryan Hughes a73a312e1b Merge pull request #8951 from omacom/cups-browsed-temporarily-removed
Temporarily remove automatic printer discovery

(cherry picked from commit c720f0b981)
2026-08-29 15:39:54 -04:00
David Heinemeier Hansson 159163bb16 Merge pull request #8203 from hjanuschka/fix-chromium-first-run-eula
Skip Chromium's new first-run EULA

(cherry picked from commit 5236f4426c)
2026-08-29 15:39:54 -04:00
Ryan Hughes 521779b114 Merge pull request #8416 from mdisec/theme-name-shell-syntax
Refuse a theme name that is shell syntax, and quote the one the unlock picker returns

(cherry picked from commit 9da8824098)
2026-08-29 03:20:17 -04:00
Ryan Hughes 3bb9867245 Merge pull request #8835 from basecamp/fix-browser-policy-exit-trap
Fix migration 1787515927 failing on Bash 5.3

(cherry picked from commit 62eb5182d0)
2026-08-28 22:55:52 -04:00
Ryan Hughes da0fe6d89f Harden browser policy directories (#7972)
Cherry-picked from quattro (7d58bb9a).

Stop world-writable Chromium and Firefox policy directories: create them
root-owned at 0755, purge non-root entries, refuse planted symlinks, and
write the browser theme colour through a passwordless helper instead of
a world-writable policy file.

Conflict resolution for v4-0-2:
- bin/omarchy-install-browser: dropped the `chromium)` case, which does
  not exist on this branch.
- test/shell.d/default-apps-test.sh: dropped; the file does not exist on
  this branch.
2026-08-28 18:25:24 -04:00
David Heinemeier Hansson 9c1ec524cd Merge pull request #8198 from bastidotnet/harden-apple-brightness-device-cache
Validate the cached Apple-display device path before use

(cherry picked from commit 06e32d243d)
2026-08-28 15:32:34 -04:00
orienw 880605f22b Fix Codex usage collection on 0.149 (#7649)
* Fix Codex usage collector approval policy

* Capture codex argv with boundaries in the scanner test

The stub joined its arguments with "$*", so the assertion compared one
flattened string and could not tell five arguments from fewer containing
spaces. Passing "-s read-only" and "-a on-request" as single arguments --
which codex rejects as an unexpected argument -- passed the test. NUL
separation and an array comparison keep the boundaries the assertion is
about.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Codex XHigh <noreply@openai.com>

---------

Co-authored-by: Omabot <omabot@omarchy.org>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Codex XHigh <noreply@openai.com>
(cherry picked from commit 4cd8a081cb)
2026-08-28 15:32:34 -04:00
Mehmet INCEandClaude Opus 5 13f18b2cb7 [Security] Stop the FIDO2 setup staging its authfile at a predictable /tmp path (backport of #7904)
Backport of the FIDO2 authfile fix (PR #7904 by @mdisec, merged to quattro as
23dab9ec) onto the v4-0-1 release branch.

pamu2fcfg wrote to /tmp/fido2 and the registration was then moved into place
with sudo mv. Any other local user can pre-create /tmp/fido2, and rename(2) does
not dereference the final component, so the privileged move installed the
attacker's symlink itself as pam_u2f's global authfile -- a file consulted by
sufficient lines in /etc/pam.d/sudo and /etc/pam.d/polkit-1.

The same move also carried the staged file's ownership into /etc, so on every
install to date /etc/fido2/fido2 is owned by the invoking user at mode 0644.
That needs no attacker, no race and no second account: anything running as that
uid can append its own credential and satisfy the machine's sudo prompt without
knowing the password.

The setup now creates a unique staging file as root beside the final authfile
and pipes pamu2fcfg into it, so root never reopens a caller-owned pathname,
rejects failed or empty enrollment output, publishes with an atomic mv -Tf,
cleans the exact staging file after every failure, refuses non-regular authfile
states, and installs root:root 0644. A migration repairs machines set up by
earlier versions by replacing the inode rather than chowning in place: a process
that already holds a writable descriptor on the legacy user-owned mapping keeps
it, so the repair has to leave that inode behind where PAM no longer reads it.

Clean cherry-pick: all six files are byte-identical to quattro, so merging
v4-0-1 into quattro resolves without a conflict. The migration's timestamp
(1787494718) is older than others already on this branch, which is harmless:
omarchy-migrate marks each migration by filename rather than tracking a
watermark, so this one runs on every machine that has not run this exact file.

test/shell passes: 195 files, including the three this adds -- the setup's
staging and failure paths, the migration's repair and unrepairable states, and
the removal's symlink handling. test/cli passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 12:12:38 +02:00
Adrian RangelandClaude Opus 5 2e989e35e5 [Security] Stop USB device names from being executed as Hyprland Lua (backport of #8129)
Backport of the input-device name fix (PR #8129 by @acrogenesis, merged to
quattro as 9285b19d) onto the v4-0-1 release branch.

Hyprland input-device and monitor names come from USB descriptors and hyprctl
output, so they are attacker-influenceable, yet the toggle and monitor commands
interpolated them straight into hyprctl eval and into generated Lua that
Hyprland re-executes on every reload. XF86TouchpadToggle is bound with
locked = true, so a malicious USB name reached Lua execution from the lock
screen as the logged-in user, and a persisted disable made it run on every
start. Publicly reported by Jorrit Jongma / Chainfire.

The disable is no longer executable Lua anywhere. The device name is stored as
plain-text data in a *-disabled-name sidecar and read back by a packaged module,
default/hypr/disabled-input-device.lua, on every reload; the live hyprctl eval
Lua-quotes the name and rejects control characters outright. The reload loader
excludes the two legacy filenames, so a leftover generated *-disabled.lua on a
not-yet-migrated install can never be sourced as code again, and a migration
recovers the device name from it and deletes it, sanitizing installs that ran
the vulnerable version. All four monitor scripts validate an output name against
a plain-connector-name pattern before writing it as Lua, closing the same latent
pattern in the siblings, and paths.lua treats a set-but-empty XDG_STATE_HOME as
unset to match the bash side.

Clean cherry-pick: all fourteen files are byte-identical to quattro, so merging
v4-0-1 into quattro resolves without a conflict. This branch ships no leftover
*-disabled.lua template of its own -- the tracked "disabled" files are the same
two quattro has -- so the migration is the only path that has to sanitize
anything here.

test/shell passes: 192 files, including the three this adds. The toggle suite's
public-PoC case passes here, as do the monitor scripts' accept/reject cases and
the XDG path cases. test/cli passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 11:07:35 +02:00
Mehmet INCEandClaude Opus 5 c6d676f23c Pin trusted PATH in privileged DNS helper (backport of #8172)
Backport of the DNS PATH pin (PR #8172 by @mdisec, merged to quattro as
4637735a) onto the v4-0-1 release branch.

omarchy dev link prepends a user-writable checkout's bin/ to sudo's secure_path
so privileged Omarchy commands resolve to the development versions, and that
reaches the subprocesses they launch too. This branch carries the same
passwordless grant -- etc/sudoers.d/omarchy-dns lets wheel run
/usr/bin/omarchy-dns Cloudflare, Google and DHCP without a password -- so the
packaged script ran as root while resolving bare helpers (dirname, install,
tee, rm, nmcli, systemctl, awk) through the caller's secure_path. Write access
to a dev checkout became arbitrary root execution, with no password prompt in
the way.

Pin PATH to trusted system directories once EUID is 0. The restriction lands
only after elevation, so the unprivileged wrapper phase keeps the caller's PATH
and can still find sudo or pkexec; every helper the privileged half uses is a
system utility, so it needs nothing from the checkout.

Clean cherry-pick: both files are byte-identical to quattro, so merging v4-0-1
into quattro resolves without a conflict. Verified by mutation: with the pin
removed, test/shell.d/dns-sudoers-test.sh fails at the poisoned-helper case;
restored, all four of its cases pass. test/shell (189 files) and test/cli pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 09:44:35 +02:00
OmarchybotandClaude Opus 5 07adef8a53 Let a received Taildrop file wait to be answered (backport of #7953)
Backport of the Taildrop toast fix (PR #7953, merged to quattro as 7e469f96)
onto the v4-0-1 release branch.

A delivery can land hours after it was sent, and the toast announcing it was
expiring after five seconds -- so a file that arrived while nobody was at the
machine was gone from the screen before anyone could click it open. Critical
urgency is what the shell reads as a popup that lives until it is clicked or
dismissed, the same thing omarchy-crash-watch uses to keep its click-to-diagnose
toast around.

The mechanism is already on this branch: omarchy-notification-send parses
options that follow the two positionals, and NotificationLogic.js gives a
critical popup duration 0, which never expires.

One conflict, in test/shell.d/notification-send-test.sh. #7953 added coverage
for the trailing-option path in the notify-send form it had then; #7926, which
merged after it on quattro and is already backported here, rewrote that file for
the Notify D-Bus form and carried the same coverage across. This branch
therefore already asserts what #7953 added -- an urgency and a glyph after the
description reach the call, and the urgency is set once -- so the branch's
version stands and the resolved file is unchanged.

Verified by mutation: with -u critical removed, test/shell.d/tailscale-receive-
test.sh fails at once; restored, it passes, including the new assertion that
every announcement waits to be answered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 09:39:50 +02:00
OmarchybotandClaude Opus 5 e713ff3166 Share the git URL check, and refuse the transports Omarchy does not clone from (backport of #8174)
Backport of the shared URL check (PR #8174, merged to quattro as 68ab12f7) onto
the v4-0-1 release branch, on top of the #8067 backport it follows.

omarchy-theme-install and omarchy-plugin-add both clone a URL a stranger can
choose, and each carried its own copy of the rule that refuses a git option or a
transport helper before cloning. The rule now lives in omarchy-git-url-check and
both callers ask it: two copies of a security check drift, and the second copy
arrived four months after the first only because someone went looking for it.

That rule was also enforcing half of what it described. <helper>::<address> is
one of two shapes git resolves a remote helper from -- it also runs
git-remote-<scheme> for <scheme>://<address> whenever the scheme is not one it
connects itself, so ext::sh -c id and ext://sh -c id reach the same helper while
only the first was refused. Nothing exploitable follows on a stock system:
protocol.ext.allow defaults to never, and the :// spelling hands git-remote-ext
a command name it cannot exec. But a third-party helper installed on PATH is
reachable through the scheme form alone, and a guard is worth more when it
enforces the rule it states.

The :// shape cannot be refused the way :: is, because it is also how every
legitimate URL arrives, so the scheme is checked against the transports git
still connects itself: ssh git git+ssh ssh+git http https ftp ftps file.
git+ssh and ssh+git are on that list because they are spelled like a helper and
read as plain ssh; leaving them off would refuse a URL that clones today. ext
and fd are off it deliberately. A single colon is always scp-style ssh and a
bare path is always a path, so neither needs constraining.

The check fails closed: the callers read a non-zero status as a refusal, so a
missing omarchy-git-url-check refuses the URL rather than waving it through.

Clean cherry-pick on top of the #8067 backport: every file is byte-identical to
quattro, so merging v4-0-1 into quattro resolves without a conflict. test/shell
passes: 189 files, including the one this adds. test/cli passes, so the new
command's metadata is well-formed. Exercised the check here: https, scp-style,
ssh, git+ssh and scp-style IPv6 all pass, while ext:: ext:// fd:: fd:// and a
leading-dash form are refused, as is an uppercase EXT:// spelling.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 09:13:35 +02:00
OmarchybotandClaude Opus 5 c7af36d0aa Offer to reboot when toggling sudoless Docker; show only the relevant menu entry (backport of #8098)
Backport of the sudoless Docker follow-up (PR #8098, merged to quattro as
06a3dbca) onto the v4-0-1 release branch, on top of the #8056 and #8080
backports it follows.

Group membership only takes effect on a fresh session, and in practice a logout
or newgrp is not enough -- only a reboot reliably applies it. The setup and
remove commands now flag the reboot and offer to do it right away with a gum
confirm, the same shape as the GPU toggle, and their notices say "after a
reboot" instead of pointing at logout or newgrp. The existing-user migration
reuses the removal command inside omarchy update, so it passes
OMARCHY_DEFER_REBOOT to skip the prompt there and lets omarchy-update-restart
handle the reboot once the whole update has finished.

Setup > Security showed Sudoless Docker under both Setup and Remove, and the
guards tested the running session's groups, which do not change until the
reboot: after enabling sudoless Docker the menu still offered Setup, the one
action that could no longer do anything, while Remove stayed hidden. Add
omarchy-sudo-docker as the single answer to both questions that differ in that
window -- by default whether this session can reach the socket, which is what
decides if a command must elevate, and with --configured whether the account is
set up for it, which is what the menu and the toggles need. It succeeds when
sudo is needed, so the Setup entry appears while sudoless Docker is off and
Remove once it is on. lazydocker and the Windows VM keep prompting until the
reboot lands.

Clean cherry-pick on top of the earlier backports: every file is byte-identical
to quattro except default/omarchy/omarchy-menu.jsonc, which merged into this
branch's menu and whose two Sudoless Docker lines match quattro exactly.
test/shell passes: 188 files, including the two this adds. test/cli passes, so
the new command's metadata is well-formed. Exercised the helper here: with no
socket it reports sudo is needed, and --configured answers from the account's
groups.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 09:02:57 +02:00
BastiandClaude Opus 5 b3028f9bd9 Guard plugin-add against git transport-helper URLs (backport of #8067)
Backport of the plugin-add URL guard (PR #8067 by @bastidotnet, merged to
quattro as 30471bf3) onto the v4-0-1 release branch.

omarchy-plugin-add cloned a user-supplied git URL without the transport-helper
guard omarchy-theme-install already applies. That guard arrived with #7884,
which is on this branch, but it never touched plugin-add -- so the sibling
command still leaned entirely on git's own protocol.ext.allow=never to keep a
URL like ext::sh -c <cmd> from running a command at clone time.

Stock systems are unaffected: Omarchy sets no protocol.* override, so the git
default holds and there is no live exploit here. This is defense in depth --
it closes the gap #7884 left in the sibling path and drops a silent dependency
on a default the project does not control. Reject ext::/fd:: and leading-dash
forms; https, ssh, scp-style and token-auth URLs still clone, including an
scp-style IPv6 host, which carries :: of its own.

Clean cherry-pick: both files are byte-identical to quattro, so merging v4-0-1
into quattro resolves without a conflict. The guard reads the same as the one
already in bin/omarchy-theme-install on this branch. test/shell passes: 186
files, with the plugin-add suite's new cases all running here -- including the
pty-driven prompt case, which is the only path that reaches the guard's
leading-dash arm.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 08:32:58 +02:00
David Heinemeier HanssonandClaude Opus 5 0f4abeec8e Wait for the keypress ourselves instead of asking gum to (backport of #8082)
Backport of the keypress fix (PR #8082, merged to quattro as 5d3299fb) onto the
v4-0-1 release branch.

gum 2.0 runs a spun command without the terminal attached, so the gum spin --
read -n 1 that held the presentation terminal open returned at once. Every menu
command that ended in a failure took its window down with it before the error
could be read, which is how a failed update looked like a terminal that just
quit.

Read the key directly. gum's own terminal query replies are still sitting on the
tty when the spinner stops, so drain those first or they answer the prompt on
the user's behalf. The /dev/tty node is there whether or not a terminal is
behind it, so open it rather than test for it -- the existence check passed on a
headless run and left both reads failing with "No such device or address" -- and
prompt on the terminal rather than stdout, so a caller that redirects us does
not leave the user waiting on a prompt they were never shown.

The green dot reads better than the globe did, so the provisioning notice uses
it too and drops its spinner along the way.

Clean cherry-pick: both files are byte-identical to quattro, so merging v4-0-1
into quattro resolves without a conflict. Exercised against the installed gum
2.0.0: headless it exits 0 at once, and on a pty it prints the prompt and
returns on one keypress. test/shell (186 files) and test/cli pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-24 19:58:40 +02:00
OmarchybotandClaude Opus 5 7b89780810 Flag a reboot when the docker group changes (backport of #8080)
Backport of the reboot flag (PR #8080, merged to quattro as 1565919c) onto the
v4-0-1 release branch, on top of the #8056 backport it follows.

Group membership is fixed at login, so removing (or adding) the docker group
does not take effect in the running session. The existing-user migration and the
Setup > Security toggles now call omarchy-state set reboot-required, so
omarchy-update-restart prompts for the reboot that actually applies the change
and the bar shows it pending. A plain log out and back in still works.

The migration test now exercises the real removal command and omarchy-state
rather than a stub, asserting the reboot flag is set on removal and left alone
when the user is already out of the group.

Clean cherry-pick on top of the #8056 backport: all three files are
byte-identical to quattro, so merging v4-0-1 into quattro resolves without a
conflict. omarchy-state and omarchy-update-restart are unchanged on this branch
and read the same ~/.local/state/omarchy/reboot-required marker. test/shell
passes: 186 files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-24 19:56:19 +02:00