Merge branch 'dev' into rc

This commit is contained in:
David Heinemeier Hansson
2026-04-23 11:57:26 +02:00
15 changed files with 136 additions and 41 deletions
+1
View File
@@ -10,6 +10,7 @@ if [[ -f $FIRST_RUN_MODE ]]; then
rm -f "$FIRST_RUN_MODE" rm -f "$FIRST_RUN_MODE"
bash "$OMARCHY_PATH/install/first-run/battery-monitor.sh" bash "$OMARCHY_PATH/install/first-run/battery-monitor.sh"
bash "$OMARCHY_PATH/install/first-run/recover-internal-monitor.sh"
bash "$OMARCHY_PATH/install/first-run/cleanup-reboot-sudoers.sh" bash "$OMARCHY_PATH/install/first-run/cleanup-reboot-sudoers.sh"
bash "$OMARCHY_PATH/install/first-run/firewall.sh" bash "$OMARCHY_PATH/install/first-run/firewall.sh"
bash "$OMARCHY_PATH/install/first-run/dns-resolver.sh" bash "$OMARCHY_PATH/install/first-run/dns-resolver.sh"
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# Returns true when an external monitor is physically connected.
# Uses kernel DRM state so the result is independent of Hyprland's startup timing.
for status in /sys/class/drm/card*-*/status; do
[[ "$status" == *-eDP-*/status ]] && continue
[[ "$(<"$status")" == "connected" ]] && exit 0
done
exit 1
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
# Clear the internal-monitor-disable toggle if no external display is connected.
# Runs before the graphical session so Hyprland doesn't block on having no output
# to render to when the user rebooted with the external unplugged.
TOGGLE="$HOME/.local/state/omarchy/toggles/hypr/internal-monitor-disable.conf"
if [[ -f $TOGGLE ]] && ! omarchy-hw-external-monitors; then
rm -f "$TOGGLE"
fi
+3 -3
View File
@@ -9,7 +9,7 @@ enable() {
} }
disable() { disable() {
if omarchy-hyprland-monitors-many; then if omarchy-hw-external-monitors; then
if omarchy-hyprland-toggle-disabled "$TOGGLE"; then if omarchy-hyprland-toggle-disabled "$TOGGLE"; then
omarchy-hyprland-toggle --enabled-notification "󰍹 Laptop display disabled" "$TOGGLE" omarchy-hyprland-toggle --enabled-notification "󰍹 Laptop display disabled" "$TOGGLE"
fi fi
@@ -20,8 +20,8 @@ disable() {
} }
recover() { recover() {
if omarchy-hyprland-monitors-none && omarchy-hyprland-toggle-enabled "$TOGGLE"; then if ! omarchy-hw-external-monitors && omarchy-hyprland-toggle-enabled "$TOGGLE"; then
enable omarchy-hyprland-toggle "$TOGGLE"
fi fi
} }
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
# Returns true when there are multiple monitors connected (so we can disable the internal one)
(( $(hyprctl monitors -j 2>/dev/null | jq length) > 1 ))
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
# Returns true when no monitors are connected
(( $(hyprctl monitors -j 2>/dev/null | jq length) == 0 ))
+25 -9
View File
@@ -1,12 +1,19 @@
#!/bin/bash #!/bin/bash
# Toggle passwordless sudo for the current user. # Toggle passwordless sudo for the current user.
# Usage: omarchy-sudo-passwordless-toggle [MINUTES]
# First run: enables passwordless sudo for 15 minutes (after confirmation). # First run: enables passwordless sudo for 15 minutes (after confirmation).
# Second run: disables it early. # Second run: disables it early.
NOPASSWD_FILE="/etc/sudoers.d/99-omarchy-nopasswd-${USER}" NOPASSWD_FILE="/etc/sudoers.d/99-omarchy-nopasswd-${USER}"
TIMER_NAME="omarchy-nopasswd-expire-${USER}" TIMER_NAME="omarchy-nopasswd-expire-${USER}"
MINUTES=${1:-15}
if [[ $1 && ! $1 =~ ^[0-9]+$ ]]; then
echo "Usage: omarchy-sudo-passwordless-toggle [MINUTES]" >&2
exit 1
fi
# Safety: if the file exists but the timer doesn't (e.g. after reboot), clean up # Safety: if the file exists but the timer doesn't (e.g. after reboot), clean up
if sudo test -f "$NOPASSWD_FILE" && ! systemctl is-active "${TIMER_NAME}.timer" &>/dev/null; then if sudo test -f "$NOPASSWD_FILE" && ! systemctl is-active "${TIMER_NAME}.timer" &>/dev/null; then
sudo rm "$NOPASSWD_FILE" sudo rm "$NOPASSWD_FILE"
@@ -14,28 +21,37 @@ fi
# Check for the file directly — sudo -n can stay cached or be granted by other rules # Check for the file directly — sudo -n can stay cached or be granted by other rules
if sudo test -f "$NOPASSWD_FILE"; then if sudo test -f "$NOPASSWD_FILE"; then
sudo rm "$NOPASSWD_FILE" if [[ $1 ]]; then
sudo systemctl stop "${TIMER_NAME}.timer" 2>/dev/null sudo systemctl stop "${TIMER_NAME}.timer" 2>/dev/null
echo "Passwordless sudo has been DISABLED. Sudo will require a password again." sudo systemd-run --on-active=${MINUTES}m --timer-property=AccuracySec=1s --unit="$TIMER_NAME" \
rm "$NOPASSWD_FILE"
echo "Passwordless sudo timer updated. It will now automatically disable in ${MINUTES} minutes."
else
sudo rm "$NOPASSWD_FILE"
sudo systemctl stop "${TIMER_NAME}.timer" 2>/dev/null
echo "Passwordless sudo has been DISABLED. Sudo will require a password again."
fi
else else
echo "" echo ""
echo "⚠️ WARNING: This will allow ANY process running as your user to" echo "⚠️WARNING: This will allow ANY process running as your user to"
echo "execute ANY command as root WITHOUT a password for 15 minutes." echo "execute ANY command as root WITHOUT a password for ${MINUTES} minutes."
echo "" echo ""
echo "This is useful for AI agents that need to run sudo commands," echo "This is useful for AI agents that need to run sudo commands,"
echo "but it significantly weakens the security of your system." echo "but it significantly weakens the security of your system."
echo "Anyone or anything with access to your user account gets full root." echo "Anyone or anything with access to your user account gets full root."
echo "" echo ""
echo "Passwordless sudo will automatically disable after 15 minutes." echo "Passwordless sudo will automatically disable after ${MINUTES} minutes."
echo "Run this command again to disable it early." echo "Run this command again to disable it early."
echo "" echo ""
if gum confirm "Enable passwordless sudo for 15 minutes? This is a significant security risk!"; then if gum confirm "Enable passwordless sudo for ${MINUTES} minutes? This is a significant security risk!"; then
echo "${USER} ALL=(ALL) NOPASSWD: ALL" | sudo tee "$NOPASSWD_FILE" > /dev/null echo "${USER} ALL=(ALL) NOPASSWD: ALL" | sudo tee "$NOPASSWD_FILE" > /dev/null
sudo chmod 440 "$NOPASSWD_FILE" sudo chmod 440 "$NOPASSWD_FILE"
sudo systemd-run --on-active=15m --timer-property=AccuracySec=1s --unit="$TIMER_NAME" \ sudo systemd-run --on-active=${MINUTES}m --timer-property=AccuracySec=1s --unit="$TIMER_NAME" \
rm "$NOPASSWD_FILE" rm "$NOPASSWD_FILE"
echo "Passwordless sudo has been ENABLED. It will automatically disable in 15 minutes."
echo ""
echo "Passwordless sudo has been ENABLED. It will automatically disable in ${MINUTES} minutes."
echo "Note: if you restart before then, run omarchy-sudo-passwordless-toggle again to disable it." echo "Note: if you restart before then, run omarchy-sudo-passwordless-toggle again to disable it."
else else
echo "Aborted. No changes made." echo "Aborted. No changes made."
@@ -0,0 +1,11 @@
[Unit]
Description=Recover the internal monitor toggle when no external display is connected
Before=graphical-session-pre.target
ConditionPathExists=%h/.local/state/omarchy/toggles/hypr/internal-monitor-disable.conf
[Service]
Type=oneshot
ExecStart=%h/.local/share/omarchy/bin/omarchy-hw-recover-internal-monitor
[Install]
WantedBy=graphical-session-pre.target
+1
View File
@@ -48,6 +48,7 @@ alias cx='printf "\033[2J\033[3J\033[H" && claude --permission-mode bypassPermis
alias d='docker' alias d='docker'
alias r='rails' alias r='rails'
alias t='tmux attach || tmux new -s Work' alias t='tmux attach || tmux new -s Work'
alias i='tdl c cx'
n() { if [ "$#" -eq 0 ]; then command nvim . ; else command nvim "$@"; fi; } n() { if [ "$#" -eq 0 ]; then command nvim . ; else command nvim "$@"; fi; }
# Git # Git
-1
View File
@@ -7,7 +7,6 @@ exec-once = uwsm-app -- swayosd-server
exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
exec-once = omarchy-cmd-first-run exec-once = omarchy-cmd-first-run
exec-once = omarchy-powerprofiles-init exec-once = omarchy-powerprofiles-init
exec-once = omarchy-hyprland-monitor-internal recover
exec-once = uwsm-app -- omarchy-hyprland-monitor-watch exec-once = uwsm-app -- omarchy-hyprland-monitor-watch
# Slow app launch fix -- set systemd vars # Slow app launch fix -- set systemd vars
+8
View File
@@ -0,0 +1,8 @@
# Omarchy snapshots root only for pre-update recovery — kept to 5, no timeline
SUBVOLUME="/"
FSTYPE="btrfs"
NUMBER_LIMIT="5"
NUMBER_LIMIT_IMPORTANT="5"
TIMELINE_CREATE="no"
@@ -0,0 +1 @@
systemctl --user enable omarchy-recover-internal-monitor.service
+6 -18
View File
@@ -50,26 +50,14 @@ EOF
# We overwrite the whole thing knowing the limine-update will add the entries for us # We overwrite the whole thing knowing the limine-update will add the entries for us
sudo cp $OMARCHY_PATH/default/limine/limine.conf /boot/limine.conf sudo cp $OMARCHY_PATH/default/limine/limine.conf /boot/limine.conf
# Match Snapper configs if not installing from the ISO # Only snapshot root — /home is user data; rolling it back loses user work
if [[ -z ${OMARCHY_CHROOT_INSTALL:-} ]]; then if ! sudo snapper list-configs 2>/dev/null | grep -q "root"; then
if ! sudo snapper list-configs 2>/dev/null | grep -q "root"; then sudo snapper -c root create-config /
sudo snapper -c root create-config /
fi
if ! sudo snapper list-configs 2>/dev/null | grep -q "home"; then
sudo snapper -c home create-config /home
fi
fi fi
sudo cp $OMARCHY_PATH/default/snapper/root /etc/snapper/configs/root
# Enable quota to allow space-aware algorithms to work # Disable btrfs quotas — full qgroup accounting is a major performance drag
sudo btrfs quota enable / sudo btrfs quota disable / 2>/dev/null || true
# Tweak default Snapper configs
sudo sed -i 's/^TIMELINE_CREATE="yes"/TIMELINE_CREATE="no"/' /etc/snapper/configs/{root,home}
sudo sed -i 's/^NUMBER_LIMIT="50"/NUMBER_LIMIT="5"/' /etc/snapper/configs/{root,home}
sudo sed -i 's/^NUMBER_LIMIT_IMPORTANT="10"/NUMBER_LIMIT_IMPORTANT="5"/' /etc/snapper/configs/{root,home}
sudo sed -i 's/^SPACE_LIMIT="0.5"/SPACE_LIMIT="0.3"/' /etc/snapper/configs/{root,home}
sudo sed -i 's/^FREE_LIMIT="0.2"/FREE_LIMIT="0.3"/' /etc/snapper/configs/{root,home}
chrootable_systemctl_enable limine-snapper-sync.service chrootable_systemctl_enable limine-snapper-sync.service
fi fi
+50
View File
@@ -0,0 +1,50 @@
echo "Drop /home snapshots, btrfs quotas, and timeline snapshots (keep 5 root snapshots, never more)"
if ! omarchy-cmd-present snapper btrfs; then
exit 0
fi
# Disable btrfs quotas first — every subvolume delete below would otherwise update
# all qgroups, which is exactly the performance drag we're removing.
sudo btrfs quota disable / 2>/dev/null || true
# Remove the home config, all its snapshots, and the .snapshots subvolume.
# If the snapshots look like someone's been using them manually (pre/post pairs,
# userdata tags, freeform descriptions), ask before destroying.
if sudo snapper list-configs 2>/dev/null | grep -q "home"; then
drop_home="yes"
if sudo snapper -c home --csvout list 2>/dev/null | \
awk -F, 'NR>1 && ($6=="pre" || $6=="post" || $13!="" || ($12!="current" && $12!="timeline" && $12 !~ /^[0-9]+\.[0-9]+\.[0-9]+/))' | \
grep -q .; then
gum confirm "Drop unused /home snapshots for better performance?" || drop_home="no"
fi
if [[ $drop_home == "yes" ]]; then
sudo snapper -c home list --columns number 2>/dev/null | awk 'NR>2 && $1 != "0" {print $1}' | \
xargs -r sudo snapper -c home delete 2>/dev/null
sudo snapper -c home delete-config 2>/dev/null
if [[ -d /home/.snapshots ]]; then
for snap in /home/.snapshots/*/snapshot; do
[[ -d $snap ]] && sudo btrfs subvolume delete "$snap" 2>/dev/null
done
sudo rm -rf /home/.snapshots/* 2>/dev/null
sudo btrfs subvolume delete /home/.snapshots 2>/dev/null
fi
fi
fi
# Ensure root config exists and matches our shipped defaults
if ! sudo snapper list-configs 2>/dev/null | grep -q "root"; then
sudo snapper -c root create-config /
fi
sudo cp $OMARCHY_PATH/default/snapper/root /etc/snapper/configs/root
# Delete all timeline snapshots — we only want pre-update (cleanup=number) snapshots
sudo snapper -c root list --columns number,cleanup 2>/dev/null | \
awk '$3 == "timeline" {print $1}' | \
xargs -r sudo snapper -c root delete 2>/dev/null
# Enforce NUMBER_LIMIT=5 on any existing number snapshots beyond the new cap
sudo snapper -c root cleanup number 2>/dev/null
+9
View File
@@ -0,0 +1,9 @@
echo "Recover the internal monitor at login when no external display is connected"
SERVICE=omarchy-recover-internal-monitor.service
mkdir -p ~/.config/systemd/user
cp $OMARCHY_PATH/config/systemd/user/$SERVICE ~/.config/systemd/user/$SERVICE
systemctl --user daemon-reload
systemctl --user enable $SERVICE