Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion bin/omarchy-brightness-display-ddc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,30 @@ step="${2:-}"

[[ -n $monitor ]] || exit 1

cache_dir="${XDG_RUNTIME_DIR:-/tmp}/omarchy-brightness-display-ddc"
# Bus/range cache must not land at a fixed name in world-writable /tmp.
# Prefer XDG_RUNTIME_DIR; otherwise a private 0700 owner-checked state dir.
private_cache_root() {
local root mode

if [[ -n ${XDG_RUNTIME_DIR:-} ]]; then
printf '%s\n' "$XDG_RUNTIME_DIR"
return 0
fi

root="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy"
mkdir -p "$root" || return 1
chmod 700 "$root" || return 1
[[ -O $root ]] || return 1
mode=$(stat -c '%a' "$root" 2>/dev/null || stat -f '%Lp' "$root")
[[ $mode == 700 ]] || return 1
printf '%s\n' "$root"
}

cache_root=$(private_cache_root) || {
echo "Failed to resolve a private cache directory for DDC brightness." >&2
exit 1
}
cache_dir="$cache_root/omarchy-brightness-display-ddc"
cache_name="${monitor//[^[:alnum:]_.-]/_}"
cache_file="$cache_dir/$cache_name.bus"
unavailable_cache_seconds=60
Expand Down
28 changes: 26 additions & 2 deletions bin/omarchy-capture-region
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,32 @@
# --match-monitor print "monitor:NAME" instead when the picked geometry
# exactly matches a monitor

FULLSCREEN_MARKER="${XDG_RUNTIME_DIR:-/tmp}/omarchy-capture-region-fullscreen"
WINDOW_MARKER="${XDG_RUNTIME_DIR:-/tmp}/omarchy-capture-region-window"
# Fullscreen/window markers must not sit at fixed names in world-writable /tmp.
# Prefer XDG_RUNTIME_DIR; otherwise a private 0700 owner-checked state dir.
private_marker_root() {
local root mode

if [[ -n ${XDG_RUNTIME_DIR:-} ]]; then
printf '%s\n' "$XDG_RUNTIME_DIR"
return 0
fi

root="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy"
mkdir -p "$root" || return 1
chmod 700 "$root" || return 1
[[ -O $root ]] || return 1
mode=$(stat -c '%a' "$root" 2>/dev/null || stat -f '%Lp' "$root")
[[ $mode == 700 ]] || return 1
printf '%s\n' "$root"
}

marker_root=$(private_marker_root) || {
echo "Failed to resolve a private directory for capture-region markers." >&2
exit 1
}
mkdir -p "$marker_root"
FULLSCREEN_MARKER="$marker_root/omarchy-capture-region-fullscreen"
WINDOW_MARKER="$marker_root/omarchy-capture-region-window"

# accounting for portrait/transformed displays
JQ_MONITOR_GEO='
Expand Down
25 changes: 23 additions & 2 deletions bin/omarchy-debug
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,32 @@ while (( $# > 0 )); do
esac
done

LOG_FILE="/tmp/omarchy-debug.log"
# /tmp is world-writable, so a fixed name there is created world-readable by
# the default umask and left behind until reboot -- and this one holds
# `sudo dmesg`, the journal, and a full hardware inventory that the invoking
# user's own uid otherwise cannot read. Keep it under the per-user runtime
# directory (0700) instead, and fall back to the state directory where
# Omarchy keeps everything else of its own when there is no session runtime dir.
log_dir="${XDG_RUNTIME_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/omarchy}"
LOG_FILE="$log_dir/omarchy-debug.log"

# Nothing here runs under `set -e`, so an unusable log_dir -- a stale
# XDG_RUNTIME_DIR, a full tmpfs, a read-only home -- would leave `--print`
# exiting 0 having printed nothing at all. -T is what makes a directory at
# LOG_FILE an error; without it `install` treats one as a destination
# directory, writes $LOG_FILE/null, and reports success.
if ! mkdir -p "$log_dir" || ! install -T -m 600 /dev/null "$LOG_FILE"; then
echo "Error: Failed to create $LOG_FILE" >&2
exit 1
fi

if [[ $NO_SUDO = "true" ]]; then
DMESG_OUTPUT="(skipped - --no-sudo flag used)"
else
DMESG_OUTPUT="$(sudo dmesg)"
fi

cat > "$LOG_FILE" <<EOF
if ! cat > "$LOG_FILE" <<EOF
Date: $(date)
Hostname: $(hostname)
Omarchy Package: $(pacman -Q omarchy-dev 2>/dev/null || pacman -Q omarchy 2>/dev/null || echo "unknown")
Expand All @@ -59,6 +76,10 @@ INSTALLED PACKAGES
=========================================
$({ expac -S '%n %v (%r)' $(pacman -Qqe) 2>/dev/null; comm -13 <(pacman -Sql | sort) <(pacman -Qqe | sort) | xargs -r expac -Q '%n %v (AUR)'; } | sort)
EOF
then
echo "Error: Failed to write $LOG_FILE" >&2
exit 1
fi

if [[ $PRINT_ONLY = "true" ]]; then
cat "$LOG_FILE"
Expand Down
5 changes: 4 additions & 1 deletion bin/omarchy-dev-link
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ done
# Staged and parsed before anything is installed: a sudoers file sudo refuses to
# read takes every rule after it down with it, including the %wheel grant, and
# the password prompt needed to undo that is on the other side of the breakage.
staged_sudoers=$(mktemp)
# Keep the draft out of world-writable /tmp; visudo -cf reads it before install.
stage_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$stage_dir"
staged_sudoers=$(mktemp "$stage_dir/omarchy-dev-path.XXXXXX")
trap 'rm -f "$staged_sudoers"' EXIT

{
Expand Down
6 changes: 4 additions & 2 deletions bin/omarchy-hyprland-monitor-watch
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
# omarchy:summary=Watch Hyprland monitor events and recover monitor toggles when a monitor is removed

SOCKET="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-monitor-clamshell.lock"
MODELESS_LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-monitor-modeless.lock"
LOCK_DIR="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$LOCK_DIR"
LOCK="$LOCK_DIR/omarchy-monitor-clamshell.lock"
MODELESS_LOCK="$LOCK_DIR/omarchy-monitor-modeless.lock"

sync_clamshell() {
(
Expand Down
10 changes: 6 additions & 4 deletions bin/omarchy-menu-images
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ if (( ${#image_dirs[@]} == 0 )); then
exit 1
fi

selection_file=$(mktemp)
done_file=$(mktemp)
pending_file=$(mktemp)
pending_video_file=$(mktemp)
ipc_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$ipc_dir"
selection_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
done_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
pending_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
pending_video_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file" "$pending_file" "$pending_video_file"' EXIT

Expand Down
6 changes: 4 additions & 2 deletions bin/omarchy-menu-input
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ while (( $# > 0 )); do
shift
done

selection_file=$(mktemp)
done_file=$(mktemp)
ipc_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$ipc_dir"
selection_file=$(mktemp "$ipc_dir/omarchy-menu-input.XXXXXX")
done_file=$(mktemp "$ipc_dir/omarchy-menu-input.XXXXXX")
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file"' EXIT

Expand Down
6 changes: 4 additions & 2 deletions bin/omarchy-menu-select
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ if (( ${#options[@]} == 0 )); then
exit 1
fi

selection_file=$(mktemp)
done_file=$(mktemp)
ipc_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$ipc_dir"
selection_file=$(mktemp "$ipc_dir/omarchy-menu-select.XXXXXX")
done_file=$(mktemp "$ipc_dir/omarchy-menu-select.XXXXXX")
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file"' EXIT

Expand Down
24 changes: 18 additions & 6 deletions bin/omarchy-menu-share
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ fi
MODE="$1"
shift

TEMP_FILE=""
cleanup() {
[[ -n ${TEMP_FILE:-} && -f $TEMP_FILE ]] && rm -f "$TEMP_FILE"
}
trap cleanup EXIT

if [[ $MODE == "clipboard" ]]; then
TEMP_FILE=$(mktemp --suffix=.txt)
# Private runtime dir — shared /tmp left clipboard contents readable to peers.
share_dir="${XDG_RUNTIME_DIR:-$HOME/.local/state/omarchy}"
mkdir -p "$share_dir"
chmod 700 "$share_dir" 2>/dev/null || true
TEMP_FILE=$(mktemp "$share_dir/omarchy-share.XXXXXX.txt")
chmod 600 "$TEMP_FILE"
wl-paste >"$TEMP_FILE"
FILE_ARRAY=("$TEMP_FILE")
elif (($# > 0)); then
Expand All @@ -41,10 +52,11 @@ else
readarray -t FILE_ARRAY <<<"$picked"
fi

# Run LocalSend in its own systemd service (detached from terminal)
systemd-run --user --quiet --collect localsend --headless send "${FILE_ARRAY[@]}"

# Note: Temporary file will remain until system cleanup for clipboard mode
# This ensures the file content is available for the LocalSend GUI
if [[ $MODE == "clipboard" ]]; then
# Wait so LocalSend can read the private temp before EXIT removes it.
systemd-run --user --quiet --collect --wait localsend --headless send "${FILE_ARRAY[@]}"
else
systemd-run --user --quiet --collect localsend --headless send "${FILE_ARRAY[@]}"
fi

exit 0
9 changes: 5 additions & 4 deletions bin/omarchy-reminder
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ open_interactive() {

show_reminders() {
local timer next remaining reminder reminder_minutes body=""
local reminder_dir="${XDG_RUNTIME_DIR:-/tmp}/omarchy-reminders"
local reminder_dir="${XDG_RUNTIME_DIR:-$HOME/.local/state}/omarchy-reminders"
local reminder_message=""
local now=$(date +%s)

Expand Down Expand Up @@ -72,7 +72,7 @@ show_reminders() {

show_json() {
local timer next remaining reminder reminder_minutes unit reminder_message label item_json reminders_json="[]"
local reminder_dir="${XDG_RUNTIME_DIR:-/tmp}/omarchy-reminders"
local reminder_dir="${XDG_RUNTIME_DIR:-$HOME/.local/state}/omarchy-reminders"
local now=$(date +%s)
local count=0
local tooltip="Set Reminder"
Expand Down Expand Up @@ -119,7 +119,7 @@ show_json() {

clear_reminders() {
local units
local reminder_dir="${XDG_RUNTIME_DIR:-/tmp}/omarchy-reminders"
local reminder_dir="${XDG_RUNTIME_DIR:-$HOME/.local/state}/omarchy-reminders"

units=$(systemctl --user list-timers --all --no-legend --no-pager "omarchy-reminder-*.timer" 2>/dev/null | awk '{ print $(NF - 1), $NF }')

Expand Down Expand Up @@ -182,12 +182,13 @@ fi
set_at=$(date +%s)
remind_at=$(date -d "+${minutes} minutes" +%H:%M)
unit="omarchy-reminder-${minutes}m-$set_at"
reminder_dir="${XDG_RUNTIME_DIR:-/tmp}/omarchy-reminders"
reminder_dir="${XDG_RUNTIME_DIR:-$HOME/.local/state}/omarchy-reminders"
message_file="$reminder_dir/$unit.message"
confirmation="You'll be reminded at $remind_at"
confirmation_title="Reminder set for ${minutes} minutes"

mkdir -p "$reminder_dir"
chmod 700 "$reminder_dir"

if [[ -n $custom_message ]]; then
printf "%s" "$custom_message" >"$message_file"
Expand Down
11 changes: 9 additions & 2 deletions bin/omarchy-system-lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ hyprctl switchxkblayout all 0 > /dev/null 2>&1

# Ensure 1password is locked. Use timeout because `1password --lock` can
# otherwise leave a full Electron helper tree running after each lock.
# Keep the flock out of world-writable /tmp: a held lock there used to make
# `flock -n || exit 0` skip `--lock`. If the private lock file cannot be
# created, still lock.
if pgrep -x "1password" >/dev/null && omarchy-cmd-present 1password; then
(
flock -n 9 || exit 0
lock_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
lock_file="$lock_dir/omarchy-1password-lock.lock"
if mkdir -m 700 -p "$lock_dir" && exec 9>"$lock_file"; then
flock -n 9 || exit 0
fi
timeout --kill-after=1s 3s 1password --lock >/dev/null 2>&1 || true
) 9>"${XDG_RUNTIME_DIR:-/tmp}/omarchy-1password-lock.lock" &
) &
fi

# Avoid running screensaver when locked
Expand Down
4 changes: 3 additions & 1 deletion bin/omarchy-theme-set
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ NEXT_THEME_PATH="$HOME/.local/state/omarchy/current/next-theme"
CURRENT_BACKGROUND_LINK="$HOME/.local/state/omarchy/current/background"
THEME_BACKGROUND_STATE_PATH="$HOME/.local/state/omarchy/theme-backgrounds"
BACKGROUND_TRANSITION_CACHE="$HOME/.cache/omarchy/background-transitions"
THEME_SET_LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-theme-set.lock"
THEME_SET_LOCK_DIR="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$THEME_SET_LOCK_DIR"
THEME_SET_LOCK="$THEME_SET_LOCK_DIR/omarchy-theme-set.lock"
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"

Expand Down
23 changes: 22 additions & 1 deletion bin/omarchy-update
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,30 @@ cleanup_update() {
omarchy_security_exit_with_revoked_sudo "$status"
}

# Transcript must not land on a world-writable predictable path. A local user
# who pre-creates /tmp/omarchy-update.log as a symlink can redirect script(1)
# into ~/.bashrc or ~/.ssh/authorized_keys. Prefer the private runtime dir;
# fall back to a 0700 cache directory under $HOME when XDG_RUNTIME_DIR is unset.
omarchy_update_log_path() {
local dir
if [[ -n ${XDG_RUNTIME_DIR:-} && -d $XDG_RUNTIME_DIR && ! -L $XDG_RUNTIME_DIR ]]; then
dir="$XDG_RUNTIME_DIR/omarchy-update"
else
dir="${HOME}/.cache/omarchy/update"
fi
mkdir -p -m 700 "$dir"
printf '%s' "$dir/update.log"
}

if [[ -z ${OMARCHY_UPDATE_LOGGED:-} ]]; then
script_command=$(printf '%q ' "$0" "$@")
exec env OMARCHY_UPDATE_LOGGED=1 OMARCHY_UPDATE_USER_PATH="$user_path" script -qefc "$script_command" "/tmp/omarchy-update.log"
update_log=$(omarchy_update_log_path)
# Refuse to follow a planted symlink at the log path.
if [[ -L $update_log ]]; then
rm -f "$update_log"
fi
exec env OMARCHY_UPDATE_LOGGED=1 OMARCHY_UPDATE_USER_PATH="$user_path" OMARCHY_UPDATE_LOG="$update_log" \
script -qefc "$script_command" "$update_log"
fi

if ! omarchy-update-lock held; then
Expand Down
20 changes: 19 additions & 1 deletion bin/omarchy-update-analyze-logs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,25 @@

# omarchy:summary=Check the update log for known failure conditions

update_log="/tmp/omarchy-update.log"
set -euo pipefail

omarchy_update_log_path() {
local dir
if [[ -n ${XDG_RUNTIME_DIR:-} && -d $XDG_RUNTIME_DIR && ! -L $XDG_RUNTIME_DIR ]]; then
dir="$XDG_RUNTIME_DIR/omarchy-update"
else
dir="${HOME}/.cache/omarchy/update"
fi
printf '%s' "$dir/update.log"
}

# Prefer the path the current update exported; otherwise resolve the same
# private location omarchy-update uses for new transcripts.
update_log="${OMARCHY_UPDATE_LOG:-$(omarchy_update_log_path)}"

if [[ ! -f $update_log || -L $update_log ]]; then
exit 0
fi

# Check for initramfs generation failure
if grep -q "Updating linux initcpios" "$update_log"; then
Expand Down
5 changes: 4 additions & 1 deletion bin/omarchy-update-lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

set -e

lock_dir="${XDG_RUNTIME_DIR:-/tmp}"
# Prefer the private runtime dir; never fall back to shared /tmp where
# another user could pre-create the lock path.
lock_dir="${XDG_RUNTIME_DIR:-$HOME/.local/state/omarchy}"
lock_path="$lock_dir/omarchy-update.lock"

lock_is_held() {
Expand All @@ -31,6 +33,7 @@ case "${1:-}" in
fi

mkdir -p "$lock_dir" 2>/dev/null || true
chmod 700 "$lock_dir" 2>/dev/null || true
exec {OMARCHY_UPDATE_LOCK_FD}>"$lock_path"
if ! flock -n "$OMARCHY_UPDATE_LOCK_FD"; then
echo "An Omarchy update is already running."
Expand Down
4 changes: 3 additions & 1 deletion bin/omarchy-update-orphan-pkgs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ echo -e "\e[32m\nOrphan system packages\e[0m"
printf ' %s\n' "${orphans[@]}"
echo

if [[ ! -t 0 || ! -t 1 ]]; then
# omarchy update -y keeps a TTY but promises not to ask. Treat unattended
# the same as a non-interactive pipe: report and move on.
if [[ ${OMARCHY_UPDATE_UNATTENDED:-} == 1 || ! -t 0 || ! -t 1 ]]; then
echo "${#orphans[@]} orphaned package(s) found. Re-run omarchy-update-orphan-pkgs in a terminal to review/remove them."
echo
exit 0
Expand Down
Loading