* Remove unsafe project bin PATH injection
* Cover customized unsafe Mise paths
* Revoke legacy Mise Work trust
* Harden legacy Mise trust cleanup
* Preserve ignored Mise Work configs
* Scope Mise path cleanup to env
* Accept paranoid Mise ignore marker
Reported-by: infosec-us-team
* Keep screen-recording state out of world-writable /tmp
* Compare the /tmp name across the run instead of requiring it absent
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Fall back to the state directory when there is no runtime dir
* Let the /tmp snapshot come back empty
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Resolve the region file the same way in the resizer
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Protect recording fallback state and document its path
---------
Co-authored-by: Omabot <omabot@omarchy.org>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
No branch on the repo is protected and there are no rulesets, so the
file never enforced owner review. Its only effect was auto-requesting a
review from the other owner on every PR, which nobody acted on.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The repo moved to the omacom org. GitHub redirects the old URLs, but
`omarchy channel set dev` was still cloning from basecamp/omarchy, which
left every dev checkout with a stale origin remote that confuses gh
(pr create fails with "No commits between omacom:quattro and
basecamp:<branch>"). Update the clone URL, the quattro upgrade tarball,
the update-confirm release link, the systemd Documentation link, and
the manual.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSFKDatumRZHB8zqk5CP5C
1Password 8.12 changed its app id from "1Password" to
"com.onepassword.OnePassword" (its .desktop file now declares that as
StartupWMClass). Our window rule only matched the old name, so the main
window came up tiled and lost the no_screen_share protection.
Match both forms so older installs keep working.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSFKDatumRZHB8zqk5CP5C
A floating window on the console is not laid out by the gaps, so it no
longer stretches the panel to full width. Moving an app onto or off the
scratchpad and toggling floating now refit too, via
window.move_to_workspace and window.update_rules; both were measured on
Hyprland 0.56.2 to carry the settled count.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012UyVoFTM98Tduoxg7qZax7
Cubic keeps pushing until packets drop, which stands queues up in the path
on fast links. BBR paces to its estimate of bottleneck bandwidth and minimum
RTT instead, cutting queueing latency while keeping throughput. fq is the
qdisc BBR is built to pace through.
tcp_bbr and sch_fq are modules in every kernel Omarchy ships and autoload
when the sysctls are set. The migration re-applies the shipped file so new
connections switch without a reboot, no-ops once the live values match, and
flags a reboot if applying fails.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Offline installs unpack the bundled tarball and pin Node to its exact
version, since latest can't be resolved without network. But nothing ever
loosened that pin, so Node stayed frozen at the ISO's version and mup
skipped it forever, while online installs tracked latest.
Rewrite the pin to latest right after registering the bundled version:
mise resolves latest to the installed version while offline (verified
with no network and an empty cache), and the first mise up with network
picks up new releases just like an online install.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017LseZ1jcLaFBnndRnW4yb5
udev patterns are shell globs, so nvme[0-9]*n[0-9]* also matched every
partition. Partitions have no queue/scheduler, and udev logged a "Could not
chase sysfs attribute" for each one at boot. Restrict the match to
SUBSYSTEM block with DEVTYPE disk, which also keeps mmcblk boot areas and
NVMe multipath nodes out.
Reword the comment: kyber targets a read latency rather than bounding it,
and the kernel's default choice depends on the device rather than being a
fixed NVMe versus everything-else split.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The kernel leaves NVMe on none and everything else on mq-deadline. Neither
bounds latency once the device queue fills, so a large build, copy, or
package upgrade can make the desktop sluggish while reads wait behind a
wall of writes.
Kyber keeps separate read and sync-write queues and throttles the depth it
submits to hit a 2ms read target, which keeps interactive reads flowing
under heavy writes at negligible CPU cost. The trade is a small ceiling on
peak throughput on very fast devices, which matters for a storage server
chasing IOPS but not for a desktop.
Ships as a package-owned udev rule in /etc so it applies at boot and on
hot-plug. Existing installs pick it up at the next boot. zram is left alone
since it has nothing to schedule.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The update conflict tests stub sudo and pacman, but omarchy-update-pacman
now puts systemd-run between them, so on a systemd-booted host the tests
would reach for the real system manager. Stub systemd-run to drop the
wrapper's options and run the command, and cover the helper's own
invocation composition in a new test.
Raised by codex review.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zcqENR1UbhuwC1v5u3Wop
omarchy-channel-set runs under set -e, so a failure after it has begun
mutating the system (dev link, pacman channel, packages) died silently
with the switch half-applied. Trap ERR once the mutation phase starts
and say how to pick the switch back up.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The floating-terminal presentation wrapper showed the green "Done!"
prompt for every exit code except Ctrl-C, so a failed update or channel
switch closed looking like a success. Pass the command's exit code
through to omarchy-show-done and render a red "Failed (exit code N)!"
prompt when it is non-zero. The pkg install/remove pickers get the same
treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Upgrading systemd runs its post_upgrade scriptlet mid-transaction, which
reexecs both the system manager and every user manager. When pacman runs
inside a user-session scope (the floating update terminal), that reexec
can SIGKILL it and abandon the transaction halfway, with packages
upgraded but none of the post-transaction hooks run.
Route every Omarchy-owned system mutation through a new hidden
omarchy-update-pacman helper that registers the transaction as a PID 1
scope via systemd-run, keeping it out of the user manager's cgroups.
System scopes survive the system manager's own reexec, and as a bonus the
transaction now also survives its terminal window closing. On unbooted
systems (the installer chroot) the helper runs pacman directly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The theme laid out the logo, password entry and progress bar once, when
the script first ran. Plymouth sizes its window to the largest display
present, so a monitor that comes up after plymouthd starts (a Thunderbolt
display whose DisplayPort tunnel is established about a second after the
kernel's display driver loads, a dock, an MST hub) got the prompt drawn at
the internal panel's coordinates: off-center on the external display and
partly off-screen on the panel. With the lid closed the passphrase box was
effectively invisible.
Move the layout into a function and re-run it from the refresh callback
whenever Window.GetWidth/GetHeight change, which is how Plymouth's script
plugin exposes a display being added or removed. Existing bullets are
repositioned too.
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
The battery service ran `powerprofilesctl get` every two seconds to keep the
active profile visible to the wallpaper and lock services. That command is a
PyGObject script, so the shell spawned a Python interpreter for it tens of
thousands of times a day. Roughly once a day one of those exits into a CPython
3.14 finalization race (python/cpython#124619): the GLib D-Bus worker thread
calls PyGILState_Ensure after the interpreter is torn down and the process
dies with SIGSEGV, leaving a core dump and a crash notification behind.
Read the ActiveProfile property straight from power-profiles-daemon with
busctl, the same way omarchy-powerprofiles-set already reads UPower. The
output is JSON, so an empty or malformed reply when the daemon is not running
still reads as no active profile, matching the previous behaviour.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gbfh4Mi9dK6SAd1P2xMTi
The speaker's USB firmware stops answering control requests when the host
stops the audio stream after WirePlumber's 5 s idle suspend. The kernel
then logs usb_set_interface failed (-110), clock source 1 is not valid,
and cannot set freq 48000 err -110; PipeWire fails to start the sink and
only a replug recovers it. On one machine this happened on six days over
three weeks, up to hundreds of timeouts a day.
A WirePlumber rule sets session.suspend-timeout-seconds = 0 for the KEF
node only, so the stream is never stopped and the trigger never fires.
Other sinks keep the default. The migration seeds the file for existing
installs and restarts WirePlumber if it is running, since conf.d is only
read at startup.
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>