Compare commits

...
Author SHA1 Message Date
David Heinemeier Hansson 4b4219727f Fix migration for rounded corners too 2026-05-15 18:31:36 +02:00
David Heinemeier Hansson b5671cb0cc Fix-up round colors for lua 2026-05-15 18:10:04 +02:00
David Heinemeier Hansson 860c0ab0d8 Merge branch 'dev' into quickshell-omarchy-menu 2026-05-15 18:06:12 +02:00
David Heinemeier Hansson 3d3c77f53d Fix the gum coloring 2026-05-15 18:03:21 +02:00
David Heinemeier Hansson 05fee802fc Don't remove wtype 2026-05-15 17:58:31 +02:00
David Heinemeier Hansson 0bfb545033 Ensure the service is fully removed
Closes #5788
2026-05-15 17:57:44 +02:00
David Heinemeier HanssonandGitHub c0275ea9f2 Foot as the default terminal (#5831)
* Bind maps too

* Make foot the default terminal
2026-05-15 17:44:09 +02:00
David Heinemeier Hansson e72b8a6dbd Skip the certificate errors 2026-05-15 17:39:32 +02:00
David Heinemeier Hansson 612dead716 Make sure we setup autostart as well 2026-05-15 17:03:39 +02:00
David Heinemeier Hansson 2d5e3cefe0 Install Sunshine Admin app as well 2026-05-15 16:59:52 +02:00
David Heinemeier Hansson b486a43985 Add sunshine service installation 2026-05-15 16:24:21 +02:00
David Heinemeier Hansson e2938ae952 Performance improvements 2026-05-15 16:24:21 +02:00
David Heinemeier Hansson 43134875b5 Ensure that $BROWSER runs omarchy-launch-browser and doesn't hand ownership to parent process
This prevents gh auth login from working without an existing open
browser
2026-05-15 16:07:35 +02:00
David Heinemeier Hansson daf301c416 Don't ask to restart multiple times 2026-05-15 15:21:03 +02:00
David Heinemeier Hansson a4635f7657 Make o available without error 2026-05-15 14:44:50 +02:00
David Heinemeier Hansson 4146600f5c Refresh the theme 2026-05-15 14:18:57 +02:00
David Heinemeier Hansson 51d998bee0 Need exclusive placement 2026-05-15 14:14:16 +02:00
David Heinemeier Hansson 95b0bfed4d Ensure that the old style is always run 2026-05-15 14:12:12 +02:00
David Heinemeier Hansson 7e99e3eff0 Ensure toggles are refreshed when doing omarcy-refresh-hyprland 2026-05-15 14:02:12 +02:00
David Heinemeier Hansson 47cd93143a Explain reasoning 2026-05-15 13:57:01 +02:00
David Heinemeier Hansson 8d107ed04c Drop outdated migrations 2026-05-15 13:56:15 +02:00
David Heinemeier Hansson 719b7df91a No longer has its own flags 2026-05-15 13:55:45 +02:00
David Heinemeier Hansson 870fe16b0a Add Alt+esc to close a pane too 2026-05-15 13:39:17 +02:00
David Heinemeier Hansson 2f56b525c6 Simpler additional tmux splits 2026-05-15 13:37:53 +02:00
David Heinemeier Hansson 883c6a6267 Bind maps too 2026-05-15 11:13:20 +02:00
Brosseau ValentinandGitHub 39eb3df863 Remove suspend-then-hibernate cleanup steps (#5829)
Those files are not present anymore (removed here e4b7372666)

Removed suspend-then-hibernate configuration cleanup steps from the script.
2026-05-15 11:03:21 +02:00
Ryan Hughes 9b4a411e5b Pin omarchy-reinstall-git to master branch
GitHub's default branch on basecamp/omarchy is no longer master, so
a plain clone pulls the development branch. Pass --branch master so
reinstalls always land on stable regardless of repo default.
2026-05-14 13:52:46 -04:00
David Heinemeier Hansson e916491c9f More helpers to cleanup configs 2026-05-14 13:15:03 +02:00
David Heinemeier Hansson a4e4b4b1ed Extract launch_sole 2026-05-14 12:58:39 +02:00
David Heinemeier Hansson 8f237f1858 Slim 2026-05-14 12:55:34 +02:00
David Heinemeier Hansson 596638aa73 Don't need the drop shadow 2026-05-14 12:52:45 +02:00
David Heinemeier Hansson 84de3d3a2e Extract more helpers 2026-05-14 12:51:03 +02:00
David Heinemeier Hansson 6840242c44 Fix indention 2026-05-14 12:37:53 +02:00
9d7474095f Keep brightness OSD popup width uniform across all percentages (#5806)
Pad the percent text to 3 chars with printf so "  5%", " 50%", and
"100%" render at identical width in the JetBrainsMono monospace label.
Previously the popup container resized between events because the
label string varied between 2 and 4 characters, which caused the
popup to visibly jump in width on consecutive brightness key presses.

Builds on #5525, which made the percent values themselves step
uniformly; this completes the loop by making the rendered popup match.

Co-authored-by: Mateus Pegorim <14262063+Pegorim@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:35:36 +02:00
David Heinemeier Hansson 7f85ee7d9d Make the selected image bigger 2026-05-14 12:33:51 +02:00
David Heinemeier Hansson 4a11ca7ae9 Loop around 2026-05-14 12:32:19 +02:00
David Heinemeier Hansson 6891c996b5 Add migration for new tmux keybinding 2026-05-14 12:04:09 +02:00
David Heinemeier Hansson 4c48d83952 More helpers 2026-05-14 12:02:53 +02:00
David Heinemeier Hansson 41988fda2a Cleanup 2026-05-14 12:02:53 +02:00
David Heinemeier Hansson 35cf232bcb Extract built-in notifications 2026-05-14 12:02:53 +02:00
Vitor MeloandGitHub e766f0ac28 Add bind M-Enter to open new pane em tmux (#5785) 2026-05-14 11:40:20 +02:00
David Heinemeier Hansson 3e098f6dd5 Next up is 4.0 2026-05-14 11:34:55 +02:00
David Heinemeier Hansson b72eb206cb Extract launch_on_start helper 2026-05-14 11:34:26 +02:00
David Heinemeier Hansson 83c2e2f84c Extract Omarchy's own bootstrap 2026-05-14 11:32:22 +02:00
David Heinemeier Hansson 9e1310106a Too defensive 2026-05-14 11:32:13 +02:00
David Heinemeier Hansson cfc7bc0cda Better naming 2026-05-14 11:21:45 +02:00
David Heinemeier Hansson dca3bfd951 Cleaner selection without exposed filtering 2026-05-14 11:17:33 +02:00
David Heinemeier Hansson 72bd02ca89 Start extracting omarchy helpers for cumbersome lua calls 2026-05-14 11:13:37 +02:00
David Heinemeier Hansson b26cd62334 Extract the nautilus cwd launcher 2026-05-14 11:12:25 +02:00
David Heinemeier Hansson 6ae8dc555e Extract launching the tmux terminal 2026-05-14 10:57:44 +02:00
David Heinemeier Hansson 9e20c4899d Extract terminal launcher with cwd 2026-05-14 10:56:10 +02:00
Ryan HughesandGitHub 6b074c7a17 Merge pull request #5804 from bjarneo/tab-themes-and-backgrounds
Enable tab and shift+tab to navigate back and forth the wallpaper/theme selector
2026-05-14 02:02:56 -04:00
Bjarne Øverli d27c1e8346 Enable tab and shift+tab to navigate back and forth 2026-05-13 17:22:15 +02:00
Ryan Hughes 4ae55d61cd Fix stale Quickshell menu lock handling 2026-05-13 00:42:16 -04:00
Ryan Hughes 3ae0915092 Keep Quickshell menu warm 2026-05-13 00:24:38 -04:00
Ryan Hughes 8387a575aa Prevent stacked Quickshell menus 2026-05-13 00:24:38 -04:00
Ryan Hughes 44915b9a5e Refactor quickshell menu to be faster and simpler to work on 2026-05-13 00:24:38 -04:00
Ryan Hughes c336de6b5b Add Quickshell Omarchy menu 2026-05-13 00:23:47 -04:00
Ryan Hughes 087909714e Add tmux keybindings viewer 2026-05-13 00:20:38 -04:00
Ryan Hughes be55e8048c Prevent modifier keys being stuck on Super + C / V / X 2026-05-12 22:41:27 -04:00
Ryan Hughes d932f47eaf Prevent bg-next from taking non-images 2026-05-12 21:57:57 -04:00
David Heinemeier Hansson 8d5e9e794e Move to pnpm dlx with a 5-day lag to skip the latest zero-day npm package exploits 2026-05-12 23:58:27 +02:00
Ryan Hughes c0e099fed5 Prevent wiping waybar configs to reposition 2026-05-11 20:07:18 -04:00
Ryan Hughes aada2a4c9c Preserve waybar position on refresh 2026-05-11 20:01:18 -04:00
Ryan HughesandGitHub 0601dea910 Merge pull request #5759 from basecamp/skwd-wall
Add QuickShell-based backgrounds selector
2026-05-11 18:38:39 -04:00
Ryan Hughes d54e8b5429 Use theme colors in image selector 2026-05-11 18:10:58 -04:00
Ryan Hughes f14d82b2f3 Start image selector on demand 2026-05-11 18:02:45 -04:00
Ryan Hughes cb87adfc99 Toggle image selector closed when already open 2026-05-11 17:53:40 -04:00
Ryan Hughes 3d8c061a39 Lazy load theme switcher thumbnails 2026-05-11 17:41:30 -04:00
Ryan Hughes 427783c41f Stub theme switcher benchmark 2026-05-11 17:20:46 -04:00
Ryan Hughes f24dd82181 Add filter typing to theme switcher 2026-05-11 17:10:45 -04:00
Ryan Hughes 903f27fdd1 Tighten image selector request handling 2026-05-11 16:50:26 -04:00
Ryan Hughes 0801209090 Keep selector labels readable 2026-05-11 16:07:37 -04:00
Ryan Hughes 314a7f75c0 Keep image selector preview centered 2026-05-11 16:03:31 -04:00
Ryan Hughes 3aaedd88b1 Remove selector width animation jitter 2026-05-11 15:57:59 -04:00
Ryan Hughes ca0ea7af57 Clamp image selector navigation 2026-05-11 15:52:38 -04:00
Ryan Hughes 693a23c58c Open image selector at selected item immediately 2026-05-11 15:47:01 -04:00
Ryan Hughes b89079ae5c Show theme names in theme switcher 2026-05-11 15:40:19 -04:00
David Heinemeier HanssonandRyan Hughes f6bd69bc0f Fix color sync 2026-05-11 15:29:31 -04:00
David Heinemeier HanssonandRyan Hughes ef129b9dab Consistency 2026-05-11 15:29:31 -04:00
David Heinemeier HanssonandRyan Hughes 0426f9b206 Cache warming 2026-05-11 15:29:31 -04:00
David Heinemeier HanssonandRyan Hughes b48f67058b Use consistent terms 2026-05-11 15:29:31 -04:00
David Heinemeier HanssonandRyan Hughes 000b7c79af Improve performance 2026-05-11 15:29:11 -04:00
David Heinemeier HanssonandRyan Hughes 0b2332e45d Permanent process for speed 2026-05-11 15:29:11 -04:00
David Heinemeier HanssonandRyan Hughes 5487c17d19 Single namespace is fine 2026-05-11 15:28:52 -04:00
David Heinemeier HanssonandRyan Hughes 008f0cf7dd Extract generic switcher 2026-05-11 15:28:52 -04:00
David Heinemeier HanssonandRyan Hughes 1e646be7ee We need quickshell available 2026-05-11 15:28:33 -04:00
David Heinemeier HanssonandRyan Hughes aba11e716f Tweaks 2026-05-11 15:28:33 -04:00
David Heinemeier HanssonandRyan Hughes 333ec367df Let's build our own wall 2026-05-11 15:28:33 -04:00
David Heinemeier HanssonandRyan Hughes 7a988d8909 Switch to using the switcher on all the normal keybindings 2026-05-11 15:27:56 -04:00
David Heinemeier HanssonandRyan Hughes 67751a45b5 Correct indention 2026-05-11 15:27:43 -04:00
David Heinemeier HanssonandRyan Hughes da822f6ffb Change from swaybg to skwd-wall
Nicer picker and support for movie bgs
2026-05-11 15:27:43 -04:00
Ryan HughesandGitHub 15658cc622 Merge pull request #5723 from basecamp/hyprland-lua-conversion
Hyprland lua conversion
2026-05-11 15:02:02 -04:00
David Heinemeier Hansson 43ec46f699 Add tds 4-way 2026-05-11 18:21:45 +02:00
141 changed files with 4913 additions and 1557 deletions
+2 -2
View File
@@ -21,7 +21,7 @@ time_remaining=$(omarchy-battery-remaining-time)
capacity=$(omarchy-battery-capacity)
if [[ $state == "charging" ]]; then
echo "󰁹 Battery ${percentage}% · ${time_remaining} to full ·  ${power_rate}W / ${capacity}Wh"
echo "Battery ${percentage}% · ${time_remaining} to full ·  ${power_rate}W / ${capacity}Wh"
else
echo "󰁹 Battery ${percentage}% · ${time_remaining} left ·  ${power_rate}W / ${capacity}Wh"
echo "Battery ${percentage}% · ${time_remaining} left ·  ${power_rate}W / ${capacity}Wh"
fi
+228
View File
@@ -0,0 +1,228 @@
#!/bin/bash
# omarchy:summary=Measure Quickshell Omarchy menu response times
# omarchy:args=[--repeat=<count>] [--no-ui]
# omarchy:examples=omarchy dev benchmark menu | omarchy dev benchmark menu --repeat=10
set -euo pipefail
OMARCHY_BIN_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
OMARCHY_PATH=${OMARCHY_PATH:-$(cd -- "$OMARCHY_BIN_DIR/.." && pwd)}
REPEAT=5
NO_UI=false
show_help() {
cat <<'EOF'
Usage:
omarchy dev benchmark menu [--repeat=<count>] [--no-ui]
Measure the Omarchy menu startup path:
- static JSONC menu parsing
- Quickshell socket startup
- cold open/close roundtrip (unless --no-ui)
- warm open/close roundtrip against the resident Quickshell process
Options:
--repeat=<count> Number of UI open/close runs to measure (default: 5)
--no-ui Skip cases that briefly open the menu
EOF
}
now_us() {
local now="${EPOCHREALTIME/./}"
printf '%s' "$now"
}
format_ms() {
local us="$1"
printf '%d.%03d' "$(( us / 1000 ))" "$(( us % 1000 ))"
}
measure_once() {
local start_us end_us
start_us=$(now_us)
"$@" >/dev/null
end_us=$(now_us)
printf '%s' "$(( end_us - start_us ))"
}
run_case() {
local label="$1"
shift
local total_us=0
local min_us=0
local max_us=0
local elapsed_us=0
for (( i = 1; i <= REPEAT; i++ )); do
elapsed_us=$(measure_once "$@")
total_us=$(( total_us + elapsed_us ))
if (( i == 1 || elapsed_us < min_us )); then
min_us=$elapsed_us
fi
if (( elapsed_us > max_us )); then
max_us=$elapsed_us
fi
done
printf '%-34s avg %8s ms min %8s ms max %8s ms\n' \
"$label" \
"$(format_ms "$(( total_us / REPEAT ))")" \
"$(format_ms "$min_us")" \
"$(format_ms "$max_us")"
}
socket_path() {
printf '%s/omarchy-menu.sock' "${XDG_RUNTIME_DIR:-/run/user/$UID}"
}
menu_qml() {
printf '%s/default/quickshell/menu.qml' "$OMARCHY_PATH"
}
kill_menu_shell() {
quickshell kill -p "$(menu_qml)" >/dev/null 2>&1 || true
for (( i = 0; i < 200; i++ )); do
if ! pgrep -f "[q]uickshell .*$(menu_qml)" >/dev/null 2>&1; then
break
fi
sleep 0.01
done
rm -f "$(socket_path)" "${XDG_RUNTIME_DIR:-/run/user/$UID}/omarchy-menu.state" "${XDG_RUNTIME_DIR:-/run/user/$UID}/omarchy-menu.lock"
}
build_menu_json() {
env OMARCHY_PATH="$OMARCHY_PATH" PATH="$OMARCHY_BIN_DIR:$PATH" \
"$OMARCHY_BIN_DIR/omarchy-menu" --json
}
start_quickshell_socket() {
local menu_file
local selection_file
local done_file
kill_menu_shell
menu_file=$(mktemp)
selection_file=$(mktemp)
done_file=$(mktemp)
printf '{"items":[]}' >"$menu_file"
rm -f "$done_file"
env \
OMARCHY_PATH="$OMARCHY_PATH" \
OMARCHY_MENU_JSON_FILE="$menu_file" \
OMARCHY_MENU_INITIAL_MENU="root" \
OMARCHY_MENU_SELECTION_FILE="$selection_file" \
OMARCHY_MENU_DONE_FILE="$done_file" \
quickshell -n -d -p "$(menu_qml)" >/dev/null
for (( i = 0; i < 200; i++ )); do
[[ -S $(socket_path) ]] && break
sleep 0.01
done
[[ -S $(socket_path) ]]
kill_menu_shell
rm -f "$menu_file" "$selection_file" "$done_file"
}
menu_layer_visible() {
hyprctl layers -j 2>/dev/null | jq -e '.. | objects | select(.namespace? == "omarchy-menu")' >/dev/null
}
open_close_menu() {
local pid
env OMARCHY_PATH="$OMARCHY_PATH" PATH="$OMARCHY_BIN_DIR:$PATH" \
"$OMARCHY_BIN_DIR/omarchy-menu" >/dev/null &
pid=$!
for (( i = 0; i < 300; i++ )); do
if menu_layer_visible && [[ -S $(socket_path) ]]; then
break
fi
sleep 0.01
done
if [[ ! -S $(socket_path) ]]; then
kill "$pid" 2>/dev/null || true
kill_menu_shell
return 1
fi
printf 'close\n' | socat -u - "UNIX-CONNECT:$(socket_path)" >/dev/null 2>&1 || true
for (( i = 0; i < 500; i++ )); do
if ! kill -0 "$pid" 2>/dev/null; then
break
fi
sleep 0.01
done
if kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
kill_menu_shell
return 1
fi
wait "$pid" || true
}
cold_open_close_menu() {
kill_menu_shell
open_close_menu
kill_menu_shell
}
warm_open_close_menu() {
open_close_menu
}
while (( $# > 0 )); do
case "$1" in
--repeat=*) REPEAT="${1#*=}" ;;
--no-ui) NO_UI=true ;;
--help | -h)
show_help
exit 0
;;
*)
echo "Unknown option: $1" >&2
show_help >&2
exit 2
;;
esac
shift
done
if [[ ! $REPEAT =~ ^[0-9]+$ ]] || (( REPEAT < 1 )); then
echo "--repeat must be a positive integer" >&2
exit 2
fi
cleanup() {
kill_menu_shell
}
trap cleanup EXIT
run_label="runs"
(( REPEAT == 1 )) && run_label="run"
printf 'Omarchy menu benchmark (%d %s each)\n\n' "$REPEAT" "$run_label"
run_case "menu JSON build" build_menu_json
if [[ $NO_UI != true ]]; then
if omarchy-cmd-present quickshell socat hyprctl jq && [[ -n ${WAYLAND_DISPLAY:-} ]]; then
printf '%-34s %s ms\n' "quickshell socket startup" "$(format_ms "$(measure_once start_quickshell_socket)")"
run_case "cold open/close" cold_open_close_menu
kill_menu_shell
open_close_menu >/dev/null
run_case "warm open/close" warm_open_close_menu
else
printf 'Skipping UI cases: quickshell/socat/hyprctl/jq/Wayland unavailable\n'
fi
fi
+163
View File
@@ -0,0 +1,163 @@
#!/bin/bash
# omarchy:summary=Measure theme switcher cache and selector prep times
# omarchy:args=[--repeat=<count>] [--keep-cache]
# omarchy:examples=omarchy dev benchmark theme switcher | omarchy dev benchmark theme-switcher --repeat=10
# omarchy:aliases=omarchy dev benchmark theme-switcher
set -euo pipefail
OMARCHY_BIN_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
OMARCHY_PATH=${OMARCHY_PATH:-$(cd -- "$OMARCHY_BIN_DIR/.." && pwd)}
REPEAT=5
KEEP_CACHE=false
show_help() {
cat <<'EOF'
Usage:
omarchy dev benchmark theme switcher [--repeat=<count>] [--keep-cache]
Measure the non-interactive parts of the theme switcher:
- theme preview index build (omarchy-theme-switcher before UI handoff)
- lazy selector row prep used by the interactive theme switcher
- full thumbnail cache warmup cost (omarchy-menu-images --cache-only)
Options:
--repeat=<count> Number of warm runs to measure for each case (default: 5)
--keep-cache Keep the temporary benchmark cache and print its path
EOF
}
now_us() {
local now="${EPOCHREALTIME/./}"
printf '%s' "$now"
}
format_ms() {
local us="$1"
printf '%d.%03d' "$(( us / 1000 ))" "$(( us % 1000 ))"
}
measure_once() {
local start_us end_us
start_us=$(now_us)
"$@" >/dev/null
end_us=$(now_us)
printf '%s' "$(( end_us - start_us ))"
}
run_case() {
local label="$1"
shift
local total_us=0
local min_us=0
local max_us=0
local elapsed_us=0
for (( i = 1; i <= REPEAT; i++ )); do
elapsed_us=$(measure_once "$@")
total_us=$(( total_us + elapsed_us ))
if (( i == 1 || elapsed_us < min_us )); then
min_us=$elapsed_us
fi
if (( elapsed_us > max_us )); then
max_us=$elapsed_us
fi
done
printf '%-34s avg %8s ms min %8s ms max %8s ms\n' \
"$label" \
"$(format_ms "$(( total_us / REPEAT ))")" \
"$(format_ms "$min_us")" \
"$(format_ms "$max_us")"
}
while (( $# > 0 )); do
case "$1" in
--repeat=*)
REPEAT="${1#*=}"
;;
--keep-cache)
KEEP_CACHE=true
;;
--help | -h)
show_help
exit 0
;;
*)
echo "Unknown option: $1" >&2
show_help >&2
exit 2
;;
esac
shift
done
if [[ ! $REPEAT =~ ^[0-9]+$ ]] || (( REPEAT < 1 )); then
echo "--repeat must be a positive integer" >&2
exit 2
fi
benchmark_cache=$(mktemp -d)
thumbnail_cache=$(mktemp -d)
stub_bin=$(mktemp -d)
cleanup() {
rm -rf "$stub_bin"
if [[ $KEEP_CACHE == "true" ]]; then
printf 'Benchmark cache: %s\n' "$benchmark_cache"
printf 'Thumbnail cache: %s\n' "$thumbnail_cache"
else
rm -rf "$benchmark_cache" "$thumbnail_cache"
fi
}
trap cleanup EXIT
cat >"$stub_bin/omarchy-menu-images" <<'EOF'
#!/bin/bash
exit 0
EOF
chmod +x "$stub_bin/omarchy-menu-images"
benchmark_env=(
env
"OMARCHY_PATH=$OMARCHY_PATH"
"XDG_CACHE_HOME=$benchmark_cache"
"PATH=$stub_bin:$OMARCHY_BIN_DIR:$PATH"
)
thumbnail_env=(
env
"OMARCHY_PATH=$OMARCHY_PATH"
"XDG_CACHE_HOME=$thumbnail_cache"
"PATH=$stub_bin:$OMARCHY_BIN_DIR:$PATH"
)
preview_dir="$benchmark_cache/omarchy/theme-selector/previews"
thumbnail_preview_dir="$thumbnail_cache/omarchy/theme-selector/previews"
build_theme_index() {
"${benchmark_env[@]}" "$OMARCHY_BIN_DIR/omarchy-theme-switcher"
}
prepare_selector_lazy() {
"${benchmark_env[@]}" "$OMARCHY_BIN_DIR/omarchy-menu-images" --prepare-only --lazy-thumbnails --show-labels --filterable "$preview_dir"
}
prepare_image_cache() {
"${thumbnail_env[@]}" "$OMARCHY_BIN_DIR/omarchy-menu-images" --cache-only "$thumbnail_preview_dir"
}
printf 'Theme switcher benchmark (%d warm runs each)\n\n' "$REPEAT"
printf '%-34s %s ms\n' "theme index cold" "$(format_ms "$(measure_once build_theme_index)")"
run_case "theme index warm" build_theme_index
printf '%-34s %s ms\n' "selector prep cold (lazy)" "$(format_ms "$(measure_once prepare_selector_lazy)")"
run_case "selector prep warm (lazy)" prepare_selector_lazy
"${thumbnail_env[@]}" "$OMARCHY_BIN_DIR/omarchy-theme-switcher" >/dev/null
printf '%-34s %s ms\n' "thumbnail cache cold" "$(format_ms "$(measure_once prepare_image_cache)")"
run_case "thumbnail cache warm" prepare_image_cache
printf '\nTheme previews: %d\n' "$(find -L "$preview_dir" -maxdepth 1 -type f 2>/dev/null | wc -l)"
-5
View File
@@ -44,11 +44,6 @@ if grep -Fq "$SWAP_FILE" /etc/fstab; then
sudo sed -i '/^# Btrfs swapfile for system hibernation$/d' /etc/fstab
fi
# Remove suspend-then-hibernate configuration
echo "Removing suspend-then-hibernate configuration"
sudo rm -f /etc/systemd/logind.conf.d/lid.conf
sudo rm -f /etc/systemd/sleep.conf.d/hibernate.conf
# Remove mkinitcpio resume hook
echo "Removing resume hook"
sudo rm "$MKINITCPIO_CONF"
+92
View File
@@ -0,0 +1,92 @@
#!/bin/bash
# omarchy:summary=Install Sunshine and open Moonlight streaming ports for LAN and Tailscale.
# omarchy:requires-sudo=true
set -e
TCP_PORTS=(47984 47989 48010)
UDP_PORTS=(5353 47998 47999 48000 48002 48010)
PRIVATE_CIDRS=(10.0.0.0/8 172.16.0.0/12 192.168.0.0/16)
UFW_COMMENT="omarchy-sunshine"
SUNSHINE_ADMIN_APP="Sunshine Admin"
SUNSHINE_ADMIN_URL="https://localhost:47990"
SUNSHINE_ADMIN_EXEC="omarchy-launch-webapp $SUNSHINE_ADMIN_URL --ignore-certificate-errors"
SUNSHINE_ICON_SOURCE="/usr/share/sunshine/web/images/logo-sunshine-45.png"
SUNSHINE_ICON_NAME="Sunshine Admin.png"
WEBAPP_ICON_DIR="$HOME/.local/share/applications/icons"
HYPR_AUTOSTART_FILE="$HOME/.config/hypr/autostart.lua"
HYPR_AUTOSTART_ENTRY='o.launch_on_start("sunshine")'
open_ufw_port_for_private_lans() {
local proto="$1"
local port="$2"
local cidr
for cidr in "${PRIVATE_CIDRS[@]}"; do
sudo ufw allow in proto "$proto" from "$cidr" to any port "$port" comment "$UFW_COMMENT"
done
}
open_ufw_port_for_tailscale() {
local proto="$1"
local port="$2"
if ip link show tailscale0 >/dev/null 2>&1; then
sudo ufw allow in on tailscale0 to any port "$port" proto "$proto" comment "$UFW_COMMENT"
fi
}
open_ufw_ports() {
local port
if omarchy-cmd-missing ufw; then
echo "UFW is not installed; skipping Sunshine firewall rules."
return
fi
for port in "${TCP_PORTS[@]}"; do
open_ufw_port_for_private_lans tcp "$port"
open_ufw_port_for_tailscale tcp "$port"
done
for port in "${UDP_PORTS[@]}"; do
open_ufw_port_for_private_lans udp "$port"
open_ufw_port_for_tailscale udp "$port"
done
sudo ufw reload
}
install_admin_webapp() {
mkdir -p "$WEBAPP_ICON_DIR"
cp "$SUNSHINE_ICON_SOURCE" "$WEBAPP_ICON_DIR/$SUNSHINE_ICON_NAME"
omarchy-webapp-install "$SUNSHINE_ADMIN_APP" "$SUNSHINE_ADMIN_URL" "$SUNSHINE_ICON_NAME" "$SUNSHINE_ADMIN_EXEC"
omarchy-restart-walker
}
enable_hyprland_autostart() {
mkdir -p "$(dirname "$HYPR_AUTOSTART_FILE")"
touch "$HYPR_AUTOSTART_FILE"
if ! grep -Fxq "$HYPR_AUTOSTART_ENTRY" "$HYPR_AUTOSTART_FILE"; then
printf '\n%s\n' "$HYPR_AUTOSTART_ENTRY" >>"$HYPR_AUTOSTART_FILE"
fi
}
echo "Installing Sunshine..."
omarchy-pkg-add sunshine
systemctl --user enable --now sunshine
echo "Opening Sunshine firewall ports..."
open_ufw_ports
echo "Installing Sunshine admin web app..."
install_admin_webapp
$SUNSHINE_ADMIN_EXEC >/dev/null 2>&1 &
echo "Enabling Sunshine autostart..."
enable_hyprland_autostart
echo ""
echo "Sunshine has been installed and its Moonlight streaming ports are open for private LANs and Tailscale."
+2 -2
View File
@@ -30,10 +30,10 @@ if omarchy-pkg-add $package; then
# Copy custom desktop entries with X-TerminalArg* keys
if [[ $package == "alacritty" ]]; then
mkdir -p ~/.local/share/applications
cp "$OMARCHY_PATH/applications/$desktop_id" ~/.local/share/applications/
cp "$OMARCHY_PATH/default/alacritty/$desktop_id" ~/.local/share/applications/
elif [[ $package == "foot" ]]; then
mkdir -p ~/.local/share/applications
cp "$OMARCHY_PATH/default/foot/$desktop_id" ~/.local/share/applications/
cp "$OMARCHY_PATH/applications/$desktop_id" ~/.local/share/applications/
fi
# Copy default config for optional terminals when missing
+4 -2
View File
@@ -6,7 +6,7 @@
default_browser=$(xdg-settings get default-web-browser)
browser_exec=$(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$default_browser 2>/dev/null | head -1)
if $browser_exec --help | grep -q MOZ_LOG; then
if $browser_exec --help 2>/dev/null | grep -q MOZ_LOG; then
private_flag="--private-window"
elif [[ $browser_exec =~ edge ]]; then
private_flag="--inprivate"
@@ -14,4 +14,6 @@ else
private_flag="--incognito"
fi
exec setsid uwsm-app -- "$browser_exec" "${@/--private/$private_flag}"
systemd-run --user --quiet --collect --unit="omarchy-browser-$(date +%s%N)" \
--property=StandardOutput=null --property=StandardError=null \
uwsm-app -- "$browser_exec" "${@/--private/$private_flag}"
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# omarchy:summary=Launch Files
exec setsid uwsm-app -- nautilus --new-window
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# omarchy:summary=Launch Files in the active terminal's current directory
exec setsid uwsm-app -- nautilus --new-window "$(omarchy-cmd-terminal-cwd)"
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
# omarchy:summary=Launch a terminal in the active terminal's current directory
# omarchy:args=[command...]
exec setsid uwsm-app -- xdg-terminal-exec --dir="$(omarchy-cmd-terminal-cwd)" "$@"
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# omarchy:summary=Launch or attach to the Work tmux session in a terminal
exec omarchy-launch-terminal bash -c "tmux attach || tmux new -s Work"
+933 -824
View File
File diff suppressed because it is too large Load Diff
+285
View File
@@ -0,0 +1,285 @@
#!/bin/bash
# omarchy:summary=Open a generic image selector menu
# omarchy:args=[--selected <image>] [--colors-file <path>] [--print-name] [--show-labels] [--filterable] [--lazy-thumbnails] [--cache-only] <image-dir>...
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
selected_image=""
colors_file=""
print_name=false
show_labels=false
filterable=false
lazy_thumbnails=false
prepare_only=false
cache_only=false
image_dirs=()
usage() {
echo "Usage: omarchy-menu-images [--selected <image>] [--colors-file <path>] [--print-name] [--show-labels] [--filterable] [--lazy-thumbnails] [--cache-only] <image-dir>..."
}
while [[ $# -gt 0 ]]; do
case "$1" in
--selected)
if (( $# < 2 )); then
usage >&2
exit 1
fi
selected_image="$2"
shift 2
;;
--colors-file)
if (( $# < 2 )); then
usage >&2
exit 1
fi
colors_file="$2"
shift 2
;;
--print-name)
print_name=true
shift
;;
--show-labels)
show_labels=true
shift
;;
--filterable)
filterable=true
shift
;;
--lazy-thumbnails)
lazy_thumbnails=true
shift
;;
--prepare-only)
prepare_only=true
shift
;;
--cache-only)
cache_only=true
shift
;;
--help|-h)
usage
exit 0
;;
*)
image_dirs+=("$1")
shift
;;
esac
done
if (( ${#image_dirs[@]} == 0 )); then
usage >&2
exit 1
fi
selection_file=$(mktemp)
done_file=$(mktemp)
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file"' EXIT
socket_path="${XDG_RUNTIME_DIR:-/run/user/$UID}/omarchy-image-selector.sock"
selector_qml="$OMARCHY_PATH/default/quickshell/select-by-image.qml"
image_dirs_env=""
for dir in "${image_dirs[@]}"; do
if [[ -z $image_dirs_env ]]; then
image_dirs_env="$dir"
else
image_dirs_env+=$'\n'"$dir"
fi
done
current_image=$(readlink -f "$selected_image" 2>/dev/null)
selected_list_image=""
if [[ -n $current_image ]]; then
for dir in "${image_dirs[@]}"; do
if [[ -d $dir && -f $selected_image && ${selected_image%/*} == "$dir" ]]; then
selected_list_image="$selected_image"
break
elif [[ -d $dir ]]; then
selected_list_image=$(find -L "$dir" -maxdepth 1 -type f -samefile "$current_image" -print -quit 2>/dev/null)
[[ -n $selected_list_image ]] && break
fi
done
fi
cache_dir=${XDG_CACHE_HOME:-$HOME/.cache}/omarchy/image-selector
index_file="$cache_dir/index.tsv"
rows=""
mkdir -p "$cache_dir"
cache_key=$(printf '%s' "$image_dirs_env" | md5sum | cut -d ' ' -f 1)
rows_cache_file="$cache_dir/$cache_key.rows"
rows_signature_file="$cache_dir/$cache_key.signature"
rows_signature="v2"$'\n'
rows_cacheable=true
image_files=()
for dir in "${image_dirs[@]}"; do
if [[ -d $dir ]]; then
rows_signature+="$dir:$(stat -Lc '%Y' "$dir")"$'\n'
while IFS= read -r -d '' image; do
image_files+=("$image")
image_signature=$(stat -Lc '%s:%Y' "$image") || continue
rows_signature+="$image:$image_signature"$'\n'
done < <(find -L "$dir" -maxdepth 1 -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \) -print0 2>/dev/null | sort -z)
fi
done
generate_thumbnail() {
local image="$1"
local thumbnail="$2"
local lock="$thumbnail.lock"
local tmp="$thumbnail.$$.jpg"
if mkdir "$lock" 2>/dev/null; then
if magick "${image}[0]" -auto-orient -resize '1536x864^' -gravity center -extent '1536x864' -strip -quality 82 "$tmp"; then
mv -f "$tmp" "$thumbnail"
else
rm -f "$tmp" "$thumbnail"
fi
rmdir "$lock" 2>/dev/null || true
else
for ((i = 0; i < 3000; i++)); do
[[ -f $thumbnail ]] && return
[[ -d $lock ]] || break
sleep 0.01
done
fi
}
thumbnail_for() {
local image="$1"
local signature hash thumbnail
signature=$(stat -Lc '%s:%Y' "$image") || return
hash=$(awk -F '\t' -v path="$image" -v sig="$signature" '$1 == path && $2 == sig { print $3; exit }' "$index_file" 2>/dev/null)
if [[ -z $hash ]]; then
hash=$(printf '%s\t%s' "$image" "$signature" | md5sum | cut -d ' ' -f 1)
printf '%s\t%s\t%s\n' "$image" "$signature" "$hash" >>"$index_file"
fi
thumbnail="$cache_dir/$hash.jpg"
if [[ ! -f $thumbnail ]]; then
if [[ $lazy_thumbnails == true && $cache_only != true ]]; then
rows_cacheable=false
if [[ $prepare_only != true ]]; then
generate_thumbnail "$image" "$thumbnail" >/dev/null 2>&1 &
fi
printf '%s' "$image"
return
fi
generate_thumbnail "$image" "$thumbnail"
fi
[[ -f $thumbnail ]] && printf '%s' "$thumbnail"
}
if [[ -f $rows_cache_file && -f $rows_signature_file ]] && cmp -s "$rows_signature_file" <(printf '%s' "$rows_signature"); then
rows=$(<"$rows_cache_file")
else
for image in "${image_files[@]}"; do
thumbnail=$(thumbnail_for "$image")
[[ -n $thumbnail ]] || continue
if [[ $lazy_thumbnails == true && $cache_only != true && $thumbnail == "$image" ]]; then
rows_cacheable=false
fi
if [[ -z $rows ]]; then
rows="$image"$'\t'"$thumbnail"
else
rows+=$'\n'"$image"$'\t'"$thumbnail"
fi
done
if [[ $rows_cacheable == true ]]; then
printf '%s' "$rows" >"$rows_cache_file"
printf '%s' "$rows_signature" >"$rows_signature_file"
else
rm -f "$rows_cache_file" "$rows_signature_file"
fi
fi
rows_payload=${rows//$'\t'/$'\f'}
rows_payload=${rows_payload//$'\n'/$'\v'}
colors_file=${colors_file:-$HOME/.config/omarchy/current/theme/quickshell.json}
colors_payload=""
if [[ -f $colors_file ]]; then
colors_payload=$(<"$colors_file")
colors_payload=${colors_payload//$'\t'/$'\f'}
colors_payload=${colors_payload//$'\n'/$'\v'}
fi
if [[ $cache_only == true || $prepare_only == true ]]; then
exit 0
fi
ensure_selector() {
if [[ -S $socket_path && $selector_qml -nt $socket_path ]]; then
quickshell kill -p "$selector_qml" >/dev/null 2>&1 || true
rm -f "$socket_path"
fi
if [[ ! -S $socket_path ]]; then
quickshell kill -p "$selector_qml" >/dev/null 2>&1 || true
quickshell -d -p "$selector_qml" >/dev/null
for ((i = 0; i < 100; i++)); do
if [[ -S $socket_path ]]; then
break
fi
sleep 0.01
done
fi
[[ -S $socket_path ]]
}
send_request() {
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$rows_payload" "$selected_list_image" "$selection_file" "$done_file" "$colors_payload" "$show_labels" "$filterable" |
socat -u - "UNIX-CONNECT:$socket_path"
}
if ! ensure_selector; then
echo "Image selector failed to start" >&2
exit 1
fi
if ! send_request; then
rm -f "$socket_path"
if ! ensure_selector || ! send_request; then
echo "Image selector failed to accept request" >&2
exit 1
fi
fi
while [[ ! -e $done_file ]]; do
sleep 0.01
done
if [[ -s $selection_file ]]; then
if [[ $print_name == true ]]; then
selection=$(<"$selection_file")
selection=${selection##*/}
printf '%s\n' "${selection%.*}"
else
cat "$selection_file"
fi
fi
+1 -1
View File
@@ -187,7 +187,7 @@ hl = setmetatable({
end,
})
local config = (os.getenv("HOME") or "") .. "/.config/hypr/hyprland.lua"
local config = os.getenv("HOME") .. "/.config/hypr/hyprland.lua"
local file = io.open(config, "r")
if file then
+248
View File
@@ -0,0 +1,248 @@
#!/bin/bash
# omarchy:summary=Display Tmux keybindings defined in your configuration using walker for an interactive search menu.
# omarchy:args=[--print|-p] [--config <path>]
print_only=false
config_file="${TMUX_CONF:-$HOME/.config/tmux/tmux.conf}"
while (($#)); do
case "$1" in
--print|-p)
print_only=true
;;
--config)
shift
config_file="$1"
;;
*)
config_file="$1"
;;
esac
shift
done
if [[ ! -f $config_file ]]; then
default_config="${OMARCHY_PATH:-$HOME/.local/share/omarchy}/config/tmux/tmux.conf"
if [[ -f $default_config ]]; then
config_file="$default_config"
else
echo "Tmux config not found: $config_file" >&2
exit 1
fi
fi
output_keybindings() {
awk '
function trim(value) {
gsub(/^[ \t]+|[ \t]+$/, "", value)
return value
}
function key_part_text(part, is_modifier, part_count) {
gsub(/^\\/, "", part)
if (is_modifier && part == "C") return "CTRL"
if (is_modifier && part == "M") return "ALT"
if (is_modifier && part == "S") return "SHIFT"
if (part == "Space") return "SPACE"
if (part == "BSpace") return "BACKSPACE"
if (part == "BTab") return "SHIFT + TAB"
if (part == "PPage") return "PAGE UP"
if (part == "NPage") return "PAGE DOWN"
if (part == "DC") return "DELETE"
if (part == "IC") return "INSERT"
if (part_count == 1 && part ~ /^[a-z]$/) return part
return toupper(part)
}
function key_text(key, parts, count, i, part, text) {
gsub(/\\/, "", key)
count = split(key, parts, "-")
text = ""
for (i = 1; i <= count; i++) {
part = key_part_text(parts[i], i < count, count)
text = text (text == "" ? "" : " + ") part
}
return text
}
function table_text(table) {
if (table == "copy-mode-vi") return "COPY MODE"
if (table == "copy-mode") return "COPY MODE"
if (table == "prefix") return "PREFIX"
gsub(/-/, " ", table)
return toupper(table)
}
function pretty_command(command) {
gsub(/\\;/, ";", command)
gsub(/[{}]/, "", command)
gsub(/^[ \t]+|[ \t]+$/, "", command)
gsub(/[ \t]+/, " ", command)
return command
}
function command_action(command, normalized, target) {
normalized = pretty_command(command)
if (normalized ~ /omarchy-menu-tmux-keybindings/) return "Show Tmux keybindings"
if (normalized ~ /^send(-keys)? -X begin-selection/) return "Begin selection"
if (normalized ~ /^send(-keys)? -X copy-selection-and-cancel/) return "Copy selection"
if (normalized ~ /^send-prefix/) return "Send prefix"
if (normalized ~ /^source-file/) return "Reload config"
if (normalized ~ /^split-window -v/) return "Split pane vertically"
if (normalized ~ /^split-window -h/) return "Split pane horizontally"
if (normalized ~ /^kill-pane/) return "Kill pane"
if (normalized ~ /^select-pane -L/) return "Focus pane left"
if (normalized ~ /^select-pane -R/) return "Focus pane right"
if (normalized ~ /^select-pane -U/) return "Focus pane up"
if (normalized ~ /^select-pane -D/) return "Focus pane down"
if (normalized ~ /^resize-pane -L/) return "Resize pane left"
if (normalized ~ /^resize-pane -R/) return "Resize pane right"
if (normalized ~ /^resize-pane -U/) return "Resize pane up"
if (normalized ~ /^resize-pane -D/) return "Resize pane down"
if (normalized ~ /^swap-pane -t "?left-of"?/) return "Move pane left"
if (normalized ~ /^swap-pane -t "?right-of"?/) return "Move pane right"
if (normalized ~ /^swap-pane -t "?up-of"?/) return "Move pane up"
if (normalized ~ /^swap-pane -t "?down-of"?/) return "Move pane down"
if (normalized ~ /^swap-pane -U/) return "Move pane left"
if (normalized ~ /^swap-pane -D/) return "Move pane right"
if (normalized ~ /rename-window/) return "Rename window"
if (normalized ~ /^new-window/) return "New window"
if (normalized ~ /^kill-window/) return "Kill window"
if (match(normalized, /^select-window -t ([^ ;]+)/, target)) {
gsub(/^:=?/, "", target[1])
if (target[1] == "-1") return "Previous window"
if (target[1] == "+1") return "Next window"
return "Switch to window " target[1]
}
if (normalized ~ /^swap-window -t -1/) return "Move window left"
if (normalized ~ /^swap-window -t \+1/) return "Move window right"
if (normalized ~ /rename-session/) return "Rename session"
if (normalized ~ /^new-session/) return "New session"
if (normalized ~ /^kill-session/) return "Kill session"
if (normalized ~ /^switch-client -p/) return "Previous session"
if (normalized ~ /^switch-client -n/) return "Next session"
return normalized
}
function add_record(combo, action) {
records[++record_count] = sprintf("%-32s → %s", combo, action)
}
function parse_bind(line, words, count, i, table, global, key, command, combo, action) {
count = split(line, words, /[ \t]+/)
i = 2
table = "prefix"
global = 0
while (i <= count && words[i] ~ /^-/) {
if (words[i] == "-n") {
global = 1
i++
} else if (words[i] == "-T") {
table = words[i + 1]
i += 2
} else if (words[i] == "-r") {
i++
} else {
i++
}
}
key = words[i]
i++
command = ""
for (; i <= count; i++) {
command = command (command == "" ? "" : " ") words[i]
}
if (key == "" || command == "") return
if (global) {
combo = key_text(key)
} else if (table == "prefix") {
combo = "PREFIX + " key_text(key)
} else {
combo = table_text(table) " + " key_text(key)
}
action = command_action(command)
add_record(combo, action)
}
BEGIN {
prefix = "C-b"
prefix2 = ""
}
{
line = trim($0)
if (line == "") next
if (line ~ /^#/) next
if (line ~ /^(set|set-option|setw|set-window-option)[ \t]/) {
word_count = split(line, words, /[ \t]+/)
for (i = 2; i <= word_count; i++) {
if (words[i] == "prefix") prefix = words[i + 1]
if (words[i] == "prefix2") prefix2 = words[i + 1]
}
next
}
if (line ~ /^(bind|bind-key)[ \t]/) parse_bind(line)
}
END {
prefix_description = key_text(prefix)
if (prefix2 != "" && prefix2 != "None") {
prefix_description = prefix_description " / " key_text(prefix2)
}
printf "%-32s → %s\n", "PREFIX", prefix_description
add_record("PREFIX + {", "Move pane left")
add_record("PREFIX + }", "Move pane right")
for (i = 1; i <= record_count; i++) print records[i]
}
' "$config_file"
}
if [[ $print_only == "true" ]]; then
output_keybindings
exit 0
fi
records=$(output_keybindings)
if [[ -z $WAYLAND_DISPLAY ]] || omarchy-cmd-missing walker; then
printf '%s\n' "$records"
exit 0
fi
monitor_height=$(hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused == true) | .height' 2>/dev/null)
if [[ ! $monitor_height =~ ^[0-9]+$ ]] || ((monitor_height <= 0)); then
monitor_height=900
fi
menu_height=$((monitor_height * 40 / 100))
printf '%s\n' "$records" | walker --dmenu -p 'Tmux keybindings' --width 800 --height "$menu_height" >/dev/null
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# omarchy:summary=Show the current battery status notification
omarchy-notification-send -g 󰁹 -u low "$(omarchy-battery-status)"
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# omarchy:summary=Show the current time and date notification
omarchy-notification-send -g  -u low "$(date +"%A %H:%M · %d %B %Y · Week %V")"
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# omarchy:summary=Show the current weather notification
omarchy-notification-send -g $(omarchy-weather-icon) -u low "$(omarchy-weather-status)"
@@ -1,10 +1,10 @@
#!/bin/bash
# omarchy:summary=Install an npx wrapper for a given npm package.
# omarchy:summary=Install a pnpm dlx wrapper for a given npm package.
# omarchy:args=<package> [command-name]
if [[ -z $1 ]]; then
echo "Usage: omarchy-npx-install <package> [command-name]"
echo "Usage: omarchy-npm-install <package> [command-name]"
exit 1
fi
@@ -23,8 +23,13 @@ if ! node_root="\$(mise where node@latest 2>/dev/null)"; then
node_root="\$(mise where node@latest)"
fi
node_bin="\$node_root/bin/node"
npx_bin="\$node_root/bin/npx"
if omarchy-cmd-missing pnpm; then
echo "Installing pnpm for \$package..."
omarchy-pkg-add pnpm
hash -r
fi
export PNPM_CONFIG_MINIMUM_RELEASE_AGE=7200
ensure_bin_runtime() {
local bin_path=\$1
@@ -51,15 +56,15 @@ exec_package_bin() {
fi
}
# Resolve the package bin inside npx, then run it with node@latest available for node shebangs.
# Resolve the package bin inside pnpm dlx, then run it with node@latest available for node shebangs.
# Some wrappers are aliases, e.g. playwright-cli wraps the playwright bin.
"\$node_bin" "\$npx_bin" --yes --prefer-online --package "\$package" -- true
PATH="\$node_root/bin:\$PATH" pnpm dlx --package "\$package" true
package_bin_path=\$("\$node_bin" "\$npx_bin" --yes --package "\$package" -- which "\$package" 2>/dev/null)
package_bin_path=\$(PATH="\$node_root/bin:\$PATH" pnpm dlx --package "\$package" which "\$package" 2>/dev/null)
exec_package_bin "\$package_bin_path" "\$@"
# Scoped packages like @openai/codex expose an unscoped bin like codex.
package_bin_path=\$("\$node_bin" "\$npx_bin" --yes --package "\$package" -- which "\$command" 2>/dev/null)
package_bin_path=\$(PATH="\$node_root/bin:\$PATH" pnpm dlx --package "\$package" which "\$command" 2>/dev/null)
exec_package_bin "\$package_bin_path" "\$@"
echo "Could not resolve npm bin for \$package / \$command" >&2
+3 -3
View File
@@ -11,14 +11,14 @@ mkdir -p ~/.local/share/applications
cp ~/.local/share/omarchy/applications/*.desktop ~/.local/share/applications/
cp ~/.local/share/omarchy/applications/hidden/*.desktop ~/.local/share/applications/
if omarchy-cmd-present foot; then
cp ~/.local/share/omarchy/default/foot/foot.desktop ~/.local/share/applications/
if omarchy-cmd-present alacritty; then
cp ~/.local/share/omarchy/default/alacritty/alacritty.desktop ~/.local/share/applications/
fi
# Refresh the webapps, TUIs, and npx wrappers
bash $OMARCHY_PATH/install/packaging/icons.sh
bash $OMARCHY_PATH/install/packaging/webapps.sh
bash $OMARCHY_PATH/install/packaging/tuis.sh
bash $OMARCHY_PATH/install/packaging/npx.sh
bash $OMARCHY_PATH/install/packaging/npm.sh
update-desktop-database ~/.local/share/applications
+1
View File
@@ -9,4 +9,5 @@ omarchy-refresh-config hypr/input.lua
omarchy-refresh-config hypr/looknfeel.lua
omarchy-refresh-config hypr/hyprland.lua
omarchy-refresh-config hypr/monitors.lua
bash "$OMARCHY_PATH/install/config/omarchy-toggles.sh"
bash "$OMARCHY_PATH/install/config/detect-keyboard-layout.sh"
+11
View File
@@ -3,6 +3,17 @@
# omarchy:summary=Reset Waybar config to Omarchy defaults
# omarchy:examples=omarchy refresh waybar
WAYBAR_CONFIG="$HOME/.config/waybar/config.jsonc"
position=$(sed -nE 's/.*"position"[[:space:]]*:[[:space:]]*"(top|bottom|left|right)".*/\1/p' "$WAYBAR_CONFIG" 2>/dev/null | head -n 1)
height=$(sed -nE 's/.*"height"[[:space:]]*:[[:space:]]*([0-9]+).*/\1/p' "$WAYBAR_CONFIG" 2>/dev/null | head -n 1)
width=$(sed -nE 's/.*"width"[[:space:]]*:[[:space:]]*([0-9]+).*/\1/p' "$WAYBAR_CONFIG" 2>/dev/null | head -n 1)
omarchy-refresh-config waybar/config.jsonc
omarchy-refresh-config waybar/style.css
[[ -n $position ]] && sed -i -E "s/(\"position\"[[:space:]]*:[[:space:]]*\")[a-z]+(\")/\\1${position}\\2/" "$WAYBAR_CONFIG"
[[ -n $height ]] && sed -i -E "s/(\"height\"[[:space:]]*:[[:space:]]*)[0-9]+/\\1${height}/" "$WAYBAR_CONFIG"
[[ -n $width ]] && sed -i -E "s/(\"width\"[[:space:]]*:[[:space:]]*)[0-9]+/\\1${width}/" "$WAYBAR_CONFIG"
omarchy-restart-waybar
+1 -1
View File
@@ -6,6 +6,6 @@ set -e
# Reinstall the Omarchy configuration directory from the git source.
git clone "https://github.com/basecamp/omarchy.git" ~/.local/share/omarchy-new >/dev/null
git clone --depth=1 --branch master "https://github.com/basecamp/omarchy.git" ~/.local/share/omarchy-new >/dev/null
mv $OMARCHY_PATH ~/.local/share/omarchy-old
mv ~/.local/share/omarchy-new $OMARCHY_PATH
+69
View File
@@ -0,0 +1,69 @@
#!/bin/bash
# omarchy:summary=Remove Sunshine and close Omarchy-managed Moonlight streaming ports.
# omarchy:requires-sudo=true
set -e
TCP_PORTS=(47984 47989 48010)
UDP_PORTS=(5353 47998 47999 48000 48002 48010)
PRIVATE_CIDRS=(10.0.0.0/8 172.16.0.0/12 192.168.0.0/16)
SUNSHINE_ADMIN_APP="Sunshine Admin"
HYPR_AUTOSTART_FILE="$HOME/.config/hypr/autostart.lua"
HYPR_AUTOSTART_ENTRY='o.launch_on_start("sunshine")'
delete_ufw_rule() {
sudo ufw --force delete "$@" 2>/dev/null || true
}
close_ufw_port_for_private_lans() {
local proto="$1"
local port="$2"
local cidr
for cidr in "${PRIVATE_CIDRS[@]}"; do
delete_ufw_rule allow in proto "$proto" from "$cidr" to any port "$port"
done
}
close_ufw_port_for_tailscale() {
local proto="$1"
local port="$2"
delete_ufw_rule allow in on tailscale0 to any port "$port" proto "$proto"
}
close_ufw_ports() {
local port
if omarchy-cmd-missing ufw; then
return
fi
for port in "${TCP_PORTS[@]}"; do
close_ufw_port_for_private_lans tcp "$port"
close_ufw_port_for_tailscale tcp "$port"
done
for port in "${UDP_PORTS[@]}"; do
close_ufw_port_for_private_lans udp "$port"
close_ufw_port_for_tailscale udp "$port"
done
sudo ufw reload
}
disable_hyprland_autostart() {
if [[ -f $HYPR_AUTOSTART_FILE ]]; then
sed -i "\|^$HYPR_AUTOSTART_ENTRY$|d" "$HYPR_AUTOSTART_FILE"
fi
}
systemctl --user disable --now sunshine 2>/dev/null || true
omarchy-pkg-drop sunshine
omarchy-webapp-remove "$SUNSHINE_ADMIN_APP" 2>/dev/null || true
disable_hyprland_autostart
close_ufw_ports
echo ""
echo "Sunshine has been removed and its Omarchy-managed Moonlight streaming ports have been closed."
+2 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash
# omarchy:summary=Set Hyprland, Hyprlock, Mako, and Walker corners to sharp or round
# omarchy:summary=Set Hyprland, Hyprlock, Mako, Walker, and Quickshell corners to sharp or round
# omarchy:args=<sharp|round>
# omarchy:examples=omarchy style corners round | omarchy style corners sharp
@@ -13,6 +13,7 @@ omarchy-style-corners-hyprland "$1"
omarchy-style-corners-hyprlock "$1"
omarchy-style-corners-mako "$1"
omarchy-style-corners-walker "$1"
omarchy-style-corners-quickshell "$1"
case $1 in
sharp) omarchy-notification-send "Sharp corners enabled" -g 󰝣 ;;
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# omarchy:summary=Set Quickshell Omarchy menu corners
# omarchy:args=<sharp|round>
# omarchy:examples=omarchy style corners quickshell round | omarchy style corners quickshell sharp
set_radius() {
local radius="$1"
local toggles_dir="$HOME/.local/state/omarchy/toggles"
mkdir -p "$toggles_dir"
printf '{ "radius": %s }\n' "$radius" >"$toggles_dir/quickshell-menu.json"
}
case "${1:-}" in
sharp) set_radius 0 ;;
round) set_radius 6 ;;
*)
echo "Usage: omarchy-style-corners-quickshell <sharp|round>"
exit 1
;;
esac
-16
View File
@@ -15,31 +15,15 @@ if [[ ! $position =~ ^(top|bottom|left|right)$ ]]; then
exit 1
fi
# Reset config and styles before making adjustments
omarchy-refresh-config waybar/config.jsonc
omarchy-refresh-config waybar/style.css
if [[ $position == "left" || $position == "right" ]]; then
height=0
width=28
horizontal=false
else
height=26
width=0
horizontal=true
fi
# Change position
sed -i -E "s/(\"position\"[[:space:]]*:[[:space:]]*\")[a-z]+(\")/\\1${position}\\2/" "$WAYBAR_CONFIG"
# Change height/width
sed -i -E "s/(\"height\"[[:space:]]*:[[:space:]]*)[0-9]+/\\1${height}/; s/(\"width\"[[:space:]]*:[[:space:]]*)[0-9]+/\\1${width}/" "$WAYBAR_CONFIG"
# Change the clock format
if [[ $horizontal == true ]]; then
sed -i -E '/"clock"[[:space:]]*:[[:space:]]*\{/,/\}/ s/"format"[[:space:]]*:[[:space:]]*"[^"]*"/"format": "{:L%A %H:%M}"/' "$WAYBAR_CONFIG"
else
sed -i -E '/"clock"[[:space:]]*:[[:space:]]*\{/,/\}/ s/"format"[[:space:]]*:[[:space:]]*"[^"]*"/"format": "{:%H\\n —\\n%M}"/' "$WAYBAR_CONFIG"
fi
omarchy-restart-waybar
+1 -1
View File
@@ -12,4 +12,4 @@ progress="$(awk -v p="$percent" 'BEGIN{printf "%.2f", p/100}')"
omarchy-swayosd-client \
--custom-icon display-brightness-symbolic \
--custom-progress "$progress" \
--custom-progress-text "${percent}%"
--custom-progress-text "$(printf '%3d%%' "$percent")"
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# omarchy:summary=Cache background switcher thumbnails for the current theme
theme_name=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
omarchy-menu-images \
--cache-only \
"$HOME/.config/omarchy/current/theme/backgrounds" \
"$HOME/.config/omarchy/backgrounds/$theme_name"
+7 -10
View File
@@ -8,13 +8,15 @@ THEME_BACKGROUNDS_PATH="$HOME/.config/omarchy/current/theme/backgrounds/"
USER_BACKGROUNDS_PATH="$HOME/.config/omarchy/backgrounds/$THEME_NAME/"
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
mapfile -d '' -t BACKGROUNDS < <(find -L "$USER_BACKGROUNDS_PATH" "$THEME_BACKGROUNDS_PATH" -maxdepth 1 -type f -print0 2>/dev/null | sort -z)
mapfile -d '' -t BACKGROUNDS < <(
find -L "$USER_BACKGROUNDS_PATH" "$THEME_BACKGROUNDS_PATH" -maxdepth 1 -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \) \
-print0 2>/dev/null | sort -z
)
TOTAL=${#BACKGROUNDS[@]}
if (( TOTAL == 0 )); then
notify-send "No background was found for theme" -t 2000
pkill -x swaybg
setsid uwsm-app -- swaybg --color '#000000' >/dev/null 2>&1 &
omarchy-notification-send "No background was found for theme" -t 2000
else
# Get current background from symlink
if [[ -L $CURRENT_BACKGROUND_LINK ]]; then
@@ -42,10 +44,5 @@ else
NEW_BACKGROUND="${BACKGROUNDS[$NEXT_INDEX]}"
fi
# Set new background symlink
ln -nsf "$NEW_BACKGROUND" "$CURRENT_BACKGROUND_LINK"
# Relaunch swaybg
pkill -x swaybg
setsid uwsm-app -- swaybg -i "$CURRENT_BACKGROUND_LINK" -m fill >/dev/null 2>&1 &
omarchy-theme-bg-set "$NEW_BACKGROUND"
fi
+1 -1
View File
@@ -2,7 +2,7 @@
# omarchy:summary=Set the current background image
# omarchy:args=<path-to-image>
# omarchy:examples=omarchy theme bg set ~/Pictures/wallpaper.png
# omarchy:examples=omarchy theme bg set ~/Pictures/background.png
if [[ -z $1 ]]; then
echo "Usage: omarchy-theme-bg-set <path-to-image>" >&2
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
# omarchy:summary=Open the Omarchy background switcher
# omarchy:group=theme
# omarchy:name=bg-switcher
# omarchy:aliases=omarchy background
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
theme_name=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
current_background=$(readlink -f "$HOME/.config/omarchy/current/background" 2>/dev/null)
omarchy-menu-images \
--selected "$current_background" \
"$HOME/.config/omarchy/current/theme/backgrounds" \
"$HOME/.config/omarchy/backgrounds/$theme_name"
+3
View File
@@ -71,3 +71,6 @@ omarchy-theme-set-keyboard
# Call hook on theme set
omarchy-hook theme-set "$THEME_NAME" >/dev/null
# Warm the background selector cache after the theme is applied, off the critical path.
omarchy-theme-bg-cache >/dev/null 2>&1 &
+98
View File
@@ -0,0 +1,98 @@
#!/bin/bash
# omarchy:summary=Open the Omarchy theme switcher
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
CACHE_PATH="${XDG_CACHE_HOME:-$HOME/.cache}/omarchy/theme-selector"
preview_dir="$CACHE_PATH/previews"
signature_file="$CACHE_PATH/signature"
mkdir -p "$preview_dir"
find_preview() {
local theme_path="$1"
local preview preview_name
for preview_name in preview.png preview.jpg preview.jpeg preview.webp preview.gif preview.bmp; do
preview=$(find -L "$theme_path" -maxdepth 1 -type f -iname "$preview_name" -print -quit 2>/dev/null)
if [[ -n $preview ]]; then
printf '%s\n' "$preview"
return
fi
done
if [[ -d $theme_path/backgrounds ]]; then
find -L "$theme_path/backgrounds" -maxdepth 1 -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \) -print 2>/dev/null | sort | head -n 1
fi
}
add_theme_preview() {
local theme_name="$1"
local preview="$2"
local extension="${preview##*.}"
extension="${extension,,}"
[[ -n $preview ]] || return
[[ -e $preview_dir/$theme_name.$extension ]] && return
ln -s "$preview" "$preview_dir/$theme_name.$extension"
}
theme_signature=""
for theme_dir in "$USER_THEMES_PATH" "$OMARCHY_THEMES_PATH"; do
if [[ -d $theme_dir ]]; then
theme_signature+="$theme_dir:$(stat -Lc '%Y' "$theme_dir")"$'\n'
while IFS= read -r -d '' theme_path; do
preview=$(find_preview "$theme_path")
theme_signature+="$theme_path:$(stat -Lc '%Y' "$theme_path")"$'\n'
if [[ -n $preview ]]; then
theme_signature+="$preview:$(stat -Lc '%s:%Y' "$preview")"$'\n'
fi
done < <(find -L "$theme_dir" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -print0 2>/dev/null | sort -z)
fi
done
if [[ ! -f $signature_file ]] || ! cmp -s "$signature_file" <(printf '%s' "$theme_signature"); then
rm -rf "$preview_dir"
mkdir -p "$preview_dir"
while IFS= read -r theme_path; do
theme_name=${theme_path##*/}
preview=$(find_preview "$theme_path")
if [[ -z $preview ]]; then
preview=$(find_preview "$OMARCHY_THEMES_PATH/$theme_name")
fi
add_theme_preview "$theme_name" "$preview"
done < <(find -L "$USER_THEMES_PATH" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -print 2>/dev/null | sort)
while IFS= read -r theme_path; do
theme_name=${theme_path##*/}
preview=$(find_preview "$theme_path")
add_theme_preview "$theme_name" "$preview"
done < <(find -L "$OMARCHY_THEMES_PATH" -mindepth 1 -maxdepth 1 -type d -print 2>/dev/null | sort)
printf '%s' "$theme_signature" >"$signature_file"
fi
current_theme=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
selected_preview=""
for extension in png jpg jpeg webp gif bmp; do
if [[ -e $preview_dir/$current_theme.$extension ]]; then
selected_preview="$preview_dir/$current_theme.$extension"
break
fi
done
exec omarchy-menu-images \
--print-name \
--show-labels \
--filterable \
--lazy-thumbnails \
--selected "$selected_preview" \
"$preview_dir"
+1 -1
View File
@@ -4,7 +4,7 @@
# omarchy:name=
# omarchy:summary=Transcode pictures and videos for sharing
# omarchy:args=[--path path] [input] [format] [resolution]
# omarchy:examples=omarchy transcode|omarchy transcode --path ~/Downloads|omarchy transcode ~/Videos/demo.mov mp4 1080p|omarchy transcode ~/Pictures/wallpaper.heic jpg medium
# omarchy:examples=omarchy transcode|omarchy transcode --path ~/Downloads|omarchy transcode ~/Videos/demo.mov mp4 1080p|omarchy transcode ~/Pictures/background.heic jpg medium
set -euo pipefail
+2 -1
View File
@@ -9,7 +9,8 @@ echo -e "\e[32mUpdate Omarchy\e[0m"
omarchy-update-time
# Suppress Hyprland config errors while git updates default config files mid-pull
hyprctl eval 'hl.config({ debug = { suppress_errors = true } })' &>/dev/null || hyprctl keyword debug:suppress_errors true &>/dev/null || true
hyprctl keyword debug:suppress_errors true &>/dev/null || true
hyprctl eval 'hl.config({ debug = { suppress_errors = true } })' &>/dev/null || true
git -C $OMARCHY_PATH pull --autostash
git -C $OMARCHY_PATH --no-pager diff --check || git -C $OMARCHY_PATH reset --merge
+7 -3
View File
@@ -4,6 +4,10 @@
echo
confirm_reboot() {
gum confirm "$1" && { omarchy-system-reboot; exit 0; }
}
running_kernel=$(uname -r)
kernel_updated=true
@@ -19,14 +23,14 @@ for kernel in /usr/lib/modules/*/vmlinuz; do
done
if [[ $kernel_updated == "true" ]]; then
gum confirm "Linux kernel has been updated. Reboot?" && omarchy-system-reboot
confirm_reboot "Linux kernel has been updated. Reboot?"
elif [[ -f $HOME/.local/state/omarchy/reboot-required ]]; then
gum confirm "Updates require reboot. Ready?" && omarchy-system-reboot
confirm_reboot "Updates require reboot. Ready?"
fi
running_hyprland=$(readlink /proc/$(pgrep -x Hyprland)/exe 2>/dev/null)
if [[ $running_hyprland == *"(deleted)"* ]]; then
gum confirm "Hyprland has been updated. Reboot?" && omarchy-system-reboot
confirm_reboot "Hyprland has been updated. Reboot?"
fi
for file in "$HOME"/.local/state/omarchy/restart-*-required; do
+2 -3
View File
@@ -11,12 +11,11 @@ if omarchy-cmd-present voxtype; then
echo "Uninstall Voxtype to remove dictation."
# Remove services
systemctl --user stop voxtype.service 2>/dev/null || true
rm -f ~/.config/systemd/user/voxtype*
systemctl --user disable --now voxtype.service 2>/dev/null || true
systemctl --user daemon-reload
# Remove packages and configs
omarchy-pkg-drop wtype voxtype-bin
omarchy-pkg-drop voxtype-bin
rm -rf ~/.config/voxtype
rm -rf ~/.local/share/voxtype
else
+1 -1
View File
@@ -14,4 +14,4 @@ place=${place%%,*}
place=${place^}
temperature=${temperature#+}
echo "$(omarchy-weather-icon) $place · Temp $temperature · Wind $wind"
echo "$place · Temp $temperature · Wind $wind"
+1 -1
View File
@@ -1 +1 @@
command = 'wl-copy && (hyprctl dispatch "hl.dsp.send_shortcut({ mods = \"SHIFT\", key = \"Insert\" })" || hyprctl dispatch sendshortcut "SHIFT, Insert,")'
command = 'wl-copy && ((hyprctl dispatch "hl.dsp.send_key_state({ mods = \"SHIFT\", key = \"Insert\", state = \"down\", window = \"activewindow\" })" && sleep 0.05 && hyprctl dispatch "hl.dsp.send_key_state({ mods = \"SHIFT\", key = \"Insert\", state = \"up\", window = \"activewindow\" })") || hyprctl dispatch sendshortcut "SHIFT, Insert, activewindow")'
+1 -1
View File
@@ -6,6 +6,6 @@
"checkThirdParty": false
},
"diagnostics": {
"globals": ["hl"]
"globals": ["hl", "o"]
}
}
+1 -3
View File
@@ -1,4 +1,2 @@
-- Extra autostart processes.
-- hl.on("hyprland.start", function()
-- hl.exec_cmd("uwsm-app -- my-service")
-- end)
-- o.launch_on_start("my-service")
+31 -30
View File
@@ -1,40 +1,41 @@
-- Application bindings.
hl.bind("SUPER + RETURN", hl.dsp.exec_cmd([[uwsm-app -- xdg-terminal-exec --dir="$(omarchy-cmd-terminal-cwd)"]]), { description = "Terminal" })
hl.bind("SUPER + ALT + RETURN", hl.dsp.exec_cmd([[uwsm-app -- xdg-terminal-exec --dir="$(omarchy-cmd-terminal-cwd)" bash -c "tmux attach || tmux new -s Work"]]), { description = "Tmux" })
hl.bind("SUPER + SHIFT + RETURN", hl.dsp.exec_cmd("omarchy-launch-browser"), { description = "Browser" })
hl.bind("SUPER + SHIFT + F", hl.dsp.exec_cmd("uwsm-app -- nautilus --new-window"), { description = "File manager" })
hl.bind("SUPER + ALT + SHIFT + F", hl.dsp.exec_cmd([[uwsm-app -- nautilus --new-window "$(omarchy-cmd-terminal-cwd)"]]), { description = "File manager (cwd)" })
hl.bind("SUPER + SHIFT + B", hl.dsp.exec_cmd("omarchy-launch-browser"), { description = "Browser" })
hl.bind("SUPER + SHIFT + ALT + B", hl.dsp.exec_cmd("omarchy-launch-browser --private"), { description = "Browser (private)" })
hl.bind("SUPER + SHIFT + M", hl.dsp.exec_cmd("omarchy-launch-or-focus spotify"), { description = "Music" })
hl.bind("SUPER + SHIFT + ALT + M", hl.dsp.exec_cmd("omarchy-launch-or-focus-tui cliamp"), { description = "Music TUI" })
hl.bind("SUPER + SHIFT + N", hl.dsp.exec_cmd("omarchy-launch-editor"), { description = "Editor" })
hl.bind("SUPER + SHIFT + D", hl.dsp.exec_cmd("omarchy-launch-tui lazydocker"), { description = "Docker" })
hl.bind("SUPER + SHIFT + G", hl.dsp.exec_cmd([[omarchy-launch-or-focus ^signal$ "uwsm-app -- signal-desktop"]]), { description = "Signal" })
hl.bind("SUPER + SHIFT + O", hl.dsp.exec_cmd([[omarchy-launch-or-focus ^obsidian$ "uwsm-app -- obsidian"]]), { description = "Obsidian" })
hl.bind("SUPER + SHIFT + W", hl.dsp.exec_cmd("uwsm-app -- typora --enable-wayland-ime"), { description = "Typora" })
hl.bind("SUPER + SHIFT + SLASH", hl.dsp.exec_cmd("uwsm-app -- 1password"), { description = "Passwords" })
o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" })
o.bind("SUPER + ALT + RETURN", "Tmux", { omarchy = "terminal-tmux" })
o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" })
o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" })
o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" })
o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" })
o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" })
o.bind("SUPER + SHIFT + M", "Music", { omarchy = "or-focus spotify" })
o.bind("SUPER + SHIFT + ALT + M", "Music TUI", { tui = "cliamp", focus = true })
o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" })
o.bind("SUPER + SHIFT + D", "Docker", { tui = "lazydocker" })
o.bind("SUPER + SHIFT + G", "Signal", { launch = "signal-desktop", focus = "^signal$" })
o.bind("SUPER + SHIFT + O", "Obsidian", { launch = "obsidian", focus = "^obsidian$" })
o.bind("SUPER + SHIFT + W", "Typora", { launch = "typora --enable-wayland-ime" })
o.bind("SUPER + SHIFT + SLASH", "Passwords", { launch = "1password" })
-- Web app bindings.
hl.bind("SUPER + SHIFT + A", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://chatgpt.com"]]), { description = "ChatGPT" })
hl.bind("SUPER + SHIFT + ALT + A", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://grok.com"]]), { description = "Grok" })
hl.bind("SUPER + SHIFT + C", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://app.hey.com/calendar/weeks/"]]), { description = "Calendar" })
hl.bind("SUPER + SHIFT + E", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://app.hey.com"]]), { description = "Email" })
hl.bind("SUPER + SHIFT + Y", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://youtube.com/"]]), { description = "YouTube" })
hl.bind("SUPER + SHIFT + ALT + G", hl.dsp.exec_cmd([[omarchy-launch-or-focus-webapp WhatsApp "https://web.whatsapp.com/"]]), { description = "WhatsApp" })
hl.bind("SUPER + SHIFT + CTRL + G", hl.dsp.exec_cmd([[omarchy-launch-or-focus-webapp "Google Messages" "https://messages.google.com/web/conversations"]]), { description = "Google Messages" })
hl.bind("SUPER + SHIFT + P", hl.dsp.exec_cmd([[omarchy-launch-or-focus-webapp "Google Photos" "https://photos.google.com/"]]), { description = "Google Photos" })
hl.bind("SUPER + SHIFT + X", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://x.com/"]]), { description = "X" })
hl.bind("SUPER + SHIFT + ALT + X", hl.dsp.exec_cmd([[omarchy-launch-webapp "https://x.com/compose/post"]]), { description = "X Post" })
o.bind("SUPER + SHIFT + A", "ChatGPT", { webapp = "https://chatgpt.com" })
o.bind("SUPER + SHIFT + ALT + A", "Grok", { webapp = "https://grok.com" })
o.bind("SUPER + SHIFT + C", "Calendar", { webapp = "https://app.hey.com/calendar/weeks/" })
o.bind("SUPER + SHIFT + E", "Email", { webapp = "https://app.hey.com" })
o.bind("SUPER + SHIFT + Y", "YouTube", { webapp = "https://youtube.com/" })
o.bind("SUPER + SHIFT + ALT + G", "WhatsApp", { webapp = "https://web.whatsapp.com/", focus = true })
o.bind("SUPER + SHIFT + CTRL + G", "Google Messages", { webapp = "https://messages.google.com/web/conversations", focus = true })
o.bind("SUPER + SHIFT + P", "Google Photos", { webapp = "https://photos.google.com/", focus = true })
o.bind("SUPER + SHIFT + S", "Google Maps", { webapp = "https://maps.google.com/", focus = true })
o.bind("SUPER + SHIFT + X", "X", { webapp = "https://x.com/" })
o.bind("SUPER + SHIFT + ALT + X", "X Post", { webapp = "https://x.com/compose/post" })
-- Add extra bindings below.
-- hl.bind("SUPER + SHIFT + R", hl.dsp.exec_cmd("alacritty -e ssh your-server"), { description = "SSH" })
-- o.bind("SUPER + SHIFT + R", "SSH", "alacritty -e ssh your-server")
-- Overwrite existing bindings with hl.unbind() first if needed.
-- hl.unbind("SUPER + SPACE")
-- hl.bind("SUPER + SPACE", hl.dsp.exec_cmd("omarchy-menu"), { description = "Omarchy menu" })
-- o.bind("SUPER + SPACE", "Omarchy menu", "omarchy-menu")
-- Logitech MX Keys examples:
-- hl.bind("SUPER + SHIFT + S", hl.dsp.exec_cmd("omarchy-capture-screenshot"))
-- hl.bind("SUPER + H", hl.dsp.exec_cmd("voxtype record toggle"))
-- hl.bind("SUPER + PERIOD", hl.dsp.exec_cmd("omarchy-launch-walker -m symbols"))
-- o.bind("SUPER + SHIFT + S", nil, "omarchy-capture-screenshot")
-- o.bind("SUPER + H", nil, "voxtype record toggle")
-- o.bind("SUPER + PERIOD", nil, { omarchy = "walker -m symbols" })
+9 -27
View File
@@ -1,32 +1,14 @@
-- Learn how to configure Hyprland: https://wiki.hypr.land/Configuring/Start/
local home = os.getenv("HOME") or ""
-- Load user modules from ~/.config and Omarchy defaults from $OMARCHY_PATH.
package.path = os.getenv("HOME")
.. "/.config/?.lua;"
.. (os.getenv("OMARCHY_PATH") or (os.getenv("HOME") .. "/.local/share/omarchy"))
.. "/?.lua;"
.. package.path
-- Hyprland recommends require() for split Lua configs. These two roots let us
-- load user modules from ~/.config and Omarchy defaults from $OMARCHY_PATH.
package.path = home .. "/.config/?.lua;" .. (os.getenv("OMARCHY_PATH") or (home .. "/.local/share/omarchy")) .. "/?.lua;" .. package.path
local paths = require("default.hypr.paths")
-- Use Omarchy defaults, but don't edit these directly.
require("default.hypr.autostart")
require("default.hypr.bindings.media")
require("default.hypr.bindings.clipboard")
require("default.hypr.bindings.tiling-v2")
require("default.hypr.bindings.utilities")
require("default.hypr.envs")
require("default.hypr.looknfeel")
require("default.hypr.input")
require("default.hypr.windows")
-- Current theme overrides.
do
local theme = io.open(paths.config_home .. "/omarchy/current/theme/hyprland.lua", "r")
if theme then
theme:close()
require("omarchy.current.theme.hyprland")
end
end
-- All Omarchy default setups
require("default.hypr.omarchy")
-- Change your own setup in these files and override defaults.
require("hypr.monitors")
@@ -39,4 +21,4 @@ require("hypr.autostart")
require("default.hypr.toggles")
-- Add any other personal Hyprland configuration below.
-- hl.window_rule({ match = { class = "qemu" }, workspace = "5" })
-- o.window("qemu", { workspace = "5" })
+2 -2
View File
@@ -43,8 +43,8 @@ hl.config({
})
-- Scroll nicely in the terminal.
hl.window_rule({ match = { class = "(Alacritty|kitty|foot)" }, scroll_touchpad = 1.5 })
hl.window_rule({ match = { class = "com.mitchellh.ghostty" }, scroll_touchpad = 0.2 })
o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 })
o.window("com.mitchellh.ghostty", { scroll_touchpad = 0.2 })
-- Enable touchpad gestures for changing workspaces.
-- See https://wiki.hypr.land/Configuring/Advanced-and-Cool/Gestures/
-20
View File
@@ -1,20 +0,0 @@
# Overwrite parts of the omarchy-menu with user-specific submenus.
# See $OMARCHY_PATH/bin/omarchy-menu for functions that can be overwritten.
#
# WARNING: Overwritten functions will obviously not be updated when Omarchy changes.
#
# Example of minimal system menu:
#
# show_system_menu() {
# case $(menu "System" " Lock\n󰐥 Shutdown") in
# *Lock*) omarchy-system-lock ;;
# *Shutdown*) omarchy-system-shutdown ;;
# *) back_to show_main_menu ;;
# esac
# }
#
# Example of overriding just the about menu action: (Using zsh instead of bash (default))
#
# show_about() {
# exec omarchy-launch-or-focus-tui "zsh -c 'fastfetch; read -k 1'"
# }
@@ -0,0 +1,31 @@
{
// Extend the Quickshell Omarchy menu with JSONC.
//
// IDs are object keys. The parent is inferred from the dotted id, so
// "personal.notes" appears under "personal", and "personal" appears on the
// root menu. Reuse an existing id to override/extend it.
//
// Fields:
// icon Nerd Font glyph shown in the icon column.
// label Visible row title.
// action Shell command to run. If omitted, the row is a submenu.
// target Existing submenu id to open. Use for links/aliases.
// provider Runtime provider function/command returning JSON rows.
// aliases Alternate `omarchy-menu <name>` routes; also searchable.
// keywords Extra search terms beyond id/label/aliases.
// description Optional subtitle and extra search text.
// when Shell condition; hide row when it fails.
// checked Shell condition; append ✓ when it succeeds.
//
// Examples:
// "personal": {"icon":"","label":"Personal","keywords":"notes projects"},
// "personal.notes": {"icon":"󰎞","label":"Notes","action":"omarchy-launch-editor ~/notes","keywords":"notes"},
// "personal.files": {"icon":"","label":"Files","action":"uwsm-app -- nautilus ~/Documents","keywords":"files documents"},
//
// Only use provider when a provider_name function or command named "name"
// returns JSON rows. Static submenus only need dotted ids.
//
// Example: replace the default About action by reusing the same id. Existing
// fields are kept unless overridden.
// "about": {"icon":"","label":"About","action":"omarchy-launch-or-focus-tui \"zsh -c 'fastfetch; read -k 1'\""},
}
+6 -1
View File
@@ -3,8 +3,9 @@ set -g prefix C-Space
set -g prefix2 C-b
bind C-Space send-prefix
# Reload config
# Config and help
bind q source-file ~/.config/tmux/tmux.conf \; display "Configuration reloaded"
bind ? display-popup -E -w 80% -h 70% -T "Tmux keybindings" "omarchy-menu-tmux-keybindings --print | less -R"
# Vi mode for copy
setw -g mode-keys vi
@@ -12,6 +13,10 @@ bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send -X copy-selection-and-cancel
# Pane Controls
bind -n M-Enter split-window -v -c "#{pane_current_path}"
bind -n M-S-Enter split-window -h -c "#{pane_current_path}"
bind -n M-Escape kill-pane
bind h split-window -v -c "#{pane_current_path}"
bind v split-window -h -c "#{pane_current_path}"
bind x kill-pane
+3
View File
@@ -3,6 +3,9 @@
# Install other terminals via Install > Terminal
export TERMINAL=xdg-terminal-exec
# Used by terminal programs (like gh) to open URLs detached from the terminal process tree
export BROWSER=omarchy-launch-browser
# Use code for VSCode
export EDITOR=nvim
+23 -4
View File
@@ -6,7 +6,7 @@
"height": 26,
"width": 0,
"modules-left": ["custom/omarchy", "hyprland/workspaces"],
"modules-center": ["clock", "custom/weather", "custom/update", "custom/voxtype", "custom/screenrecording-indicator", "custom/idle-indicator", "custom/notification-silencing-indicator"],
"modules-center": ["clock#horizontal", "clock#vertical", "custom/weather", "custom/update", "custom/voxtype", "custom/screenrecording-indicator", "custom/idle-indicator", "custom/notification-silencing-indicator"],
"modules-right": [
"group/tray-expander",
"bluetooth",
@@ -61,12 +61,18 @@
"on-click": "omarchy-launch-or-focus-tui btop",
"on-click-right": "alacritty"
},
"clock": {
"clock#horizontal": {
"format": "{:L%A %H:%M}",
"format-alt": "{:L%d %B W%V %Y}",
"tooltip": false,
"on-click-right": "omarchy-launch-floating-terminal-with-presentation omarchy-tz-select"
},
"clock#vertical": {
"format": "{:%H\n —\n%M}",
"format-alt": "{:L%d %B W%V %Y}",
"tooltip": false,
"on-click-right": "omarchy-launch-floating-terminal-with-presentation omarchy-tz-select"
},
"custom/weather": {
"exec": "$OMARCHY_PATH/default/waybar/weather.sh",
"return-type": "json",
@@ -135,9 +141,13 @@
"transition-duration": 600,
"children-class": "tray-group-item"
},
"modules": ["custom/expand-icon", "tray"]
"modules": ["group/expand-icons", "tray"]
},
"custom/expand-icon": {
"group/expand-icons": {
"orientation": "inherit",
"modules": ["custom/expand-icon#horizontal", "custom/expand-icon#vertical"]
},
"custom/expand-icon#horizontal": {
"format": "",
"tooltip": false,
"on-scroll-up": "",
@@ -145,6 +155,15 @@
"on-scroll-left": "",
"on-scroll-right": ""
},
"custom/expand-icon#vertical": {
"format": "",
"rotate": 270,
"tooltip": false,
"on-scroll-up": "",
"on-scroll-down": "",
"on-scroll-left": "",
"on-scroll-right": ""
},
"custom/screenrecording-indicator": {
"on-click": "omarchy-capture-screenrecording",
"exec": "$OMARCHY_PATH/default/waybar/indicators/screen-recording.sh",
+42
View File
@@ -110,6 +110,7 @@ tooltip {
#custom-voxtype.recording {
color: #a55555;
}
.left .modules-left, .right .modules-left { margin: 8px 0 0 0; }
.left .modules-right, .right .modules-right { margin: 0 0 8px 0; }
@@ -145,3 +146,44 @@ tooltip {
}
.left #custom-voxtype, .right #custom-voxtype { margin: 7.5px 0 0 0; min-width: 0; min-height: 12px; }
#custom-expand-icon.vertical,
.left #custom-expand-icon.horizontal,
.right #custom-expand-icon.horizontal {
opacity: 0;
font-size: 0;
min-width: 0;
min-height: 0;
margin: 0;
padding: 0;
}
.left #custom-expand-icon.vertical,
.right #custom-expand-icon.vertical {
opacity: 1;
font-size: inherit;
min-width: 0;
min-height: 12px;
margin: 1.5px 0;
padding: 6px 0;
}
#clock.vertical,
.left #clock.horizontal,
.right #clock.horizontal {
opacity: 0;
font-size: 0;
min-width: 0;
min-height: 0;
margin: 0;
padding: 0;
}
.left #clock.vertical,
.right #clock.vertical {
opacity: 1;
font-size: inherit;
min-width: 0;
min-height: 12px;
margin: 8.75px 0 0 0;
}
+27
View File
@@ -34,6 +34,33 @@ tdl() {
tmux send-keys -t "$editor_pane" "$EDITOR ." C-m
# Select the nvim pane for focus
tmux select-pane -t "$opencode_pane"
}
# Create a Tmux Dev Square layout with editor, diff watch, terminal, and opencode
# Usage: tds
tds() {
[[ -n $1 ]] && { echo "Usage: tds"; return 1; }
[[ -z $TMUX ]] && { echo "You must start tmux to use tds."; return 1; }
local current_dir="${PWD}"
local editor_pane diff_pane terminal_pane opencode_pane
editor_pane="$TMUX_PANE"
tmux rename-window -t "$editor_pane" "$(basename "$current_dir")"
terminal_pane=$(tmux split-window -v -p 50 -t "$editor_pane" -c "$current_dir" -P -F '#{pane_id}')
diff_pane=$(tmux split-window -h -p 50 -t "$editor_pane" -c "$current_dir" -P -F '#{pane_id}')
opencode_pane=$(tmux split-window -h -p 50 -t "$terminal_pane" -c "$current_dir" -P -F '#{pane_id}')
tmux send-keys -t "$editor_pane" -l "nvim ."
tmux send-keys -t "$editor_pane" C-m
tmux send-keys -t "$diff_pane" -l "hunk diff --watch"
tmux send-keys -t "$diff_pane" C-m
tmux send-keys -t "$opencode_pane" -l "opencode"
tmux send-keys -t "$opencode_pane" C-m
tmux select-pane -t "$editor_pane"
}
@@ -44,9 +44,9 @@ function GetEntries()
-- Track added files to avoid duplicates
local seen = {}
for _, wallpaper_dir in ipairs(dirs) do
for _, background_dir in ipairs(dirs) do
local handle = io.popen(
"find -L " .. ShellEscape(wallpaper_dir)
"find -L " .. ShellEscape(background_dir)
.. " -maxdepth 1 -type f \\( -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' -o -name '*.gif' -o -name '*.bmp' -o -name '*.webp' \\) 2>/dev/null | sort"
)
if handle then
+1 -2
View File
@@ -1,2 +1 @@
hl.window_rule({ match = { class = "^(1[p|P]assword)$" }, no_screen_share = true })
hl.window_rule({ match = { class = "^(1[p|P]assword)$" }, tag = "+floating-window" })
o.window("^(1[p|P]assword)$", { no_screen_share = true, tag = "+floating-window" })
+5 -5
View File
@@ -1,6 +1,6 @@
hl.window_rule({ match = { class = "^(Bitwarden)$" }, no_screen_share = true })
hl.window_rule({ match = { class = "^(Bitwarden)$" }, tag = "+floating-window" })
o.window("^(Bitwarden)$", { no_screen_share = true, tag = "+floating-window" })
-- Bitwarden Chrome Extension.
hl.window_rule({ match = { class = "chrome-nngceckbapebfimnlniiiahkandclblb-Default" }, no_screen_share = true })
hl.window_rule({ match = { class = "chrome-nngceckbapebfimnlniiiahkandclblb-Default" }, tag = "+floating-window" })
o.window("chrome-nngceckbapebfimnlniiiahkandclblb-Default", {
no_screen_share = true,
tag = "+floating-window",
})
+9 -16
View File
@@ -1,19 +1,12 @@
-- Browser types.
hl.window_rule({ match = { class = "((google-)?[cC]hrom(e|ium)|[bB]rave-browser|[mM]icrosoft-edge|Vivaldi-stable|helium)" }, tag = "+chromium-based-browser" })
hl.window_rule({ match = { class = "([fF]irefox|zen|librewolf)" }, tag = "+firefox-based-browser" })
hl.window_rule({ match = { tag = "chromium-based-browser" }, tag = "-default-opacity" })
hl.window_rule({ match = { tag = "firefox-based-browser" }, tag = "-default-opacity" })
-- Browser tags and styling.
o.window("((google-)?[cC]hrom(e|ium)|[bB]rave-browser|[mM]icrosoft-edge|Vivaldi-stable|helium)", { tag = "+chromium-based-browser" })
o.window("([fF]irefox|zen|librewolf)", { tag = "+firefox-based-browser" })
o.window({ tag = "chromium-based-browser" }, { tag = "-default-opacity", tile = true, opacity = "1.0 0.97" })
o.window({ tag = "firefox-based-browser" }, { tag = "-default-opacity", opacity = "1.0 0.97" })
-- Video apps: remove chromium browser tag so they don't get opacity applied.
hl.window_rule({ match = { class = "(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)" }, tag = "-chromium-based-browser" })
hl.window_rule({ match = { class = "(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)" }, tag = "-default-opacity" })
o.window("(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)", { tag = "-chromium-based-browser" })
o.window("(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)", { tag = "-default-opacity" })
-- Force chromium-based browsers into a tile to deal with --app bug.
hl.window_rule({ match = { tag = "chromium-based-browser" }, tile = true })
-- Only a subtle opacity change, but not for video sites.
hl.window_rule({ match = { tag = "chromium-based-browser" }, opacity = "1.0 0.97" })
hl.window_rule({ match = { tag = "firefox-based-browser" }, opacity = "1.0 0.97" })
-- Hide the screen-sharing notification bar (the "Hide" button on it is broken on Wayland).
hl.window_rule({ match = { title = ".*is sharing.*" }, workspace = "special silent" })
-- Hide screen sharing notification windows.
o.window({ title = ".*is sharing.*" }, { workspace = "special silent" })
+2 -2
View File
@@ -1,2 +1,2 @@
-- Focus floating DaVinci Resolve dialog windows.
hl.window_rule({ match = { class = ".*[Rr]esolve.*", float = true }, stay_focused = true })
-- DaVinci Resolve dialog focus handling.
o.window(".*[Rr]esolve.*", { float = true, stay_focused = true })
+1 -5
View File
@@ -1,5 +1 @@
hl.window_rule({
name = "geforce",
match = { class = "GeForceNOW" },
idle_inhibit = "fullscreen",
})
o.window("GeForceNOW", { idle_inhibit = "fullscreen" })
+1 -1
View File
@@ -1,2 +1,2 @@
-- Remove 1px border around hyprshot screenshots.
hl.layer_rule({ match = { namespace = "selection" }, no_anim = true })
hl.layer_rule({ match = { namespace = "selection" }, no_anim = true, animation = "none" })
+1 -5
View File
@@ -1,6 +1,2 @@
-- Disable mouse focus (see https://github.com/basecamp/omarchy/pull/5183#issuecomment-4189299971).
hl.window_rule({
name = "jetbrains-focus",
match = { class = "^(jetbrains-.*)$" },
no_follow_mouse = true,
})
o.window("^(jetbrains-.*)$", { no_follow_mouse = true })
+2 -3
View File
@@ -1,4 +1,3 @@
-- Float LocalSend and fzf file picker.
hl.window_rule({ match = { class = "(Share|localsend)" }, float = true })
hl.window_rule({ match = { class = "(Share|localsend)" }, center = true })
hl.window_rule({ match = { class = "localsend" }, size = { 1100, 700 } })
o.window("(Share|localsend)", { float = true, center = true })
o.window("localsend", { size = { 1100, 700 } })
+1 -6
View File
@@ -1,6 +1 @@
hl.window_rule({
name = "moonlight",
match = { class = "com.moonlight_stream.Moonlight" },
fullscreen = true,
idle_inhibit = "fullscreen",
})
o.window("com.moonlight_stream.Moonlight", { fullscreen = true, idle_inhibit = "fullscreen" })
+11 -9
View File
@@ -1,10 +1,12 @@
-- Picture-in-picture overlays.
hl.window_rule({ match = { title = "(Picture.?in.?[Pp]icture)" }, tag = "+pip" })
hl.window_rule({ match = { tag = "pip" }, tag = "-default-opacity" })
hl.window_rule({ match = { tag = "pip" }, float = true })
hl.window_rule({ match = { tag = "pip" }, pin = true })
hl.window_rule({ match = { tag = "pip" }, size = { 600, 338 } })
hl.window_rule({ match = { tag = "pip" }, keep_aspect_ratio = true })
hl.window_rule({ match = { tag = "pip" }, border_size = 0 })
hl.window_rule({ match = { tag = "pip" }, opacity = "1 1" })
hl.window_rule({ match = { tag = "pip" }, move = { "(monitor_w-window_w-40)", "(monitor_h*0.04)" } })
o.window({ title = "(Picture.?in.?[Pp]icture)" }, { tag = "+pip" })
o.window({ tag = "pip" }, {
tag = "-default-opacity",
float = true,
pin = true,
size = { 600, 338 },
keep_aspect_ratio = true,
border_size = 0,
opacity = "1 1",
move = { "(monitor_w-window_w-40)", "(monitor_h*0.04)" },
})
+1 -2
View File
@@ -1,2 +1 @@
hl.window_rule({ match = { class = "qemu" }, tag = "-default-opacity" })
hl.window_rule({ match = { class = "qemu" }, opacity = "1 1" })
o.window("qemu", { tag = "-default-opacity", opacity = "1 1" })
+2
View File
@@ -0,0 +1,2 @@
-- Keep the menu instant: no layer-shell fade/slide animation.
hl.layer_rule({ match = { namespace = "omarchy-menu" }, no_anim = true, animation = "none" })
+6 -4
View File
@@ -1,4 +1,6 @@
hl.window_rule({ match = { class = "com.libretro.RetroArch" }, fullscreen = true })
hl.window_rule({ match = { class = "com.libretro.RetroArch" }, tag = "-default-opacity" })
hl.window_rule({ match = { class = "com.libretro.RetroArch" }, opacity = "1 1" })
hl.window_rule({ match = { class = "com.libretro.RetroArch" }, idle_inhibit = "fullscreen" })
o.window("com.libretro.RetroArch", {
fullscreen = true,
tag = "-default-opacity",
opacity = "1 1",
idle_inhibit = "fullscreen",
})
+4 -8
View File
@@ -1,8 +1,4 @@
-- Float Steam.
hl.window_rule({ match = { class = "steam" }, float = true })
hl.window_rule({ match = { class = "steam", title = "Steam" }, center = true })
hl.window_rule({ match = { class = "steam.*" }, tag = "-default-opacity" })
hl.window_rule({ match = { class = "steam.*" }, opacity = "1 1" })
hl.window_rule({ match = { class = "steam", title = "Steam" }, size = { 1100, 700 } })
hl.window_rule({ match = { class = "steam", title = "Friends List" }, size = { 460, 800 } })
hl.window_rule({ match = { class = "steam" }, idle_inhibit = "fullscreen" })
o.window("steam", { float = true, idle_inhibit = "fullscreen" })
o.window({ class = "steam", title = "Steam" }, { center = true, size = { 1100, 700 } })
o.window("steam.*", { tag = "-default-opacity", opacity = "1 1" })
o.window({ class = "steam", title = "Friends List" }, { size = { 460, 800 } })
+13 -18
View File
@@ -1,23 +1,18 @@
-- Floating windows.
hl.window_rule({ match = { tag = "floating-window" }, float = true })
hl.window_rule({ match = { tag = "floating-window" }, center = true })
hl.window_rule({ match = { tag = "floating-window" }, size = { 875, 600 } })
o.window({ tag = "floating-window" }, { float = true, center = true, size = { 875, 600 } })
hl.window_rule({ match = { class = "(org.omarchy.bluetui|org.omarchy.impala|org.omarchy.wiremix|org.omarchy.btop|org.omarchy.terminal|org.omarchy.bash|org.codeberg.dnkl.foot|org.gnome.NautilusPreviewer|org.gnome.Evince|com.gabm.satty|Omarchy|About|TUI.float|imv|mpv)" }, tag = "+floating-window" })
hl.window_rule({ match = { class = "(xdg-desktop-portal-gtk|sublime_text|DesktopEditors|org.gnome.Nautilus)", title = "^(Open.*Files?|Open [F|f]older.*|Save.*Files?|Save.*As|Save|All Files|.*wants to [open|save].*|[C|c]hoose.*)" }, tag = "+floating-window" })
hl.window_rule({ match = { class = "org.gnome.Calculator" }, float = true })
o.window("(org.omarchy.bluetui|org.omarchy.impala|org.omarchy.wiremix|org.omarchy.btop|org.omarchy.terminal|org.omarchy.bash|org.codeberg.dnkl.foot|org.gnome.NautilusPreviewer|org.gnome.Evince|com.gabm.satty|Omarchy|About|TUI.float|imv|mpv)", { tag = "+floating-window" })
o.window({ class = "(xdg-desktop-portal-gtk|sublime_text|DesktopEditors|org.gnome.Nautilus)", title = "^(Open.*Files?|Open [F|f]older.*|Save.*Files?|Save.*As|Save|All Files|.*wants to [open|save].*|[C|c]hoose.*)" }, { tag = "+floating-window" })
o.window("org.gnome.Calculator", { float = true })
-- Fullscreen screensaver.
hl.window_rule({ match = { class = "org.omarchy.screensaver" }, fullscreen = true })
hl.window_rule({ match = { class = "org.omarchy.screensaver" }, float = true })
hl.window_rule({ match = { class = "org.omarchy.screensaver" }, animation = "slide" })
-- Screen saver should always cover the screen and not be tiled.
o.window("org.omarchy.screensaver", { fullscreen = true, float = true, animation = "slide" })
-- No transparency on media windows.
hl.window_rule({ match = { class = "^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$" }, tag = "-default-opacity" })
hl.window_rule({ match = { class = "^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$" }, opacity = "1 1" })
-- Media/image/video apps should be opaque.
o.window("^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$", { tag = "-default-opacity", opacity = "1 1" })
-- Popped window rounding.
hl.window_rule({ match = { tag = "pop" }, rounding = 8 })
-- Common app-controlled tags.
o.window({ tag = "pop" }, { rounding = 8 })
o.window({ tag = "noidle" }, { idle_inhibit = "always" })
-- Prevent idle while open.
hl.window_rule({ match = { tag = "noidle" }, idle_inhibit = "always" })
-- Disable animations for image selector overlay.
hl.layer_rule({ match = { namespace = "omarchy-image-selector" }, no_anim = true, animation = "none" })
+1 -1
View File
@@ -1,2 +1,2 @@
-- Prevent Telegram from stealing focus on new messages.
hl.window_rule({ match = { class = "org.telegram.desktop" }, focus_on_activate = false })
o.window("org.telegram.desktop", { focus_on_activate = false })
+2 -3
View File
@@ -1,4 +1,3 @@
-- Define terminal tag to style them uniformly.
hl.window_rule({ match = { class = "(Alacritty|kitty|com.mitchellh.ghostty|foot)" }, tag = "+terminal" })
hl.window_rule({ match = { tag = "terminal" }, tag = "-default-opacity" })
hl.window_rule({ match = { tag = "terminal" }, opacity = "0.97 0.9" })
o.window("(Alacritty|kitty|com.mitchellh.ghostty|foot)", { tag = "+terminal" })
o.window({ tag = "terminal" }, { tag = "-default-opacity", opacity = "0.97 0.9" })
+2 -2
View File
@@ -1,2 +1,2 @@
-- Float Typora print dialog.
hl.window_rule({ match = { class = "^Typora$", title = "^Print$" }, float = true, center = true })
-- Typora print dialog.
o.window({ class = "^Typora$", title = "^Print$" }, { float = true, center = true })
+1 -1
View File
@@ -1,2 +1,2 @@
-- Application-specific animation.
hl.layer_rule({ match = { namespace = "walker" }, no_anim = true })
hl.layer_rule({ match = { namespace = "walker" }, no_anim = true, animation = "none" })
+8 -6
View File
@@ -1,6 +1,8 @@
-- Webcam overlay for screen recording.
hl.window_rule({ match = { title = "WebcamOverlay" }, float = true })
hl.window_rule({ match = { title = "WebcamOverlay" }, pin = true })
hl.window_rule({ match = { title = "WebcamOverlay" }, no_initial_focus = true })
hl.window_rule({ match = { title = "WebcamOverlay" }, no_dim = true })
hl.window_rule({ match = { title = "WebcamOverlay" }, move = { "(monitor_w-window_w-40)", "(monitor_h-window_h-40)" } })
-- Webcam overlay window.
o.window({ title = "WebcamOverlay" }, {
float = true,
pin = true,
no_initial_focus = true,
no_dim = true,
move = { "(monitor_w-window_w-40)", "(monitor_h-window_h-40)" },
})
+14 -16
View File
@@ -1,18 +1,16 @@
hl.on("hyprland.start", function()
hl.exec_cmd("uwsm-app -- hypridle")
hl.exec_cmd("uwsm-app -- mako")
hl.exec_cmd("! omarchy-toggle-enabled waybar-off && uwsm-app -- waybar")
hl.exec_cmd("uwsm-app -- fcitx5 --disable notificationitem")
hl.exec_cmd("uwsm-app -- swaybg -i ~/.config/omarchy/current/background -m fill")
hl.exec_cmd("/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1")
hl.exec_cmd("omarchy-first-run")
hl.exec_cmd("omarchy-powerprofiles-init")
hl.exec_cmd("uwsm-app -- omarchy-hyprland-monitor-watch")
o.launch_on_start("hypridle")
o.launch_on_start("mako")
o.exec_on_start("! omarchy-toggle-enabled waybar-off && " .. o.launch("waybar"))
o.launch_on_start("fcitx5 --disable notificationitem")
o.launch_on_start("swaybg -i ~/.config/omarchy/current/background -m fill")
o.exec_on_start("/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1")
o.exec_on_start("omarchy-first-run")
o.exec_on_start("omarchy-powerprofiles-init")
o.launch_on_start("omarchy-hyprland-monitor-watch")
-- Slow app launch fix -- set systemd vars.
hl.exec_cmd("systemctl --user import-environment $(env | cut -d'=' -f 1)")
hl.exec_cmd("dbus-update-activation-environment --systemd --all")
-- Slow app launch fix -- set systemd vars.
o.exec_on_start("systemctl --user import-environment $(env | cut -d'=' -f 1)")
o.exec_on_start("dbus-update-activation-environment --systemd --all")
-- Run post-boot hooks after startup config has loaded.
hl.exec_cmd("sleep 2 && omarchy-hook post-boot")
end)
-- Run post-boot hooks after startup config has loaded.
o.exec_on_start("sleep 2 && omarchy-hook post-boot")
+16 -4
View File
@@ -1,4 +1,16 @@
hl.bind("SUPER + C", hl.dsp.send_shortcut({ mods = "CTRL", key = "Insert" }), { description = "Universal copy" })
hl.bind("SUPER + V", hl.dsp.send_shortcut({ mods = "SHIFT", key = "Insert" }), { description = "Universal paste" })
hl.bind("SUPER + X", hl.dsp.send_shortcut({ mods = "CTRL", key = "X" }), { description = "Universal cut" })
hl.bind("SUPER + CTRL + V", hl.dsp.exec_cmd("omarchy-launch-walker -m clipboard"), { description = "Clipboard manager" })
-- Work around Hyprland send_shortcut sometimes leaving synthetic key state stuck/repeating.
-- https://github.com/hyprwm/Hyprland/discussions/14099
local function send_shortcut_once(mods, key)
return function()
hl.dispatch(hl.dsp.send_key_state({ mods = mods, key = key, state = "down", window = "activewindow" }))
hl.timer(function()
hl.dispatch(hl.dsp.send_key_state({ mods = mods, key = key, state = "up", window = "activewindow" }))
end, { timeout = 50, type = "oneshot" })
end
end
o.bind("SUPER + C", "Universal copy", send_shortcut_once("CTRL", "Insert"))
o.bind("SUPER + V", "Universal paste", send_shortcut_once("SHIFT", "Insert"))
o.bind("SUPER + X", "Universal cut", send_shortcut_once("CTRL", "X"))
o.bind("SUPER + CTRL + V", "Clipboard manager", { omarchy = "walker -m clipboard" })
+23 -23
View File
@@ -1,29 +1,29 @@
-- Volume, brightness, keyboard backlight, and touchpad controls.
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("omarchy-swayosd-client --output-volume raise"), { locked = true, repeating = true, description = "Volume up" })
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("omarchy-swayosd-client --output-volume lower"), { locked = true, repeating = true, description = "Volume down" })
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("omarchy-swayosd-client --output-volume mute-toggle"), { locked = true, repeating = true, description = "Mute" })
hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("omarchy-audio-input-mute"), { locked = true, repeating = true, description = "Mute microphone" })
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("omarchy-brightness-display +5%"), { locked = true, repeating = true, description = "Brightness up" })
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("omarchy-brightness-display 5%-"), { locked = true, repeating = true, description = "Brightness down" })
hl.bind("SHIFT + XF86MonBrightnessUp", hl.dsp.exec_cmd("omarchy-brightness-display 100%"), { locked = true, repeating = true, description = "Brightness maximum" })
hl.bind("SHIFT + XF86MonBrightnessDown", hl.dsp.exec_cmd("omarchy-brightness-display 1%"), { locked = true, repeating = true, description = "Brightness minimum" })
hl.bind("XF86KbdBrightnessUp", hl.dsp.exec_cmd("omarchy-brightness-keyboard up"), { locked = true, repeating = true, description = "Keyboard brightness up" })
hl.bind("XF86KbdBrightnessDown", hl.dsp.exec_cmd("omarchy-brightness-keyboard down"), { locked = true, repeating = true, description = "Keyboard brightness down" })
hl.bind("XF86KbdLightOnOff", hl.dsp.exec_cmd("omarchy-brightness-keyboard cycle"), { locked = true, description = "Keyboard backlight cycle" })
hl.bind("XF86TouchpadToggle", hl.dsp.exec_cmd("omarchy-toggle-touchpad"), { locked = true, description = "Toggle touchpad" })
hl.bind("XF86TouchpadOn", hl.dsp.exec_cmd("omarchy-toggle-touchpad on"), { locked = true, description = "Enable touchpad" })
hl.bind("XF86TouchpadOff", hl.dsp.exec_cmd("omarchy-toggle-touchpad off"), { locked = true, description = "Disable touchpad" })
o.bind("XF86AudioRaiseVolume", "Volume up", "omarchy-swayosd-client --output-volume raise", { locked = true, repeating = true })
o.bind("XF86AudioLowerVolume", "Volume down", "omarchy-swayosd-client --output-volume lower", { locked = true, repeating = true })
o.bind("XF86AudioMute", "Mute", "omarchy-swayosd-client --output-volume mute-toggle", { locked = true, repeating = true })
o.bind("XF86AudioMicMute", "Mute microphone", "omarchy-audio-input-mute", { locked = true, repeating = true })
o.bind("XF86MonBrightnessUp", "Brightness up", "omarchy-brightness-display +5%", { locked = true, repeating = true })
o.bind("XF86MonBrightnessDown", "Brightness down", "omarchy-brightness-display 5%-", { locked = true, repeating = true })
o.bind("SHIFT + XF86MonBrightnessUp", "Brightness maximum", "omarchy-brightness-display 100%", { locked = true, repeating = true })
o.bind("SHIFT + XF86MonBrightnessDown", "Brightness minimum", "omarchy-brightness-display 1%", { locked = true, repeating = true })
o.bind("XF86KbdBrightnessUp", "Keyboard brightness up", "omarchy-brightness-keyboard up", { locked = true, repeating = true })
o.bind("XF86KbdBrightnessDown", "Keyboard brightness down", "omarchy-brightness-keyboard down", { locked = true, repeating = true })
o.bind("XF86KbdLightOnOff", "Keyboard backlight cycle", "omarchy-brightness-keyboard cycle", { locked = true })
o.bind("XF86TouchpadToggle", "Toggle touchpad", "omarchy-toggle-touchpad", { locked = true })
o.bind("XF86TouchpadOn", "Enable touchpad", "omarchy-toggle-touchpad on", { locked = true })
o.bind("XF86TouchpadOff", "Disable touchpad", "omarchy-toggle-touchpad off", { locked = true })
-- Precise volume and brightness controls.
hl.bind("ALT + XF86AudioRaiseVolume", hl.dsp.exec_cmd("omarchy-swayosd-client --output-volume +1"), { locked = true, repeating = true, description = "Volume up precise" })
hl.bind("ALT + XF86AudioLowerVolume", hl.dsp.exec_cmd("omarchy-swayosd-client --output-volume -1"), { locked = true, repeating = true, description = "Volume down precise" })
hl.bind("ALT + XF86MonBrightnessUp", hl.dsp.exec_cmd("omarchy-brightness-display +1%"), { locked = true, repeating = true, description = "Brightness up precise" })
hl.bind("ALT + XF86MonBrightnessDown", hl.dsp.exec_cmd("omarchy-brightness-display 1%-"), { locked = true, repeating = true, description = "Brightness down precise" })
o.bind("ALT + XF86AudioRaiseVolume", "Volume up precise", "omarchy-swayosd-client --output-volume +1", { locked = true, repeating = true })
o.bind("ALT + XF86AudioLowerVolume", "Volume down precise", "omarchy-swayosd-client --output-volume -1", { locked = true, repeating = true })
o.bind("ALT + XF86MonBrightnessUp", "Brightness up precise", "omarchy-brightness-display +1%", { locked = true, repeating = true })
o.bind("ALT + XF86MonBrightnessDown", "Brightness down precise", "omarchy-brightness-display 1%-", { locked = true, repeating = true })
-- Media controls.
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("omarchy-swayosd-client --playerctl next"), { locked = true, description = "Next track" })
hl.bind("XF86AudioPause", hl.dsp.exec_cmd("omarchy-swayosd-client --playerctl play-pause"), { locked = true, description = "Pause" })
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("omarchy-swayosd-client --playerctl play-pause"), { locked = true, description = "Play" })
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("omarchy-swayosd-client --playerctl previous"), { locked = true, description = "Previous track" })
o.bind("XF86AudioNext", "Next track", "omarchy-swayosd-client --playerctl next", { locked = true })
o.bind("XF86AudioPause", "Pause", "omarchy-swayosd-client --playerctl play-pause", { locked = true })
o.bind("XF86AudioPlay", "Play", "omarchy-swayosd-client --playerctl play-pause", { locked = true })
o.bind("XF86AudioPrev", "Previous track", "omarchy-swayosd-client --playerctl previous", { locked = true })
hl.bind("SUPER + XF86AudioMute", hl.dsp.exec_cmd("omarchy-audio-output-switch"), { locked = true, description = "Switch audio output" })
o.bind("SUPER + XF86AudioMute", "Switch audio output", "omarchy-audio-output-switch", { locked = true })
+67 -67
View File
@@ -1,93 +1,93 @@
hl.bind("SUPER + W", hl.dsp.window.close(), { description = "Close window" })
hl.bind("CTRL + ALT + DELETE", hl.dsp.exec_cmd("omarchy-hyprland-window-close-all"), { description = "Close all windows" })
o.bind("SUPER + W", "Close window", hl.dsp.window.close())
o.bind("CTRL + ALT + DELETE", "Close all windows", "omarchy-hyprland-window-close-all")
hl.bind("SUPER + J", hl.dsp.layout("togglesplit"), { description = "Toggle window split" })
hl.bind("SUPER + P", hl.dsp.window.pseudo(), { description = "Pseudo window" })
hl.bind("SUPER + T", hl.dsp.window.float({ action = "toggle" }), { description = "Toggle window floating/tiling" })
hl.bind("SUPER + F", hl.dsp.window.fullscreen({ mode = "fullscreen" }), { description = "Full screen" })
hl.bind("SUPER + CTRL + F", hl.dsp.window.fullscreen_state({ internal = 0, client = 2 }), { description = "Tiled full screen" })
hl.bind("SUPER + ALT + F", hl.dsp.window.fullscreen({ mode = "maximized" }), { description = "Full width" })
hl.bind("SUPER + O", hl.dsp.exec_cmd("omarchy-hyprland-window-pop"), { description = "Pop window out (float & pin)" })
hl.bind("SUPER + L", hl.dsp.exec_cmd("omarchy-hyprland-workspace-layout-toggle"), { description = "Toggle workspace layout" })
o.bind("SUPER + J", "Toggle window split", hl.dsp.layout("togglesplit"))
o.bind("SUPER + P", "Pseudo window", hl.dsp.window.pseudo())
o.bind("SUPER + T", "Toggle window floating/tiling", hl.dsp.window.float({ action = "toggle" }))
o.bind("SUPER + F", "Full screen", hl.dsp.window.fullscreen({ mode = "fullscreen" }))
o.bind("SUPER + CTRL + F", "Tiled full screen", hl.dsp.window.fullscreen_state({ internal = 0, client = 2 }))
o.bind("SUPER + ALT + F", "Full width", hl.dsp.window.fullscreen({ mode = "maximized" }))
o.bind("SUPER + O", "Pop window out (float & pin)", "omarchy-hyprland-window-pop")
o.bind("SUPER + L", "Toggle workspace layout", "omarchy-hyprland-workspace-layout-toggle")
hl.bind("SUPER + LEFT", hl.dsp.focus({ direction = "l" }), { description = "Focus on left window" })
hl.bind("SUPER + RIGHT", hl.dsp.focus({ direction = "r" }), { description = "Focus on right window" })
hl.bind("SUPER + UP", hl.dsp.focus({ direction = "u" }), { description = "Focus on above window" })
hl.bind("SUPER + DOWN", hl.dsp.focus({ direction = "d" }), { description = "Focus on below window" })
o.bind("SUPER + LEFT", "Focus on left window", hl.dsp.focus({ direction = "l" }))
o.bind("SUPER + RIGHT", "Focus on right window", hl.dsp.focus({ direction = "r" }))
o.bind("SUPER + UP", "Focus on above window", hl.dsp.focus({ direction = "u" }))
o.bind("SUPER + DOWN", "Focus on below window", hl.dsp.focus({ direction = "d" }))
for workspace = 1, 10 do
local key = "code:" .. tostring(workspace + 9)
hl.bind("SUPER + " .. key, hl.dsp.focus({ workspace = tostring(workspace) }), { description = "Switch to workspace " .. workspace })
hl.bind("SUPER + SHIFT + " .. key, hl.dsp.window.move({ workspace = tostring(workspace) }), { description = "Move window to workspace " .. workspace })
hl.bind("SUPER + SHIFT + ALT + " .. key, hl.dsp.window.move({ workspace = tostring(workspace), follow = false }), { description = "Move window silently to workspace " .. workspace })
o.bind("SUPER + " .. key, "Switch to workspace " .. workspace, hl.dsp.focus({ workspace = tostring(workspace) }))
o.bind("SUPER + SHIFT + " .. key, "Move window to workspace " .. workspace, hl.dsp.window.move({ workspace = tostring(workspace) }))
o.bind("SUPER + SHIFT + ALT + " .. key, "Move window silently to workspace " .. workspace, hl.dsp.window.move({ workspace = tostring(workspace), follow = false }))
end
hl.bind("SUPER + S", hl.dsp.workspace.toggle_special("scratchpad"), { description = "Toggle scratchpad" })
hl.bind("SUPER + ALT + S", hl.dsp.window.move({ workspace = "special:scratchpad", follow = false }), { description = "Move window to scratchpad" })
o.bind("SUPER + S", "Toggle scratchpad", hl.dsp.workspace.toggle_special("scratchpad"))
o.bind("SUPER + ALT + S", "Move window to scratchpad", hl.dsp.window.move({ workspace = "special:scratchpad", follow = false }))
hl.bind("SUPER + TAB", hl.dsp.focus({ workspace = "e+1" }), { description = "Next workspace" })
hl.bind("SUPER + SHIFT + TAB", hl.dsp.focus({ workspace = "e-1" }), { description = "Previous workspace" })
hl.bind("SUPER + CTRL + TAB", hl.dsp.focus({ workspace = "previous" }), { description = "Former workspace" })
o.bind("SUPER + TAB", "Next workspace", hl.dsp.focus({ workspace = "e+1" }))
o.bind("SUPER + SHIFT + TAB", "Previous workspace", hl.dsp.focus({ workspace = "e-1" }))
o.bind("SUPER + CTRL + TAB", "Former workspace", hl.dsp.focus({ workspace = "previous" }))
hl.bind("SUPER + SHIFT + ALT + LEFT", hl.dsp.workspace.move({ monitor = "l" }), { description = "Move workspace to left monitor" })
hl.bind("SUPER + SHIFT + ALT + RIGHT", hl.dsp.workspace.move({ monitor = "r" }), { description = "Move workspace to right monitor" })
hl.bind("SUPER + SHIFT + ALT + UP", hl.dsp.workspace.move({ monitor = "u" }), { description = "Move workspace to up monitor" })
hl.bind("SUPER + SHIFT + ALT + DOWN", hl.dsp.workspace.move({ monitor = "d" }), { description = "Move workspace to down monitor" })
o.bind("SUPER + SHIFT + ALT + LEFT", "Move workspace to left monitor", hl.dsp.workspace.move({ monitor = "l" }))
o.bind("SUPER + SHIFT + ALT + RIGHT", "Move workspace to right monitor", hl.dsp.workspace.move({ monitor = "r" }))
o.bind("SUPER + SHIFT + ALT + UP", "Move workspace to up monitor", hl.dsp.workspace.move({ monitor = "u" }))
o.bind("SUPER + SHIFT + ALT + DOWN", "Move workspace to down monitor", hl.dsp.workspace.move({ monitor = "d" }))
hl.bind("SUPER + SHIFT + LEFT", hl.dsp.window.swap({ direction = "l" }), { description = "Swap window to the left" })
hl.bind("SUPER + SHIFT + RIGHT", hl.dsp.window.swap({ direction = "r" }), { description = "Swap window to the right" })
hl.bind("SUPER + SHIFT + UP", hl.dsp.window.swap({ direction = "u" }), { description = "Swap window up" })
hl.bind("SUPER + SHIFT + DOWN", hl.dsp.window.swap({ direction = "d" }), { description = "Swap window down" })
o.bind("SUPER + SHIFT + LEFT", "Swap window to the left", hl.dsp.window.swap({ direction = "l" }))
o.bind("SUPER + SHIFT + RIGHT", "Swap window to the right", hl.dsp.window.swap({ direction = "r" }))
o.bind("SUPER + SHIFT + UP", "Swap window up", hl.dsp.window.swap({ direction = "u" }))
o.bind("SUPER + SHIFT + DOWN", "Swap window down", hl.dsp.window.swap({ direction = "d" }))
hl.bind("ALT + TAB", hl.dsp.window.cycle_next(), { description = "Focus on next window" })
hl.bind("ALT + SHIFT + TAB", hl.dsp.window.cycle_next({ next = false }), { description = "Focus on previous window" })
hl.bind("ALT + TAB", hl.dsp.window.bring_to_top(), { description = "Reveal active window on top" })
hl.bind("ALT + SHIFT + TAB", hl.dsp.window.bring_to_top(), { description = "Reveal active window on top" })
o.bind("ALT + TAB", "Focus on next window", hl.dsp.window.cycle_next())
o.bind("ALT + SHIFT + TAB", "Focus on previous window", hl.dsp.window.cycle_next({ next = false }))
o.bind("ALT + TAB", "Reveal active window on top", hl.dsp.window.bring_to_top())
o.bind("ALT + SHIFT + TAB", "Reveal active window on top", hl.dsp.window.bring_to_top())
hl.bind("CTRL + ALT + TAB", hl.dsp.focus({ monitor = "+1" }), { description = "Focus on next monitor" })
hl.bind("CTRL + ALT + SHIFT + TAB", hl.dsp.focus({ monitor = "-1" }), { description = "Focus on previous monitor" })
o.bind("CTRL + ALT + TAB", "Focus on next monitor", hl.dsp.focus({ monitor = "+1" }))
o.bind("CTRL + ALT + SHIFT + TAB", "Focus on previous monitor", hl.dsp.focus({ monitor = "-1" }))
hl.bind("SUPER + code:20", hl.dsp.window.resize({ x = -100, y = 0, relative = true }), { description = "Expand window left" })
hl.bind("SUPER + code:21", hl.dsp.window.resize({ x = 100, y = 0, relative = true }), { description = "Shrink window left" })
hl.bind("SUPER + SHIFT + code:20", hl.dsp.window.resize({ x = 0, y = -100, relative = true }), { description = "Shrink window up" })
hl.bind("SUPER + SHIFT + code:21", hl.dsp.window.resize({ x = 0, y = 100, relative = true }), { description = "Expand window down" })
o.bind("SUPER + code:20", "Expand window left", hl.dsp.window.resize({ x = -100, y = 0, relative = true }))
o.bind("SUPER + code:21", "Shrink window left", hl.dsp.window.resize({ x = 100, y = 0, relative = true }))
o.bind("SUPER + SHIFT + code:20", "Shrink window up", hl.dsp.window.resize({ x = 0, y = -100, relative = true }))
o.bind("SUPER + SHIFT + code:21", "Expand window down", hl.dsp.window.resize({ x = 0, y = 100, relative = true }))
hl.bind("SUPER + ALT + code:20", hl.dsp.window.resize({ x = -25, y = 0, relative = true }), { description = "Expand window left a little" })
hl.bind("SUPER + ALT + code:21", hl.dsp.window.resize({ x = 25, y = 0, relative = true }), { description = "Shrink window left a little" })
hl.bind("SUPER + SHIFT + ALT + code:20", hl.dsp.window.resize({ x = 0, y = -25, relative = true }), { description = "Shrink window up a little" })
hl.bind("SUPER + SHIFT + ALT + code:21", hl.dsp.window.resize({ x = 0, y = 25, relative = true }), { description = "Expand window down a little" })
o.bind("SUPER + ALT + code:20", "Expand window left a little", hl.dsp.window.resize({ x = -25, y = 0, relative = true }))
o.bind("SUPER + ALT + code:21", "Shrink window left a little", hl.dsp.window.resize({ x = 25, y = 0, relative = true }))
o.bind("SUPER + SHIFT + ALT + code:20", "Shrink window up a little", hl.dsp.window.resize({ x = 0, y = -25, relative = true }))
o.bind("SUPER + SHIFT + ALT + code:21", "Expand window down a little", hl.dsp.window.resize({ x = 0, y = 25, relative = true }))
hl.bind("SUPER + CTRL + code:20", hl.dsp.window.resize({ x = -300, y = 0, relative = true }), { description = "Expand window left a lot" })
hl.bind("SUPER + CTRL + code:21", hl.dsp.window.resize({ x = 300, y = 0, relative = true }), { description = "Shrink window left a lot" })
hl.bind("SUPER + CTRL + SHIFT + code:20", hl.dsp.window.resize({ x = 0, y = -300, relative = true }), { description = "Shrink window up a lot" })
hl.bind("SUPER + CTRL + SHIFT + code:21", hl.dsp.window.resize({ x = 0, y = 300, relative = true }), { description = "Expand window down a lot" })
o.bind("SUPER + CTRL + code:20", "Expand window left a lot", hl.dsp.window.resize({ x = -300, y = 0, relative = true }))
o.bind("SUPER + CTRL + code:21", "Shrink window left a lot", hl.dsp.window.resize({ x = 300, y = 0, relative = true }))
o.bind("SUPER + CTRL + SHIFT + code:20", "Shrink window up a lot", hl.dsp.window.resize({ x = 0, y = -300, relative = true }))
o.bind("SUPER + CTRL + SHIFT + code:21", "Expand window down a lot", hl.dsp.window.resize({ x = 0, y = 300, relative = true }))
hl.bind("SUPER + mouse_down", hl.dsp.focus({ workspace = "e+1" }), { description = "Scroll active workspace forward" })
hl.bind("SUPER + mouse_up", hl.dsp.focus({ workspace = "e-1" }), { description = "Scroll active workspace backward" })
o.bind("SUPER + mouse_down", "Scroll active workspace forward", hl.dsp.focus({ workspace = "e+1" }))
o.bind("SUPER + mouse_up", "Scroll active workspace backward", hl.dsp.focus({ workspace = "e-1" }))
hl.bind("SUPER + mouse:272", hl.dsp.window.drag(), { mouse = true, description = "Move window" })
hl.bind("SUPER + mouse:273", hl.dsp.window.resize(), { mouse = true, description = "Resize window" })
o.bind("SUPER + mouse:272", "Move window", hl.dsp.window.drag(), { mouse = true })
o.bind("SUPER + mouse:273", "Resize window", hl.dsp.window.resize(), { mouse = true })
hl.bind("SUPER + G", hl.dsp.group.toggle(), { description = "Toggle window grouping" })
hl.bind("SUPER + ALT + G", hl.dsp.window.move({ out_of_group = true }), { description = "Move active window out of group" })
o.bind("SUPER + G", "Toggle window grouping", hl.dsp.group.toggle())
o.bind("SUPER + ALT + G", "Move active window out of group", hl.dsp.window.move({ out_of_group = true }))
hl.bind("SUPER + ALT + LEFT", hl.dsp.window.move({ into_group = "l" }), { description = "Move window to group on left" })
hl.bind("SUPER + ALT + RIGHT", hl.dsp.window.move({ into_group = "r" }), { description = "Move window to group on right" })
hl.bind("SUPER + ALT + UP", hl.dsp.window.move({ into_group = "u" }), { description = "Move window to group on top" })
hl.bind("SUPER + ALT + DOWN", hl.dsp.window.move({ into_group = "d" }), { description = "Move window to group on bottom" })
o.bind("SUPER + ALT + LEFT", "Move window to group on left", hl.dsp.window.move({ into_group = "l" }))
o.bind("SUPER + ALT + RIGHT", "Move window to group on right", hl.dsp.window.move({ into_group = "r" }))
o.bind("SUPER + ALT + UP", "Move window to group on top", hl.dsp.window.move({ into_group = "u" }))
o.bind("SUPER + ALT + DOWN", "Move window to group on bottom", hl.dsp.window.move({ into_group = "d" }))
hl.bind("SUPER + ALT + TAB", hl.dsp.group.next(), { description = "Next window in group" })
hl.bind("SUPER + ALT + SHIFT + TAB", hl.dsp.group.prev(), { description = "Previous window in group" })
o.bind("SUPER + ALT + TAB", "Next window in group", hl.dsp.group.next())
o.bind("SUPER + ALT + SHIFT + TAB", "Previous window in group", hl.dsp.group.prev())
hl.bind("SUPER + CTRL + LEFT", hl.dsp.group.prev(), { description = "Move grouped window focus left" })
hl.bind("SUPER + CTRL + RIGHT", hl.dsp.group.next(), { description = "Move grouped window focus right" })
o.bind("SUPER + CTRL + LEFT", "Move grouped window focus left", hl.dsp.group.prev())
o.bind("SUPER + CTRL + RIGHT", "Move grouped window focus right", hl.dsp.group.next())
hl.bind("SUPER + ALT + mouse_down", hl.dsp.group.next(), { description = "Next window in group" })
hl.bind("SUPER + ALT + mouse_up", hl.dsp.group.prev(), { description = "Previous window in group" })
o.bind("SUPER + ALT + mouse_down", "Next window in group", hl.dsp.group.next())
o.bind("SUPER + ALT + mouse_up", "Previous window in group", hl.dsp.group.prev())
for index = 1, 5 do
hl.bind("SUPER + ALT + code:" .. tostring(index + 9), hl.dsp.group.active({ index = index }), { description = "Switch to group window " .. index })
o.bind("SUPER + ALT + code:" .. tostring(index + 9), "Switch to group window " .. index, hl.dsp.group.active({ index = index }))
end
hl.bind("SUPER + code:61", hl.dsp.exec_cmd("omarchy-hyprland-monitor-scaling-cycle"), { description = "Cycle monitor scaling" })
hl.bind("SUPER + ALT + code:61", hl.dsp.exec_cmd("omarchy-hyprland-monitor-scaling-cycle --reverse"), { description = "Cycle monitor scaling backwards" })
o.bind("SUPER + code:61", "Cycle monitor scaling", "omarchy-hyprland-monitor-scaling-cycle")
o.bind("SUPER + ALT + code:61", "Cycle monitor scaling backwards", "omarchy-hyprland-monitor-scaling-cycle --reverse")
+57 -56
View File
@@ -1,72 +1,73 @@
hl.bind("SUPER + SPACE", hl.dsp.exec_cmd("omarchy-launch-walker"), { description = "Launch apps" })
hl.bind("SUPER + CTRL + E", hl.dsp.exec_cmd("omarchy-launch-walker -m symbols"), { description = "Emoji picker" })
hl.bind("SUPER + CTRL + C", hl.dsp.exec_cmd("omarchy-menu capture"), { description = "Capture menu" })
hl.bind("SUPER + CTRL + O", hl.dsp.exec_cmd("omarchy-menu toggle"), { description = "Toggle menu" })
hl.bind("SUPER + CTRL + H", hl.dsp.exec_cmd("omarchy-menu hardware"), { description = "Hardware menu" })
hl.bind("SUPER + ALT + SPACE", hl.dsp.exec_cmd("omarchy-menu"), { description = "Omarchy menu" })
hl.bind("SUPER + SHIFT + code:201", hl.dsp.exec_cmd("omarchy-menu"), { description = "Omarchy menu" })
hl.bind("SUPER + ESCAPE", hl.dsp.exec_cmd("omarchy-menu system"), { description = "System menu" })
hl.bind("XF86PowerOff", hl.dsp.exec_cmd("omarchy-menu system"), { locked = true, description = "Power menu" })
hl.bind("SUPER + K", hl.dsp.exec_cmd("omarchy-menu-keybindings"), { description = "Show key bindings" })
hl.bind("XF86Calculator", hl.dsp.exec_cmd("gnome-calculator"), { description = "Calculator" })
o.bind("SUPER + SPACE", "Launch apps", { omarchy = "walker" })
o.bind("SUPER + CTRL + E", "Emoji picker", { omarchy = "walker -m symbols" })
o.bind_menu("SUPER + CTRL + C", "Capture menu", "capture")
o.bind_menu("SUPER + CTRL + O", "Toggle menu", "toggle")
o.bind_menu("SUPER + CTRL + H", "Hardware menu", "hardware")
o.bind_menu("SUPER + ALT + SPACE", "Omarchy menu", nil)
o.bind_menu("SUPER + SHIFT + code:201", "Omarchy menu", nil)
o.bind_menu("SUPER + ESCAPE", "System menu", "system")
o.bind_menu("XF86PowerOff", "Power menu", "system", { locked = true })
o.bind("SUPER + K", "Show key bindings", "omarchy-menu-keybindings")
o.bind("SUPER + ALT + K", "Show Tmux key bindings", "omarchy-menu-tmux-keybindings")
o.bind("XF86Calculator", "Calculator", "gnome-calculator")
hl.bind("SUPER + SHIFT + SPACE", hl.dsp.exec_cmd("omarchy-toggle-waybar"), { description = "Toggle top bar" })
hl.bind("SUPER + SHIFT + CTRL + UP", hl.dsp.exec_cmd("omarchy-style-waybar-position top"), { description = "Move Waybar to top" })
hl.bind("SUPER + SHIFT + CTRL + DOWN", hl.dsp.exec_cmd("omarchy-style-waybar-position bottom"), { description = "Move Waybar to bottom" })
hl.bind("SUPER + SHIFT + CTRL + LEFT", hl.dsp.exec_cmd("omarchy-style-waybar-position left"), { description = "Move Waybar to left" })
hl.bind("SUPER + SHIFT + CTRL + RIGHT", hl.dsp.exec_cmd("omarchy-style-waybar-position right"), { description = "Move Waybar to right" })
hl.bind("SUPER + CTRL + SPACE", hl.dsp.exec_cmd("omarchy-menu background"), { description = "Theme background menu" })
hl.bind("SUPER + SHIFT + CTRL + SPACE", hl.dsp.exec_cmd("omarchy-menu theme"), { description = "Theme menu" })
hl.bind("SUPER + BACKSPACE", hl.dsp.exec_cmd("omarchy-hyprland-window-transparency-toggle"), { description = "Toggle window transparency" })
hl.bind("SUPER + SHIFT + BACKSPACE", hl.dsp.exec_cmd("omarchy-hyprland-window-gaps-toggle"), { description = "Toggle window gaps" })
hl.bind("SUPER + CTRL + BACKSPACE", hl.dsp.exec_cmd("omarchy-hyprland-window-single-square-aspect-toggle"), { description = "Toggle single-window square aspect" })
o.bind("SUPER + SHIFT + SPACE", "Toggle top bar", "omarchy-toggle-waybar")
o.bind("SUPER + SHIFT + CTRL + UP", "Move Waybar to top", "omarchy-style-waybar-position top")
o.bind("SUPER + SHIFT + CTRL + DOWN", "Move Waybar to bottom", "omarchy-style-waybar-position bottom")
o.bind("SUPER + SHIFT + CTRL + LEFT", "Move Waybar to left", "omarchy-style-waybar-position left")
o.bind("SUPER + SHIFT + CTRL + RIGHT", "Move Waybar to right", "omarchy-style-waybar-position right")
o.bind_menu("SUPER + CTRL + SPACE", "Background switcher", "background")
o.bind_menu("SUPER + SHIFT + CTRL + SPACE", "Theme menu", "theme")
o.bind("SUPER + BACKSPACE", "Toggle window transparency", "omarchy-hyprland-window-transparency-toggle")
o.bind("SUPER + SHIFT + BACKSPACE", "Toggle window gaps", "omarchy-hyprland-window-gaps-toggle")
o.bind("SUPER + CTRL + BACKSPACE", "Toggle single-window square aspect", "omarchy-hyprland-window-single-square-aspect-toggle")
hl.bind("SUPER + COMMA", hl.dsp.exec_cmd("makoctl dismiss"), { description = "Dismiss last notification" })
hl.bind("SUPER + SHIFT + COMMA", hl.dsp.exec_cmd("makoctl dismiss --all"), { description = "Dismiss all notifications" })
hl.bind("SUPER + CTRL + COMMA", hl.dsp.exec_cmd("omarchy-toggle-notification-silencing"), { description = "Toggle silencing notifications" })
hl.bind("SUPER + ALT + COMMA", hl.dsp.exec_cmd("makoctl invoke"), { description = "Invoke last notification" })
hl.bind("SUPER + SHIFT + ALT + COMMA", hl.dsp.exec_cmd("makoctl restore"), { description = "Restore last notification" })
o.bind("SUPER + COMMA", "Dismiss last notification", "makoctl dismiss")
o.bind("SUPER + SHIFT + COMMA", "Dismiss all notifications", "makoctl dismiss --all")
o.bind("SUPER + CTRL + COMMA", "Toggle silencing notifications", "omarchy-toggle-notification-silencing")
o.bind("SUPER + ALT + COMMA", "Invoke last notification", "makoctl invoke")
o.bind("SUPER + SHIFT + ALT + COMMA", "Restore last notification", "makoctl restore")
hl.bind("SUPER + CTRL + I", hl.dsp.exec_cmd("omarchy-toggle-idle"), { description = "Toggle locking on idle" })
hl.bind("SUPER + CTRL + N", hl.dsp.exec_cmd("omarchy-toggle-nightlight"), { description = "Toggle nightlight" })
hl.bind("SUPER + CTRL + Delete", hl.dsp.exec_cmd("omarchy-hyprland-monitor-internal toggle"), { description = "Toggle laptop display" })
hl.bind("SUPER + CTRL + ALT + Delete", hl.dsp.exec_cmd("omarchy-hyprland-monitor-internal-mirror toggle"), { description = "Toggle laptop display mirroring" })
hl.bind("switch:on:Lid Switch", hl.dsp.exec_cmd("omarchy-hw-external-monitors && omarchy-hyprland-monitor-internal off"), { locked = true })
hl.bind("switch:off:Lid Switch", hl.dsp.exec_cmd("omarchy-hyprland-monitor-internal on"), { locked = true })
o.bind_toggle("SUPER + CTRL + I", "Toggle locking on idle", "idle")
o.bind_toggle("SUPER + CTRL + N", "Toggle nightlight", "nightlight")
o.bind("SUPER + CTRL + Delete", "Toggle laptop display", "omarchy-hyprland-monitor-internal toggle")
o.bind("SUPER + CTRL + ALT + Delete", "Toggle laptop display mirroring", "omarchy-hyprland-monitor-internal-mirror toggle")
o.bind("switch:on:Lid Switch", nil, "omarchy-hw-external-monitors && omarchy-hyprland-monitor-internal off", { locked = true })
o.bind("switch:off:Lid Switch", nil, "omarchy-hyprland-monitor-internal on", { locked = true })
hl.bind("PRINT", hl.dsp.exec_cmd("omarchy-capture-screenshot"), { description = "Screenshot" })
hl.bind("ALT + PRINT", hl.dsp.exec_cmd("omarchy-menu screenrecord"), { description = "Screenrecording" })
hl.bind("SUPER + PRINT", hl.dsp.exec_cmd("pkill hyprpicker || hyprpicker -a"), { description = "Color picker" })
hl.bind("SUPER + CTRL + PRINT", hl.dsp.exec_cmd("omarchy-capture-text-extraction"), { description = "Extract text (OCR) from screenshot" })
o.bind("PRINT", "Screenshot", "omarchy-capture-screenshot")
o.bind_menu("ALT + PRINT", "Screenrecording", "screenrecord")
o.bind("SUPER + PRINT", "Color picker", "pkill hyprpicker || hyprpicker -a")
o.bind("SUPER + CTRL + PRINT", "Extract text (OCR) from screenshot", "omarchy-capture-text-extraction")
hl.bind("SUPER + CTRL + S", hl.dsp.exec_cmd("omarchy-menu share"), { description = "Share" })
o.bind_menu("SUPER + CTRL + S", "Share", "share")
hl.bind("SUPER + CTRL + PERIOD", hl.dsp.exec_cmd("omarchy-transcode"), { description = "Transcode" })
o.bind("SUPER + CTRL + PERIOD", "Transcode", "omarchy-transcode")
hl.bind("SUPER + CTRL + R", hl.dsp.exec_cmd("omarchy-menu reminder-set"), { description = "Set reminder" })
hl.bind("SUPER + CTRL + ALT + R", hl.dsp.exec_cmd("omarchy-reminder show"), { description = "Show reminders" })
hl.bind("SUPER + SHIFT + CTRL + R", hl.dsp.exec_cmd("omarchy-reminder clear"), { description = "Clear reminders" })
o.bind_menu("SUPER + CTRL + R", "Set reminder", "reminder-set")
o.bind("SUPER + CTRL + ALT + R", "Show reminders", "omarchy-reminder show")
o.bind("SUPER + SHIFT + CTRL + R", "Clear reminders", "omarchy-reminder clear")
hl.bind("SUPER + CTRL + ALT + T", hl.dsp.exec_cmd([[notify-send -u low " $(date +"%A %H:%M · %d %B %Y · Week %V")"]]), { description = "Show time" })
hl.bind("SUPER + CTRL + ALT + B", hl.dsp.exec_cmd([[notify-send -u low "$(omarchy-battery-status)"]]), { description = "Show battery remaining" })
hl.bind("SUPER + CTRL + ALT + W", hl.dsp.exec_cmd([[notify-send -u low "$(omarchy-weather-status)"]]), { description = "Show weather" })
o.bind("SUPER + CTRL + ALT + T", "Show time", "omarchy-notification-time")
o.bind("SUPER + CTRL + ALT + B", "Show battery remaining", "omarchy-notification-battery")
o.bind("SUPER + CTRL + ALT + W", "Show weather", "omarchy-notification-weather")
hl.bind("SUPER + CTRL + A", hl.dsp.exec_cmd("omarchy-launch-audio"), { description = "Audio controls" })
hl.bind("SUPER + CTRL + B", hl.dsp.exec_cmd("omarchy-launch-bluetooth"), { description = "Bluetooth controls" })
hl.bind("SUPER + CTRL + W", hl.dsp.exec_cmd("omarchy-launch-wifi"), { description = "Wifi controls" })
hl.bind("SUPER + CTRL + T", hl.dsp.exec_cmd("omarchy-launch-tui btop"), { description = "Activity" })
o.bind("SUPER + CTRL + A", "Audio controls", { omarchy = "audio" })
o.bind("SUPER + CTRL + B", "Bluetooth controls", { omarchy = "bluetooth" })
o.bind("SUPER + CTRL + W", "Wifi controls", { omarchy = "wifi" })
o.bind("SUPER + CTRL + T", "Activity", { tui = "btop" })
hl.bind("SUPER + CTRL + X", hl.dsp.exec_cmd("voxtype record toggle"), { description = "Toggle dictation" })
hl.bind("F9", hl.dsp.exec_cmd("voxtype record start"), { description = "Start dictation (push-to-talk)" })
hl.bind("F9", hl.dsp.exec_cmd("voxtype record stop"), { release = true, description = "Stop dictation (push-to-talk)" })
o.bind("SUPER + CTRL + X", "Toggle dictation", "voxtype record toggle")
o.bind("F9", "Start dictation (push-to-talk)", "voxtype record start")
o.bind("F9", "Stop dictation (push-to-talk)", "voxtype record stop", { release = true })
hl.bind("SUPER + CTRL + Z", function()
o.bind("SUPER + CTRL + Z", "Zoom in", function()
local zoom = hl.get_config("cursor.zoom_factor") or 1
hl.config({ cursor = { zoom_factor = zoom + 1 } })
end, { description = "Zoom in" })
end)
hl.bind("SUPER + CTRL + ALT + Z", function()
o.bind("SUPER + CTRL + ALT + Z", "Reset zoom", function()
hl.config({ cursor = { zoom_factor = 1 } })
end, { description = "Reset zoom" })
end)
hl.bind("SUPER + CTRL + L", hl.dsp.exec_cmd("omarchy-system-lock"), { description = "Lock system" })
o.bind("SUPER + CTRL + L", "Lock system", "omarchy-system-lock")
+103
View File
@@ -0,0 +1,103 @@
-- Shared helpers for Hyprland Lua configuration.
o = o or {}
local function shell_quote(value)
return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
end
local function command_from(value, description)
if type(value) ~= "table" then
return value
end
if value.omarchy then
return "omarchy-launch-" .. value.omarchy
elseif value.focus and value.launch then
return o.launch_sole(value.focus, value.launch)
elseif value.launch then
return o.launch(value.launch)
elseif value.webapp then
if value.focus then
return o.launch_webapp_sole(description, value.webapp)
else
return o.launch_webapp(value.webapp)
end
elseif value.tui then
if value.focus then
return "omarchy-launch-or-focus-tui " .. shell_quote(value.tui)
else
return "omarchy-launch-tui " .. shell_quote(value.tui)
end
end
return value
end
function o.bind(keys, description, dispatcher, options)
local opts = options or {}
if description then
opts.description = description
end
dispatcher = command_from(dispatcher, description)
if type(dispatcher) == "string" then
dispatcher = hl.dsp.exec_cmd(dispatcher)
end
hl.bind(keys, dispatcher, opts)
end
function o.launch(command)
return "uwsm-app -- " .. command
end
function o.exec_on_start(command)
hl.on("hyprland.start", function()
hl.exec_cmd(command)
end)
end
function o.launch_on_start(command)
o.exec_on_start(o.launch(command))
end
function o.launch_webapp(url)
return "omarchy-launch-webapp " .. shell_quote(url)
end
function o.launch_webapp_sole(name, url)
return "omarchy-launch-or-focus-webapp " .. shell_quote(name) .. " " .. shell_quote(url)
end
function o.launch_sole(match, command)
return "omarchy-launch-or-focus " .. shell_quote(match) .. " " .. shell_quote(o.launch(command))
end
function o.bind_menu(keys, description, menu, options)
o.bind(keys, description, menu and ("omarchy-menu " .. menu) or "omarchy-menu", options)
end
function o.bind_toggle(keys, description, toggle, options)
o.bind(keys, description, "omarchy-toggle-" .. toggle, options)
end
function o.notify(message)
return "notify-send -u low " .. shell_quote(message)
end
function o.window(match, rules)
rules.match = rules.match or {}
if type(match) == "string" then
rules.match.class = match
else
for key, value in pairs(match) do
rules.match[key] = value
end
end
hl.window_rule(rules)
end
+24
View File
@@ -0,0 +1,24 @@
-- Omarchy Hyprland setup: helpers, defaults, and current theme overrides.
require("default.hypr.helpers")
-- Use Omarchy defaults, but don't edit these directly.
require("default.hypr.autostart")
require("default.hypr.bindings.media")
require("default.hypr.bindings.clipboard")
require("default.hypr.bindings.tiling-v2")
require("default.hypr.bindings.utilities")
require("default.hypr.envs")
require("default.hypr.looknfeel")
require("default.hypr.input")
require("default.hypr.windows")
-- Current theme overrides.
do
local paths = require("default.hypr.paths")
local theme = io.open(paths.config_home .. "/omarchy/current/theme/hyprland.lua", "r")
if theme then
theme:close()
require("omarchy.current.theme.hyprland")
end
end
+1 -1
View File
@@ -2,7 +2,7 @@
-- Lua files loaded with require() have separate local scopes, so modules that
-- need these paths import this table instead of repeating os.getenv() lookups.
local home = os.getenv("HOME") or ""
local home = os.getenv("HOME")
return {
home = home,
+7 -7
View File
@@ -4,10 +4,10 @@ require("default.hypr.bindings.tiling-v2")
require("default.hypr.bindings.utilities")
-- Application bindings without Omarchy's preinstalled web apps, TUIs, or desktop apps.
hl.bind("SUPER + RETURN", hl.dsp.exec_cmd([[uwsm-app -- xdg-terminal-exec --dir="$(omarchy-cmd-terminal-cwd)"]]), { description = "Terminal" })
hl.bind("SUPER + SHIFT + RETURN", hl.dsp.exec_cmd("omarchy-launch-browser"), { description = "Browser" })
hl.bind("SUPER + SHIFT + F", hl.dsp.exec_cmd("uwsm-app -- nautilus --new-window"), { description = "File manager" })
hl.bind("SUPER + ALT + SHIFT + F", hl.dsp.exec_cmd([[uwsm-app -- nautilus --new-window "$(omarchy-cmd-terminal-cwd)"]]), { description = "File manager (cwd)" })
hl.bind("SUPER + SHIFT + B", hl.dsp.exec_cmd("omarchy-launch-browser"), { description = "Browser" })
hl.bind("SUPER + SHIFT + ALT + B", hl.dsp.exec_cmd("omarchy-launch-browser --private"), { description = "Browser (private)" })
hl.bind("SUPER + SHIFT + N", hl.dsp.exec_cmd("omarchy-launch-editor"), { description = "Editor" })
o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" })
o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" })
o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" })
o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" })
o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" })
o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" })
o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" })
@@ -1,4 +0,0 @@
decoration {
rounding = 6
rounding_power = 3
}
+7
View File
@@ -0,0 +1,7 @@
-- Use round window corners.
hl.config({
decoration = {
rounding = 6,
rounding_power = 3,
},
})
+3 -3
View File
@@ -1,9 +1,9 @@
-- See https://wiki.hypr.land/Configuring/Basics/Window-Rules/
hl.window_rule({ match = { class = ".*" }, suppress_event = "maximize" })
o.window(".*", { suppress_event = "maximize" })
-- Tag all windows for default opacity (apps can override with -default-opacity tag).
hl.window_rule({ match = { class = ".*" }, tag = "+default-opacity" })
o.window(".*", { tag = "+default-opacity" })
-- Fix some dragging issues with XWayland.
hl.window_rule({
@@ -22,4 +22,4 @@ hl.window_rule({
require("default.hypr.apps")
-- Apply default opacity after apps have had a chance to opt out.
hl.window_rule({ match = { tag = "default-opacity" }, opacity = "0.97 0.9" })
o.window({ tag = "default-opacity" }, { opacity = "0.97 0.9" })
+3 -3
View File
@@ -6,7 +6,7 @@ description: >
~/.config/alacritty/, ~/.config/foot/, ~/.config/kitty/, ~/.config/ghostty/, ~/.config/mako/,
or ~/.config/omarchy/. Triggers: Hyprland, window rules, animations, keybindings,
monitors, gaps, borders, blur, opacity, waybar, walker, terminal config, themes,
wallpaper, night light, idle, lock screen, screenshots, reminders, layer rules,
background, night light, idle, lock screen, screenshots, reminders, layer rules,
workspace settings, display config, and user-facing omarchy commands. Excludes Omarchy
source development in ~/.local/share/omarchy/ and `omarchy dev` workflows.
---
@@ -28,7 +28,7 @@ It is not for contributing to Omarchy source code.
- Editing ANY file in `~/.config/omarchy/`
- Window behavior, animations, opacity, blur, gaps, borders
- Layer rules, workspace settings, display/monitor configuration
- Themes, wallpapers, fonts, appearance changes
- Themes, backgrounds, fonts, appearance changes
- User-facing `omarchy` commands (`omarchy theme ...`, `omarchy refresh ...`, `omarchy restart ...`, etc.)
- Screenshots, screen recording, reminders, night light, idle behavior, lock screen
@@ -254,7 +254,7 @@ omarchy refresh hyprland
omarchy theme list # Show available themes
omarchy theme current # Show current theme
omarchy theme set <name> # Apply theme (use "Tokyo Night" not "tokyo-night")
omarchy theme bg next # Cycle wallpaper
omarchy theme bg next # Cycle background
omarchy theme install <url> # Install from git repo
```
+333
View File
@@ -0,0 +1,333 @@
{
// Omarchy menu definition.
// JSONC is used for Neovim-friendly highlighting, comments, and trailing commas.
// IDs are object keys. Dotted IDs imply hierarchy: trigger.share.file belongs
// under trigger.share.
// Kind is inferred: action -> action, target -> link, otherwise submenu.
// Dotted IDs define the tree. Use provider:"name" only when the submenu
// calls provider_name() or a command named "name" to return JSON rows.
// Optional fields:
// aliases alternate `omarchy-menu <name>` routes; also searchable
// keywords extra search terms beyond id/label/aliases
// when shell condition; hide row when it fails
// checked shell condition; append ✓ when it succeeds
// Root Menu
"apps": {"icon":"󰀻","label":"Apps","aliases":["app","applications"],"keywords":"launch launcher","action":"omarchy-launch-walker -p 'Launch…'"},
"learn": {"icon":"󰧑","label":"Learn","keywords":"manual docs help reference"},
"trigger": {"icon":"󱓞","label":"Trigger","keywords":"actions capture share toggle hardware reminder"},
"style": {"icon":"","label":"Style","keywords":"theme background font waybar hyprland appearance"},
"setup": {"icon":"","label":"Setup","aliases":["settings"],"keywords":"configure defaults wifi bluetooth audio"},
"install": {"icon":"󰉉","label":"Install","keywords":"package app service browser editor terminal development gaming"},
"remove": {"icon":"󰭌","label":"Remove","aliases":["uninstall"],"keywords":"package app browser development gaming"},
"update": {"icon":"","label":"Update","aliases":["restart","refresh"],"keywords":"upgrade channel firmware timezone"},
"about": {"icon":"","label":"About","keywords":"omarchy system information","action":"omarchy-launch-about"},
"system": {"icon":"","label":"System","aliases":["power-menu"],"keywords":"lock logout restart shutdown suspend hibernate"},
// System
"system.screensaver": {"icon":"󱄄","label":"Screensaver","action":"omarchy-launch-screensaver force"},
"system.lock": {"icon":"","label":"Lock","keywords":"screen","action":"omarchy-system-lock"},
"system.suspend": {"icon":"󰒲","label":"Suspend","keywords":"sleep","when":"! omarchy-toggle-enabled suspend-off","action":"systemctl suspend"},
"system.hibernate": {"icon":"󰤁","label":"Hibernate","keywords":"sleep","when":"omarchy-hibernation-available","action":"systemctl hibernate"},
"system.logout": {"icon":"󰍃","label":"Logout","keywords":"sign out","action":"omarchy-system-logout"},
"system.restart": {"icon":"󰜉","label":"Restart","keywords":"reboot","action":"omarchy-system-reboot"},
"system.shutdown": {"icon":"󰐥","label":"Shutdown","keywords":"power off","action":"omarchy-system-shutdown"},
// Learn
"learn.keybindings": {"icon":"","label":"Keybindings","keywords":"keyboard shortcuts bindings","action":"omarchy-menu-keybindings"},
"learn.tmux-keybindings": {"icon":"","label":"Tmux keybindings","keywords":"keyboard shortcuts bindings terminal","action":"omarchy-menu-tmux-keybindings"},
"learn.omarchy": {"icon":"","label":"Omarchy","keywords":"manual documentation","action":"omarchy-launch-webapp 'https://learn.omacom.io/2/the-omarchy-manual'"},
"learn.hyprland": {"icon":"","label":"Hyprland","keywords":"wiki docs","action":"omarchy-launch-webapp 'https://wiki.hypr.land/'"},
"learn.arch": {"icon":"󰣇","label":"Arch","keywords":"linux wiki docs","action":"omarchy-launch-webapp 'https://wiki.archlinux.org/title/Main_page'"},
"learn.neovim": {"icon":"","label":"Neovim","keywords":"lazyvim keymaps docs","action":"omarchy-launch-webapp 'https://www.lazyvim.org/keymaps'"},
"learn.bash": {"icon":"󱆃","label":"Bash","keywords":"shell cheatsheet","action":"omarchy-launch-webapp 'https://devhints.io/bash'"},
// Trigger
"trigger.reminder": {"icon":"󰔛","label":"Reminder","aliases":["reminder"],"keywords":"timer notification remind"},
"trigger.capture": {"icon":"","label":"Capture","aliases":["capture","screenshot","screenrecord","screen-record","screenrecording"],"keywords":"color text extraction"},
"trigger.capture.screenshot": {"icon":"","label":"Screenshot","keywords":"picture","action":"omarchy-capture-screenshot"},
"trigger.capture.screenrecord.stop": {"icon":"","label":"Stop Screenrecording","keywords":"recording video","when":"pgrep -f '^gpu-screen-recorder' >/dev/null","action":"stop_active_screenrecording"},
"trigger.capture.screenrecord": {"icon":"","label":"Screenrecord","keywords":"record screen video"},
"trigger.capture.text": {"icon":"󰴑","label":"Text Extraction","keywords":"ocr","action":"omarchy-capture-text-extraction"},
"trigger.capture.color": {"icon":"󰃉","label":"Color","keywords":"picker hyprpicker","action":"pkill hyprpicker || hyprpicker -a"},
"trigger.capture.screenrecord.no-audio": {"icon":"","label":"With no audio","action":"omarchy-capture-screenrecording"},
"trigger.capture.screenrecord.desktop-audio": {"icon":"","label":"With desktop audio","action":"omarchy-capture-screenrecording --with-desktop-audio"},
"trigger.capture.screenrecord.microphone": {"icon":"","label":"With desktop + microphone audio","keywords":"mic","action":"omarchy-capture-screenrecording --with-desktop-audio --with-microphone-audio"},
"trigger.capture.screenrecord.webcam": {"icon":"","label":"With desktop + microphone audio + webcam","keywords":"camera","action":"screenrecord_with_webcam"},
"trigger.transcode": {"icon":"󰧸","label":"Transcode","keywords":"convert image video","action":"omarchy-transcode"},
"trigger.share": {"icon":"","label":"Share","aliases":["share"],"keywords":"clipboard file folder localsend"},
"trigger.toggle": {"icon":"󰔎","label":"Toggle","aliases":["toggle","toggles"],"keywords":"screensaver nightlight idle notifications waybar"},
"trigger.hardware": {"icon":"","label":"Hardware","aliases":["hardware","hw"],"keywords":"monitor touchpad touchscreen gpu"},
"trigger.hardware.laptop-display": {"icon":"󰛧","label":"Laptop Display","keywords":"monitor","action":"omarchy-hyprland-monitor-internal toggle"},
"trigger.hardware.mirror-display": {"icon":"󰍹","label":"Mirror Display","keywords":"monitor","action":"omarchy-hyprland-monitor-internal-mirror toggle"},
"trigger.hardware.hybrid-gpu": {"icon":"","label":"Hybrid GPU","keywords":"graphics","when":"omarchy-hw-hybrid-gpu >/dev/null","action":"present_terminal omarchy-toggle-hybrid-gpu"},
"trigger.hardware.touchpad": {"icon":"󰟸","label":"Touchpad","keywords":"trackpad","when":"omarchy-hw-touchpad >/dev/null","action":"omarchy-toggle-touchpad"},
"trigger.hardware.touchpad-haptics": {"icon":"󰌌","label":"Touchpad Haptics","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics"},
"trigger.hardware.touchpad-haptics.low": {"icon":"󰌌","label":"low","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics","checked":"haptic_touchpad_is low","action":"dell-xps-touchpad-haptics set low"},
"trigger.hardware.touchpad-haptics.mid": {"icon":"󰌌","label":"mid","keywords":"medium","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics","checked":"haptic_touchpad_is mid","action":"dell-xps-touchpad-haptics set mid"},
"trigger.hardware.touchpad-haptics.high": {"icon":"󰌌","label":"high","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics","checked":"haptic_touchpad_is high","action":"dell-xps-touchpad-haptics set high"},
"trigger.hardware.touchscreen": {"icon":"󰆽","label":"Touchscreen","keywords":"tablet","when":"omarchy-hw-touchscreen >/dev/null","action":"omarchy-toggle-touchscreen"},
"trigger.reminder.set": {"icon":"󰔛","label":"Set one","aliases":["reminder-set","remind"],"keywords":"timer","action":"show_custom_reminder_input"},
"trigger.reminder.show": {"icon":"󰔛","label":"Show all","keywords":"list","action":"omarchy-reminder show"},
"trigger.reminder.clear": {"icon":"󰔛","label":"Clear all","keywords":"delete","action":"omarchy-reminder clear"},
"trigger.share.clipboard": {"icon":"","label":"Clipboard","action":"omarchy-menu-share clipboard"},
"trigger.share.file": {"icon":"","label":"File","action":"terminal bash -c 'omarchy-menu-share file'"},
"trigger.share.folder": {"icon":"","label":"Folder","keywords":"directory","action":"terminal bash -c 'omarchy-menu-share folder'"},
"trigger.share.receive": {"icon":"󰥦","label":"Receive","keywords":"localsend","action":"uwsm-app -- localsend"},
"trigger.toggle.screensaver": {"icon":"󱄄","label":"Screensaver","action":"omarchy-toggle-screensaver"},
"trigger.toggle.nightlight": {"icon":"󰔎","label":"Nightlight","keywords":"night light hyprsunset","action":"omarchy-toggle-nightlight"},
"trigger.toggle.idle-lock": {"icon":"󱫖","label":"Idle Lock","keywords":"hypridle","action":"omarchy-toggle-idle"},
"trigger.toggle.notifications": {"icon":"󰂛","label":"Notifications","keywords":"mako silence","action":"omarchy-toggle-notification-silencing"},
"trigger.toggle.top-bar": {"icon":"󰍜","label":"Top Bar","keywords":"waybar","action":"omarchy-toggle-waybar"},
"trigger.toggle.workspace-layout": {"icon":"󱂬","label":"Workspace Layout","action":"omarchy-hyprland-workspace-layout-toggle"},
"trigger.toggle.window-gaps": {"icon":"","label":"Window Gaps","action":"omarchy-hyprland-window-gaps-toggle"},
"trigger.toggle.one-window-ratio": {"icon":"","label":"1-Window Ratio","keywords":"square","action":"omarchy-hyprland-window-single-square-aspect-toggle"},
"trigger.toggle.monitor-scaling": {"icon":"󰍹","label":"Monitor Scaling","keywords":"display","action":"omarchy-hyprland-monitor-scaling-cycle"},
"trigger.toggle.direct-boot": {"icon":"","label":"Direct Boot","action":"present_terminal omarchy-config-direct-boot"},
"trigger.toggle.passwordless-sudo": {"icon":"󰟵","label":"Passwordless Sudo","action":"present_terminal omarchy-sudo-passwordless"},
// Style
"style.theme": {"icon":"󰸌","label":"Theme","aliases":["theme","themes"],"keywords":"colors","action":"theme=$(omarchy-theme-switcher); [[ -n $theme ]] && omarchy-theme-set \"$theme\""},
"style.unlock": {"icon":"󰟵","label":"Unlock","keywords":"themes","action":"omarchy-launch-walker -m menus:omarchyunlocks --width 800 --minheight 400"},
"style.font": {"icon":"","label":"Font","keywords":"typeface","provider":"fonts"},
"style.background": {"icon":"","label":"Background","aliases":["background","wallpaper"],"action":"background=$(omarchy-theme-bg-switcher); [[ -n $background ]] && omarchy-theme-bg-set \"$background\""},
"style.waybar": {"icon":"󰍜","label":"Waybar","keywords":"bar top bottom left right"},
"style.corners": {"icon":"󰘇","label":"Corners","keywords":"sharp round rounded"},
"style.hyprland": {"icon":"","label":"Hyprland","keywords":"look feel","action":"open_in_editor \"$(hypr_config_file looknfeel)\""},
"style.screensaver": {"icon":"󱄄","label":"Screensaver","keywords":"branding"},
"style.about": {"icon":"","label":"About","keywords":"branding"},
"style.install": {"icon":"󰉉","label":"Install","keywords":"theme background font"},
"style.waybar.top": {"icon":"󰁝","label":"Top","keywords":"position","action":"omarchy-style-waybar-position top"},
"style.waybar.bottom": {"icon":"󰁅","label":"Bottom","keywords":"position","action":"omarchy-style-waybar-position bottom"},
"style.waybar.left": {"icon":"󰁍","label":"Left","keywords":"position","action":"omarchy-style-waybar-position left"},
"style.waybar.right": {"icon":"󰁔","label":"Right","keywords":"position","action":"omarchy-style-waybar-position right"},
"style.corners.sharp": {"icon":"󰝣","label":"Sharp","keywords":"square","action":"omarchy-style-corners sharp"},
"style.corners.round": {"icon":"󰘇","label":"Round","keywords":"rounded","action":"omarchy-style-corners round"},
"style.about.text": {"icon":"","label":"Edit Text","keywords":"branding","action":"omarchy-branding-about text"},
"style.about.image": {"icon":"","label":"Set From Image","keywords":"branding","action":"omarchy-branding-about image"},
"style.about.default": {"icon":"","label":"Restore Default","keywords":"branding","action":"omarchy-branding-about reset"},
"style.screensaver.text": {"icon":"","label":"Edit Text","keywords":"branding","action":"omarchy-branding-screensaver text"},
"style.screensaver.image": {"icon":"","label":"Set From Image","keywords":"branding","action":"omarchy-branding-screensaver image"},
"style.screensaver.default": {"icon":"","label":"Restore Default","keywords":"branding","action":"omarchy-branding-screensaver reset"},
"style.install.theme": {"icon":"󰸌","label":"Theme","action":"present_terminal omarchy-theme-install"},
"style.install.background": {"icon":"","label":"Background","keywords":"wallpaper","action":"omarchy-theme-bg-install"},
"style.install.font": {"icon":"","label":"Font"},
"style.install.font.cascadia": {"icon":"","label":"Cascadia Mono","action":"install_font 'Cascadia Mono' ttf-cascadia-mono-nerd 'CaskaydiaMono Nerd Font'"},
"style.install.font.meslo": {"icon":"","label":"Meslo LG Mono","action":"install_font 'Meslo LG Mono' ttf-meslo-nerd 'MesloLGL Nerd Font'"},
"style.install.font.fira": {"icon":"","label":"Fira Code","action":"install_font 'Fira Code' ttf-firacode-nerd 'FiraCode Nerd Font'"},
"style.install.font.victor": {"icon":"","label":"Victor Code","action":"install_font 'Victor Code' ttf-victor-mono-nerd 'VictorMono Nerd Font'"},
"style.install.font.bitstream": {"icon":"","label":"Bitstream Vera Mono","action":"install_font 'Bitstream Vera Code' ttf-bitstream-vera-mono-nerd 'BitstromWera Nerd Font'"},
"style.install.font.iosevka": {"icon":"","label":"Iosevka","action":"install_font Iosevka ttf-iosevka-nerd 'Iosevka Nerd Font Mono'"},
// Setup
"setup.audio": {"icon":"","label":"Audio","keywords":"sound","action":"omarchy-launch-audio"},
"setup.wifi": {"icon":"","label":"Wifi","keywords":"wireless network","action":"omarchy-launch-wifi"},
"setup.bluetooth": {"icon":"󰂯","label":"Bluetooth","action":"omarchy-launch-bluetooth"},
"setup.power": {"icon":"󱐋","label":"Power Profile","aliases":["power","power-profile","power-profiles"],"keywords":"performance battery","provider":"power-profiles"},
"setup.sleep": {"icon":"","label":"System Sleep","keywords":"suspend hibernate"},
"setup.sleep.suspend-enable": {"icon":"󰒲","label":"Enable Suspend","when":"omarchy-toggle-enabled suspend-off","action":"omarchy-toggle-suspend"},
"setup.sleep.suspend-disable": {"icon":"󰒲","label":"Disable Suspend","when":"! omarchy-toggle-enabled suspend-off","action":"omarchy-toggle-suspend"},
"setup.sleep.hibernate-enable": {"icon":"󰤁","label":"Enable Hibernate","when":"! omarchy-hibernation-available","action":"present_terminal omarchy-hibernation-setup"},
"setup.sleep.hibernate-disable": {"icon":"󰤁","label":"Disable Hibernate","when":"omarchy-hibernation-available","action":"present_terminal omarchy-hibernation-remove"},
"setup.monitors": {"icon":"󰍹","label":"Monitors","keywords":"monitor display hyprland","action":"open_in_editor \"$(hypr_config_file monitors)\""},
"setup.keybindings": {"icon":"","label":"Keybindings","keywords":"keyboard shortcuts","when":"[[ -f $(hypr_config_file bindings) ]]","action":"open_in_editor \"$(hypr_config_file bindings)\""},
"setup.input": {"icon":"","label":"Input","keywords":"keyboard touchpad mouse","when":"[[ -f $(hypr_config_file input) ]]","action":"open_in_editor \"$(hypr_config_file input)\""},
"setup.default": {"icon":"","label":"Defaults","aliases":["default","defaults"],"keywords":"browser terminal editor"},
"setup.default.browser": {"icon":"","label":"Browser"},
"setup.default.browser.chromium": {"icon":"","label":"Chromium","when":"omarchy-cmd-present chromium","checked":"default_browser_is chromium","action":"omarchy-default-browser chromium"},
"setup.default.browser.chrome": {"icon":"󰊯","label":"Chrome","keywords":"google","when":"omarchy-cmd-present google-chrome-stable","checked":"default_browser_is chrome","action":"omarchy-default-browser chrome"},
"setup.default.browser.brave": {"icon":"󰖟","label":"Brave","when":"omarchy-cmd-present brave","checked":"default_browser_is brave","action":"omarchy-default-browser brave"},
"setup.default.browser.brave-origin": {"icon":"󰖟","label":"Brave Origin","when":"omarchy-cmd-present brave-origin-beta","checked":"default_browser_is brave-origin","action":"omarchy-default-browser brave-origin"},
"setup.default.browser.edge": {"icon":"󰇩","label":"Edge","when":"omarchy-cmd-present microsoft-edge-stable","checked":"default_browser_is edge","action":"omarchy-default-browser edge"},
"setup.default.browser.firefox": {"icon":"󰈹","label":"Firefox","when":"omarchy-cmd-present firefox","checked":"default_browser_is firefox","action":"omarchy-default-browser firefox"},
"setup.default.browser.zen": {"icon":"󰖟","label":"Zen","when":"omarchy-cmd-present zen-browser","checked":"default_browser_is zen","action":"omarchy-default-browser zen"},
"setup.default.terminal": {"icon":"","label":"Terminal"},
"setup.default.terminal.alacritty": {"icon":"","label":"Alacritty","when":"omarchy-cmd-present alacritty","checked":"default_terminal_is alacritty","action":"omarchy-default-terminal alacritty"},
"setup.default.terminal.foot": {"icon":"","label":"Foot","when":"omarchy-cmd-present foot","checked":"default_terminal_is foot","action":"omarchy-default-terminal foot"},
"setup.default.terminal.ghostty": {"icon":"","label":"Ghostty","when":"omarchy-cmd-present ghostty","checked":"default_terminal_is ghostty","action":"omarchy-default-terminal ghostty"},
"setup.default.terminal.kitty": {"icon":"","label":"Kitty","when":"omarchy-cmd-present kitty","checked":"default_terminal_is kitty","action":"omarchy-default-terminal kitty"},
"setup.default.editor": {"icon":"","label":"Editor"},
"setup.default.editor.neovim": {"icon":"","label":"Neovim","keywords":"nvim","when":"omarchy-cmd-present nvim","checked":"default_editor_is nvim","action":"omarchy-default-editor nvim"},
"setup.default.editor.vscode": {"icon":"","label":"VSCode","keywords":"code","when":"omarchy-cmd-present code","checked":"default_editor_is code","action":"omarchy-default-editor code"},
"setup.default.editor.cursor": {"icon":"","label":"Cursor","when":"omarchy-cmd-present cursor","checked":"default_editor_is cursor","action":"omarchy-default-editor cursor"},
"setup.default.editor.zed": {"icon":"","label":"Zed","when":"omarchy-cmd-present zeditor","checked":"default_editor_is zeditor","action":"omarchy-default-editor zed"},
"setup.default.editor.sublime": {"icon":"","label":"Sublime Text","when":"omarchy-cmd-present sublime_text","checked":"default_editor_is sublime_text","action":"omarchy-default-editor sublime_text"},
"setup.default.editor.helix": {"icon":"","label":"Helix","when":"omarchy-cmd-present helix","checked":"default_editor_is helix","action":"omarchy-default-editor helix"},
"setup.default.editor.vim": {"icon":"","label":"Vim","when":"omarchy-cmd-present vim","checked":"default_editor_is vim","action":"omarchy-default-editor vim"},
"setup.default.editor.emacs": {"icon":"","label":"Emacs","when":"omarchy-cmd-present emacs","checked":"default_editor_is emacs","action":"omarchy-default-editor emacs"},
"setup.dns": {"icon":"󰱔","label":"DNS","keywords":"network","action":"present_terminal omarchy-setup-dns"},
"setup.security": {"icon":"","label":"Security","keywords":"fingerprint fido2"},
"setup.config": {"icon":"","label":"Config","keywords":"files hyprland waybar walker"},
"setup.security.fingerprint": {"icon":"󰈷","label":"Fingerprint","action":"present_terminal omarchy-setup-security-fingerprint"},
"setup.security.fido2": {"icon":"","label":"Fido2","keywords":"key","action":"present_terminal omarchy-setup-security-fido2"},
"setup.config.hyprland": {"icon":"","label":"Hyprland","action":"open_in_editor \"$(hypr_config_file hyprland)\""},
"setup.config.hypridle": {"icon":"","label":"Hypridle","keywords":"idle","action":"open_in_editor ~/.config/hypr/hypridle.conf && omarchy-restart-hypridle"},
"setup.config.hyprlock": {"icon":"","label":"Hyprlock","keywords":"lock","action":"open_in_editor ~/.config/hypr/hyprlock.conf"},
"setup.config.hyprsunset": {"icon":"","label":"Hyprsunset","keywords":"night light","action":"open_in_editor ~/.config/hypr/hyprsunset.conf && omarchy-restart-hyprsunset"},
"setup.config.swayosd": {"icon":"","label":"Swayosd","action":"open_in_editor ~/.config/swayosd/config.toml && omarchy-restart-swayosd"},
"setup.config.walker": {"icon":"󰌧","label":"Walker","keywords":"launcher","action":"open_in_editor ~/.config/walker/config.toml && omarchy-restart-walker"},
"setup.config.waybar": {"icon":"󰍜","label":"Waybar","keywords":"bar","action":"open_in_editor ~/.config/waybar/config.jsonc && omarchy-restart-waybar"},
"setup.config.xcompose": {"icon":"󰞅","label":"XCompose","keywords":"compose key","action":"open_in_editor ~/.XCompose && omarchy-restart-xcompose"},
// Install
"install.package": {"icon":"󰣇","label":"Package","keywords":"pacman aur","action":"terminal omarchy-pkg-install"},
"install.aur": {"icon":"󰣇","label":"AUR","keywords":"package","action":"terminal omarchy-pkg-aur-install"},
"install.webapp": {"icon":"","label":"Web App","keywords":"pwa","action":"present_terminal omarchy-webapp-install"},
"install.tui": {"icon":"","label":"TUI","keywords":"terminal app","action":"present_terminal omarchy-tui-install"},
"install.service": {"icon":"","label":"Service","keywords":"dropbox tailscale vpn"},
"install.style": {"icon":"","label":"Style","keywords":"theme background font","target":"style.install"},
"install.development": {"icon":"󰵮","label":"Development","keywords":"languages programming"},
"install.editor": {"icon":"","label":"Editor","keywords":"ide"},
"install.terminal": {"icon":"","label":"Terminal","keywords":"emulator"},
"install.browser": {"icon":"","label":"Browser","keywords":"web"},
"install.ai": {"icon":"󱚤","label":"AI","keywords":"dictation ollama lm studio crush"},
"install.gaming": {"icon":"","label":"Gaming","keywords":"steam retroarch minecraft lutris heroic"},
"install.windows": {"icon":"󰍲","label":"Windows","keywords":"vm","action":"present_terminal 'omarchy-windows-vm install'"},
"install.browser.chrome": {"icon":"","label":"Chrome","action":"present_terminal 'omarchy-install-browser chrome'"},
"install.browser.edge": {"icon":"","label":"Edge","action":"present_terminal 'omarchy-install-browser edge'"},
"install.browser.brave": {"icon":"","label":"Brave","action":"present_terminal 'omarchy-install-browser brave'"},
"install.browser.brave-origin": {"icon":"","label":"Brave Origin","action":"present_terminal 'omarchy-install-browser brave-origin'"},
"install.browser.firefox": {"icon":"","label":"Firefox","action":"present_terminal 'omarchy-install-browser firefox'"},
"install.browser.zen": {"icon":"󰖟","label":"Zen","action":"present_terminal 'omarchy-install-browser zen'"},
"install.service.dropbox": {"icon":"","label":"Dropbox","action":"present_terminal omarchy-install-dropbox"},
"install.service.tailscale": {"icon":"","label":"Tailscale","keywords":"vpn","action":"present_terminal omarchy-install-tailscale"},
"install.service.nordvpn": {"icon":"󱇱","label":"NordVPN [AUR]","keywords":"vpn","action":"present_terminal omarchy-install-nordvpn"},
"install.service.once": {"icon":"󰏖","label":"ONCE","action":"present_terminal omarchy-install-once"},
"install.service.bitwarden": {"icon":"󰟵","label":"Bitwarden","keywords":"password","action":"install_and_launch Bitwarden 'bitwarden bitwarden-cli' bitwarden"},
"install.service.chromium-account": {"icon":"","label":"Chromium Account","keywords":"google","action":"present_terminal omarchy-install-chromium-google-account"},
"install.editor.vscode": {"icon":"","label":"VSCode","keywords":"code","action":"present_terminal omarchy-install-vscode"},
"install.editor.cursor": {"icon":"","label":"Cursor","action":"install_and_launch Cursor cursor-bin cursor"},
"install.editor.zed": {"icon":"","label":"Zed","action":"present_terminal omarchy-install-zed"},
"install.editor.sublime": {"icon":"","label":"Sublime Text","action":"install_and_launch 'Sublime Text' sublime-text-4 sublime_text"},
"install.editor.helix": {"icon":"","label":"Helix","action":"present_terminal omarchy-install-helix"},
"install.editor.vim": {"icon":"","label":"Vim","action":"install Vim vim"},
"install.editor.emacs": {"icon":"","label":"Emacs","action":"install Emacs emacs-wayland && systemctl --user enable --now emacs.service"},
"install.terminal.alacritty": {"icon":"","label":"Alacritty","action":"install_terminal alacritty"},
"install.terminal.foot": {"icon":"","label":"Foot","action":"install_terminal foot"},
"install.terminal.ghostty": {"icon":"","label":"Ghostty","action":"install_terminal ghostty"},
"install.terminal.kitty": {"icon":"","label":"Kitty","action":"install_terminal kitty"},
"install.ai.dictation": {"icon":"","label":"Dictation","keywords":"voice","action":"present_terminal omarchy-voxtype-install"},
"install.ai.lm-studio": {"icon":"󱚤","label":"LM Studio","action":"install 'LM Studio' lmstudio-bin"},
"install.ai.ollama": {"icon":"󱚤","label":"Ollama","action":"if omarchy-cmd-present nvidia-smi; then ollama_pkg=ollama-cuda; elif omarchy-cmd-present rocminfo; then ollama_pkg=ollama-rocm; else ollama_pkg=ollama; fi; install Ollama \"$ollama_pkg\""},
"install.ai.crush": {"icon":"󱚤","label":"Crush","action":"install Crush crush-bin"},
"install.gaming.steam": {"icon":"","label":"Steam","action":"present_terminal omarchy-install-gaming-steam"},
"install.gaming.retroarch": {"icon":"󰯉","label":"RetroArch","action":"present_terminal omarchy-install-gaming-retroarch"},
"install.gaming.minecraft": {"icon":"󰍳","label":"Minecraft","action":"install_and_launch Minecraft minecraft-launcher minecraft-launcher"},
"install.gaming.geforce-now": {"icon":"󰢹","label":"NVIDIA GeForce NOW","action":"present_terminal omarchy-install-gaming-geforce-now"},
"install.gaming.xbox-cloud": {"icon":"","label":"Xbox Cloud Gaming","action":"present_terminal omarchy-install-gaming-xbox-cloud"},
"install.gaming.xbox-controller": {"icon":"󰂯","label":"Xbox Controller","action":"present_terminal omarchy-install-gaming-xbox-controllers"},
"install.gaming.moonlight": {"icon":"󰍹","label":"Moonlight (GameStream)","action":"present_terminal omarchy-install-gaming-moonlight"},
"install.gaming.lutris": {"icon":"","label":"Lutris (Battle.net)","action":"present_terminal omarchy-install-gaming-lutris"},
"install.gaming.heroic": {"icon":"󱓟","label":"Heroic (Epic Games)","action":"present_terminal omarchy-install-gaming-heroic"},
"install.gaming.retro-launcher": {"icon":"󰯉","label":"RetroArch Game Launcher","action":"omarchy-games-retro-install"},
"install.development.rails": {"icon":"󰫏","label":"Ruby on Rails","action":"present_terminal 'omarchy-install-dev-env ruby'"},
"install.development.docker-dbs": {"icon":"","label":"Docker DB","keywords":"databases","action":"present_terminal omarchy-install-docker-dbs"},
"install.development.javascript": {"icon":"","label":"JavaScript","keywords":"node bun deno"},
"install.development.go": {"icon":"","label":"Go","keywords":"golang","action":"present_terminal 'omarchy-install-dev-env go'"},
"install.development.php": {"icon":"","label":"PHP","keywords":"laravel symfony"},
"install.development.python": {"icon":"","label":"Python","action":"present_terminal 'omarchy-install-dev-env python'"},
"install.development.elixir": {"icon":"","label":"Elixir","keywords":"phoenix"},
"install.development.zig": {"icon":"","label":"Zig","action":"present_terminal 'omarchy-install-dev-env zig'"},
"install.development.rust": {"icon":"","label":"Rust","action":"present_terminal 'omarchy-install-dev-env rust'"},
"install.development.java": {"icon":"","label":"Java","action":"present_terminal 'omarchy-install-dev-env java'"},
"install.development.dotnet": {"icon":"","label":".NET","action":"present_terminal 'omarchy-install-dev-env dotnet'"},
"install.development.ocaml": {"icon":"","label":"OCaml","action":"present_terminal 'omarchy-install-dev-env ocaml'"},
"install.development.clojure": {"icon":"","label":"Clojure","action":"present_terminal 'omarchy-install-dev-env clojure'"},
"install.development.scala": {"icon":"","label":"Scala","action":"present_terminal 'omarchy-install-dev-env scala'"},
"install.development.javascript.node": {"icon":"","label":"Node.js","action":"present_terminal 'omarchy-install-dev-env node'"},
"install.development.javascript.bun": {"icon":"","label":"Bun","action":"present_terminal 'omarchy-install-dev-env bun'"},
"install.development.javascript.deno": {"icon":"","label":"Deno","action":"present_terminal 'omarchy-install-dev-env deno'"},
"install.development.php.php": {"icon":"","label":"PHP","action":"present_terminal 'omarchy-install-dev-env php'"},
"install.development.php.laravel": {"icon":"","label":"Laravel","action":"present_terminal 'omarchy-install-dev-env laravel'"},
"install.development.php.symfony": {"icon":"","label":"Symfony","action":"present_terminal 'omarchy-install-dev-env symfony'"},
"install.development.elixir.elixir": {"icon":"","label":"Elixir","action":"present_terminal 'omarchy-install-dev-env elixir'"},
"install.development.elixir.phoenix": {"icon":"","label":"Phoenix","action":"present_terminal 'omarchy-install-dev-env phoenix'"},
// Remove
"remove.package": {"icon":"󰣇","label":"Package","keywords":"uninstall","action":"terminal omarchy-pkg-remove"},
"remove.webapp": {"icon":"","label":"Web App","keywords":"uninstall","action":"present_terminal omarchy-webapp-remove"},
"remove.tui": {"icon":"","label":"TUI","keywords":"uninstall terminal app","action":"present_terminal omarchy-tui-remove"},
"remove.development": {"icon":"󰵮","label":"Development","keywords":"uninstall languages"},
"remove.theme": {"icon":"󰸌","label":"Theme","keywords":"uninstall","action":"present_terminal omarchy-theme-remove"},
"remove.browser": {"icon":"","label":"Browser","keywords":"uninstall"},
"remove.dictation": {"icon":"","label":"Dictation","keywords":"uninstall voice","action":"present_terminal omarchy-voxtype-remove"},
"remove.gaming": {"icon":"","label":"Gaming","keywords":"uninstall steam retroarch minecraft"},
"remove.windows": {"icon":"󰍲","label":"Windows","keywords":"uninstall vm","action":"present_terminal 'omarchy-windows-vm remove'"},
"remove.preinstalls": {"icon":"󰏓","label":"Preinstalls","action":"present_terminal omarchy-remove-preinstalls"},
"remove.security": {"icon":"","label":"Security","keywords":"fingerprint fido2"},
"remove.security.fingerprint": {"icon":"󰈷","label":"Fingerprint","action":"present_terminal omarchy-remove-security-fingerprint"},
"remove.security.fido2": {"icon":"","label":"Fido2","action":"present_terminal omarchy-remove-security-fido2"},
"remove.browser.chrome": {"icon":"","label":"Chrome","action":"present_terminal 'omarchy-remove-browser chrome'"},
"remove.browser.edge": {"icon":"","label":"Edge","action":"present_terminal 'omarchy-remove-browser edge'"},
"remove.browser.brave": {"icon":"","label":"Brave","action":"present_terminal 'omarchy-remove-browser brave'"},
"remove.browser.brave-origin": {"icon":"","label":"Brave Origin","action":"present_terminal 'omarchy-remove-browser brave-origin'"},
"remove.browser.firefox": {"icon":"","label":"Firefox","action":"present_terminal 'omarchy-remove-browser firefox'"},
"remove.browser.zen": {"icon":"","label":"Zen","action":"present_terminal 'omarchy-remove-browser zen'"},
"remove.gaming.steam": {"icon":"","label":"Steam","action":"present_terminal omarchy-remove-gaming-steam"},
"remove.gaming.retroarch": {"icon":"","label":"RetroArch","action":"present_terminal omarchy-remove-gaming-retroarch"},
"remove.gaming.minecraft": {"icon":"󰍳","label":"Minecraft","action":"present_terminal omarchy-remove-gaming-minecraft"},
"remove.gaming.geforce-now": {"icon":"󰢹","label":"NVIDIA GeForce NOW","action":"present_terminal omarchy-remove-gaming-geforce-now"},
"remove.gaming.xbox-cloud": {"icon":"","label":"Xbox Cloud Gaming","action":"present_terminal omarchy-remove-gaming-xbox-cloud"},
"remove.gaming.xbox-controller": {"icon":"󰖺","label":"Xbox Controller (󰂯)","action":"present_terminal omarchy-remove-gaming-xbox-controllers"},
"remove.gaming.moonlight": {"icon":"󰍹","label":"Moonlight (GameStream)","action":"present_terminal omarchy-remove-gaming-moonlight"},
"remove.gaming.lutris": {"icon":"","label":"Lutris (Battle.net)","action":"present_terminal omarchy-remove-gaming-lutris"},
"remove.gaming.heroic": {"icon":"󱓟","label":"Heroic (Epic Games)","action":"present_terminal omarchy-remove-gaming-heroic"},
"remove.development.rails": {"icon":"󰫏","label":"Ruby on Rails","action":"present_terminal 'omarchy-remove-dev-env ruby'"},
"remove.development.javascript": {"icon":"","label":"JavaScript","keywords":"node bun deno"},
"remove.development.go": {"icon":"","label":"Go","keywords":"golang","action":"present_terminal 'omarchy-remove-dev-env go'"},
"remove.development.php": {"icon":"","label":"PHP","keywords":"laravel symfony"},
"remove.development.python": {"icon":"","label":"Python","action":"present_terminal 'omarchy-remove-dev-env python'"},
"remove.development.elixir": {"icon":"","label":"Elixir","keywords":"phoenix"},
"remove.development.zig": {"icon":"","label":"Zig","action":"present_terminal 'omarchy-remove-dev-env zig'"},
"remove.development.rust": {"icon":"","label":"Rust","action":"present_terminal 'omarchy-remove-dev-env rust'"},
"remove.development.java": {"icon":"","label":"Java","action":"present_terminal 'omarchy-remove-dev-env java'"},
"remove.development.dotnet": {"icon":"","label":".NET","action":"present_terminal 'omarchy-remove-dev-env dotnet'"},
"remove.development.ocaml": {"icon":"","label":"OCaml","action":"present_terminal 'omarchy-remove-dev-env ocaml'"},
"remove.development.clojure": {"icon":"","label":"Clojure","action":"present_terminal 'omarchy-remove-dev-env clojure'"},
"remove.development.scala": {"icon":"","label":"Scala","action":"present_terminal 'omarchy-remove-dev-env scala'"},
"remove.development.javascript.node": {"icon":"","label":"Node.js","action":"present_terminal 'omarchy-remove-dev-env node'"},
"remove.development.javascript.bun": {"icon":"","label":"Bun","action":"present_terminal 'omarchy-remove-dev-env bun'"},
"remove.development.javascript.deno": {"icon":"","label":"Deno","action":"present_terminal 'omarchy-remove-dev-env deno'"},
"remove.development.php.php": {"icon":"","label":"PHP","action":"present_terminal 'omarchy-remove-dev-env php'"},
"remove.development.php.laravel": {"icon":"","label":"Laravel","action":"present_terminal 'omarchy-remove-dev-env laravel'"},
"remove.development.php.symfony": {"icon":"","label":"Symfony","action":"present_terminal 'omarchy-remove-dev-env symfony'"},
"remove.development.elixir.elixir": {"icon":"","label":"Elixir","action":"present_terminal 'omarchy-remove-dev-env elixir'"},
"remove.development.elixir.phoenix": {"icon":"","label":"Phoenix","action":"present_terminal 'omarchy-remove-dev-env phoenix'"},
// Update
"update.omarchy": {"icon":"","label":"Omarchy","keywords":"system","action":"present_terminal omarchy-update"},
"update.channel": {"icon":"󰔫","label":"Channel","keywords":"stable rc edge dev"},
"update.config": {"icon":"","label":"Config","keywords":"refresh default"},
"update.themes": {"icon":"󰸌","label":"Extra Themes","action":"present_terminal omarchy-theme-update"},
"update.process": {"icon":"","label":"Process","keywords":"restart services"},
"update.hardware": {"icon":"󰇅","label":"Hardware","keywords":"restart audio wifi bluetooth trackpad"},
"update.firmware": {"icon":"","label":"Firmware","keywords":"fwupd","action":"present_terminal omarchy-update-firmware"},
"update.password": {"icon":"","label":"Password","keywords":"drive user"},
"update.timezone": {"icon":"","label":"Timezone","keywords":"time zone","action":"present_terminal omarchy-tz-select"},
"update.time": {"icon":"","label":"Time","keywords":"clock ntp","action":"present_terminal omarchy-update-time"},
"update.channel.stable": {"icon":"🟢","label":"Stable","action":"present_terminal 'omarchy-channel-set stable'"},
"update.channel.rc": {"icon":"🟡","label":"RC","keywords":"release candidate","action":"present_terminal 'omarchy-channel-set rc'"},
"update.channel.edge": {"icon":"🟠","label":"Edge","action":"present_terminal 'omarchy-channel-set edge'"},
"update.channel.dev": {"icon":"🔴","label":"Dev","keywords":"development","action":"present_terminal 'omarchy-channel-set dev'"},
"update.process.hypridle": {"icon":"","label":"Hypridle","keywords":"restart","action":"omarchy-restart-hypridle"},
"update.process.hyprsunset": {"icon":"","label":"Hyprsunset","keywords":"restart","action":"omarchy-restart-hyprsunset"},
"update.process.mako": {"icon":"󰎟","label":"Mako","keywords":"restart notifications","action":"omarchy-restart-mako"},
"update.process.swayosd": {"icon":"","label":"Swayosd","keywords":"restart","action":"omarchy-restart-swayosd"},
"update.process.walker": {"icon":"󰌧","label":"Walker","keywords":"restart launcher","action":"omarchy-restart-walker"},
"update.process.waybar": {"icon":"󰍜","label":"Waybar","keywords":"restart","action":"omarchy-restart-waybar"},
"update.config.hyprland": {"icon":"","label":"Hyprland","keywords":"refresh","action":"present_terminal omarchy-refresh-hyprland"},
"update.config.hypridle": {"icon":"","label":"Hypridle","keywords":"refresh","action":"present_terminal omarchy-refresh-hypridle"},
"update.config.hyprlock": {"icon":"","label":"Hyprlock","keywords":"refresh","action":"present_terminal omarchy-refresh-hyprlock"},
"update.config.hyprsunset": {"icon":"","label":"Hyprsunset","keywords":"refresh","action":"present_terminal omarchy-refresh-hyprsunset"},
"update.config.plymouth": {"icon":"󱣴","label":"Plymouth","keywords":"refresh","action":"present_terminal omarchy-refresh-plymouth"},
"update.config.swayosd": {"icon":"","label":"Swayosd","keywords":"refresh","action":"present_terminal omarchy-refresh-swayosd"},
"update.config.tmux": {"icon":"","label":"Tmux","keywords":"refresh","action":"present_terminal omarchy-refresh-tmux"},
"update.config.walker": {"icon":"󰌧","label":"Walker","keywords":"refresh","action":"present_terminal omarchy-refresh-walker"},
"update.config.waybar": {"icon":"󰍜","label":"Waybar","keywords":"refresh","action":"present_terminal omarchy-refresh-waybar"},
"update.hardware.audio": {"icon":"","label":"Audio","keywords":"restart pipewire","action":"present_terminal omarchy-restart-pipewire"},
"update.hardware.wifi": {"icon":"󱚾","label":"Wi-Fi","keywords":"restart wireless","action":"present_terminal omarchy-restart-wifi"},
"update.hardware.bluetooth": {"icon":"󰂯","label":"Bluetooth","keywords":"restart","action":"present_terminal omarchy-restart-bluetooth"},
"update.hardware.trackpad": {"icon":"󰟸","label":"Trackpad","keywords":"restart touchpad","action":"present_terminal omarchy-restart-trackpad"},
"update.password.drive": {"icon":"","label":"Drive Encryption","action":"present_terminal omarchy-drive-password"},
"update.password.user": {"icon":"","label":"User","keywords":"passwd","action":"present_terminal passwd"},
}
+892
View File
@@ -0,0 +1,892 @@
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import QtQuick
ShellRoot {
id: root
property string socketPath: (Quickshell.env("XDG_RUNTIME_DIR") || ("/run/user/" + Quickshell.env("UID"))) + "/omarchy-menu.sock"
property string startupMenuJsonFile: Quickshell.env("OMARCHY_MENU_JSON_FILE") || ""
property string menuBin: Quickshell.env("OMARCHY_MENU_BIN") || "omarchy-menu"
property string startupInitialMenu: Quickshell.env("OMARCHY_MENU_INITIAL_MENU") || "root"
property string startupSelectionFile: Quickshell.env("OMARCHY_MENU_SELECTION_FILE") || ""
property string startupDoneFile: Quickshell.env("OMARCHY_MENU_DONE_FILE") || ""
property string startupColorsRaw: Quickshell.env("OMARCHY_MENU_COLORS_RAW") || ""
property string fontFamily: Quickshell.env("OMARCHY_MENU_FONT") || "monospace"
property string colorsFile: Quickshell.env("OMARCHY_MENU_COLORS_FILE") || (Quickshell.env("HOME") + "/.config/omarchy/current/theme/menu.json")
property string styleFile: Quickshell.env("OMARCHY_MENU_STYLE_FILE") || (Quickshell.env("HOME") + "/.local/state/omarchy/toggles/quickshell-menu.json")
property string selectionFile: ""
property string doneFile: ""
property bool requestActive: false
property bool opened: false
property bool rowsLoaded: false
property string activeMenu: "root"
property string filterText: ""
property int selectedIndex: 0
property int requestSerial: 0
property int applySerial: 0
property var items: ({})
property var itemOrder: []
property var navStack: []
property var providersLoaded: ({})
property var providerQueue: []
property var doneFilesToRelease: []
property color accent: "#89b4fa"
property color background: "#101315"
property color foreground: "#cacccc"
property color border: foreground
property int cornerRadius: 0
property int contentMargin: 18
property int headerHeight: 34
property int contentSpacing: 6
property int baseRowHeight: 50
property int detailRowHeight: 58
property int rowSpacing: 3
property int dividerHeight: 17
property bool searchDivider: false
property int layoutSerial: 0
property int cardWidth: Math.min(300, panel.width - 48)
property int visibleRowsHeight: rowListHeight(layoutSerial, displayModel.count, filterText, searchDivider)
property int cardHeight: Math.min(Math.max(220, contentMargin * 2 + headerHeight + contentSpacing + visibleRowsHeight), panel.height - 48)
function shellQuote(value) {
return "'" + String(value).replace(/'/g, "'\\''") + "'"
}
function decodeField(value) {
return String(value || "").replace(/\v/g, "\n").replace(/\f/g, "\t")
}
function withAlpha(color, alpha) {
return Qt.rgba(color.r, color.g, color.b, alpha)
}
function rowHeightForDetail(detail) {
return root.filterText && detail ? root.detailRowHeight : root.baseRowHeight
}
function rowListHeight(_serial, _count, _filter, _divider) {
if (displayModel.count === 0) return root.baseRowHeight
var count = Math.min(displayModel.count, 10)
var total = 0
var previousSection = ""
for (var i = 0; i < count; i++) {
var row = displayModel.get(i)
if (i > 0) total += root.rowSpacing
if (row.section === "drilldown" && previousSection !== "drilldown") total += root.dividerHeight
total += root.rowHeightForDetail(row.detail)
previousSection = row.section
}
return total
}
function item(id) {
return root.items[id] || null
}
function loadMenuJson(raw) {
var nextItems = ({})
var nextOrder = []
var payload = JSON.parse(raw || "{}")
var rows = payload.items || []
for (var i = 0; i < rows.length; i++) {
var entry = rows[i]
var id = entry.id || ""
if (!id) continue
var order = nextItems[id] ? nextItems[id].order : nextOrder.length
if (!nextItems[id]) nextOrder.push(id)
nextItems[id] = {
id: id,
parent: entry.parent || "",
kind: entry.kind || "action",
icon: entry.icon || "",
label: entry.label || id,
target: entry.target || "",
keywords: entry.keywords || "",
description: entry.description || "",
action: entry.action || "",
provider: entry.provider || "",
order: order
}
}
if (!nextItems.root) {
nextItems.root = { id: "root", parent: "", kind: "menu", icon: "", label: "Go", target: "", keywords: "", description: "", order: -1 }
}
root.items = nextItems
root.itemOrder = nextOrder
root.rowsLoaded = true
}
function mergeProviderJson(raw, menuId) {
var payload = ({})
try {
payload = JSON.parse(raw || "{}")
} catch (e) {
return
}
var rows = payload.items || []
var changed = false
for (var i = 0; i < rows.length; i++) {
var entry = rows[i]
var id = entry.id || ""
if (!id) continue
if (!root.items[id]) root.itemOrder.push(id)
root.items[id] = {
id: id,
parent: entry.parent || menuId,
kind: entry.kind || "action",
icon: entry.icon || "",
label: entry.label || id,
target: entry.target || "",
keywords: entry.keywords || "",
description: entry.description || "",
action: entry.action || "",
provider: entry.provider || "",
order: root.itemOrder.indexOf(id)
}
changed = true
}
if (changed) root.rebuildDisplay()
}
function startProviderForMenu(id) {
var entry = root.item(id)
if (!entry || !entry.provider || root.providersLoaded[id]) return
root.providersLoaded[id] = true
providerProc.menuId = id
providerProc.output = ""
providerProc.command = [root.menuBin, "--provider", entry.provider, id]
providerProc.running = true
}
function startNextProvider() {
if (providerProc.running) return
while (root.providerQueue.length > 0) {
var id = root.providerQueue.shift()
var entry = root.item(id)
if (!entry || !entry.provider || root.providersLoaded[id]) continue
root.startProviderForMenu(id)
return
}
}
function loadProviderForMenu(id) {
var entry = root.item(id)
if (!entry || !entry.provider || root.providersLoaded[id]) return
if (providerProc.running) {
if (root.providerQueue.indexOf(id) < 0) root.providerQueue = root.providerQueue.concat([id])
return
}
root.startProviderForMenu(id)
}
function loadProvidersForSearch() {
var active = root.item(root.activeMenu) ? root.activeMenu : "root"
for (var i = 0; i < root.itemOrder.length; i++) {
var entry = root.item(root.itemOrder[i])
if (!entry || !entry.provider || root.providersLoaded[entry.id]) continue
if (active !== "root" && entry.id !== active && !root.isDescendantOf(entry.id, active)) continue
root.loadProviderForMenu(entry.id)
}
}
function depthFor(id) {
var depth = 0
var current = root.item(id)
var guard = 0
while (current && current.parent && current.parent !== "root" && guard < 32) {
depth += 1
current = root.item(current.parent)
guard += 1
}
return depth
}
function pathFor(id) {
var labels = []
var current = root.item(id)
var guard = 0
while (current && current.id !== "root" && guard < 32) {
labels.unshift(current.label)
current = root.item(current.parent)
guard += 1
}
return labels.join(" ")
}
function parentPathFor(id) {
var entry = root.item(id)
if (!entry || !entry.parent || entry.parent === "root") return ""
return root.pathFor(entry.parent)
}
function breadcrumbFor(id) {
var path = root.pathFor(id)
return path ? ("Go " + path) : "Go"
}
function isDescendantOf(id, ancestorId) {
if (ancestorId === "root") return id !== "root"
var current = root.item(id)
var guard = 0
while (current && current.parent && guard < 32) {
if (current.parent === ancestorId) return true
current = root.item(current.parent)
guard += 1
}
return false
}
function childCount(id) {
var count = 0
for (var i = 0; i < root.itemOrder.length; i++) {
var entry = root.item(root.itemOrder[i])
if (entry && entry.parent === id) count += 1
}
return count
}
function matchesQuery(entry, query) {
if (!entry || entry.id === "root") return false
var haystack = (entry.label + " " + root.pathFor(entry.id) + " " + entry.keywords + " " + entry.description).toLowerCase()
var terms = query.toLowerCase().trim().split(/\s+/)
for (var i = 0; i < terms.length; i++) {
if (terms[i] && haystack.indexOf(terms[i]) === -1) return false
}
return true
}
function searchScore(entry, query) {
var needle = query.toLowerCase().trim()
var label = entry.label.toLowerCase()
var path = root.pathFor(entry.id).toLowerCase()
var keywords = entry.keywords.toLowerCase()
var parent = root.item(entry.parent)
var parentLabel = parent ? parent.label.toLowerCase() : ""
var score = 80
if (label === needle) score = entry.parent === "root" ? 2 : 0
else if (label.indexOf(needle) === 0) score = 10
else if (path.indexOf(needle) === 0) score = entry.kind === "action" ? 12 : 14
else if (parentLabel === needle) score = entry.kind === "action" ? 18 : 20
else if (label.indexOf(needle) >= 0) score = 30
else if (path.indexOf(needle) >= 0) score = 40
else if (keywords.indexOf(needle) >= 0) score = 50
if (entry.kind === "menu" || entry.kind === "link") score -= 2
return score * 1000 + root.depthFor(entry.id) * 25 + entry.order
}
function displayRow(entry, detail, score, section) {
var target = entry.kind === "link" ? entry.target : entry.id
return {
itemId: entry.id,
kind: entry.kind,
icon: entry.icon,
label: entry.label,
target: target,
detail: detail || "",
path: root.pathFor(entry.id),
childCount: (entry.kind === "menu" || entry.kind === "link") ? root.childCount(target) : 0,
action: entry.action || "",
provider: entry.provider || "",
score: score || 0,
section: section || ""
}
}
function rebuildDisplay() {
displayModel.clear()
if (!root.rowsLoaded) return
var active = root.item(root.activeMenu) ? root.activeMenu : "root"
root.activeMenu = active
var rows = []
var query = root.filterText.trim()
root.searchDivider = false
if (query) {
var currentRows = []
var drilldownRows = []
for (var i = 0; i < root.itemOrder.length; i++) {
var entry = root.item(root.itemOrder[i])
if (!entry || entry.id === "root") continue
if (!root.isDescendantOf(entry.id, active)) continue
if (!root.matchesQuery(entry, query)) continue
var detail = root.parentPathFor(entry.id)
var row = root.displayRow(entry, detail, root.searchScore(entry, query))
if (entry.parent === active) currentRows.push(row)
else drilldownRows.push(row)
}
var searchSort = function(a, b) {
if (a.score !== b.score) return a.score - b.score
return a.path.localeCompare(b.path)
}
currentRows.sort(searchSort)
drilldownRows.sort(searchSort)
root.searchDivider = currentRows.length > 0 && drilldownRows.length > 0
if (root.searchDivider) {
for (var d = 0; d < drilldownRows.length; d++) drilldownRows[d].section = "drilldown"
}
rows = currentRows.concat(drilldownRows)
} else {
if (active !== "root") {
var parentTarget = root.item(active).parent || "root"
var backTarget = root.navStack.length > 0 ? root.navStack[root.navStack.length - 1] : parentTarget
rows.push({ itemId: "__back", kind: "back", icon: "", label: "Back", target: backTarget, detail: root.breadcrumbFor(backTarget), path: "", childCount: 0, action: "", score: -1, section: "" })
}
for (var j = 0; j < root.itemOrder.length; j++) {
var child = root.item(root.itemOrder[j])
if (!child || child.parent !== active) continue
rows.push(root.displayRow(child, child.description, child.order))
}
}
for (var k = 0; k < rows.length; k++) displayModel.append(rows[k])
layoutSerial += 1
if (displayModel.count === 0) selectedIndex = 0
else if (selectedIndex >= displayModel.count) selectedIndex = displayModel.count - 1
else if (selectedIndex < 0) selectedIndex = 0
Qt.callLater(function() {
if (displayModel.count > 0) resultList.positionViewAtIndex(root.selectedIndex, ListView.Contain)
})
}
function select(delta) {
if (displayModel.count === 0) return
selectedIndex += delta
if (selectedIndex < 0) selectedIndex = 0
if (selectedIndex >= displayModel.count) selectedIndex = displayModel.count - 1
resultList.positionViewAtIndex(selectedIndex, ListView.Contain)
}
function setFilter(nextFilter) {
root.filterText = nextFilter
root.selectedIndex = 0
if (root.filterText.trim()) root.loadProvidersForSearch()
root.rebuildDisplay()
}
function setActiveMenu(id, pushHistory) {
if (!root.item(id)) id = "root"
if (pushHistory && id !== root.activeMenu) root.navStack = root.navStack.concat([root.activeMenu])
root.activeMenu = id
root.filterText = ""
root.selectedIndex = 0
root.rebuildDisplay()
root.loadProviderForMenu(id)
}
function goBack() {
if (root.activeMenu === "root") return false
if (root.navStack.length > 0) {
var previous = root.navStack[root.navStack.length - 1]
root.navStack = root.navStack.slice(0, root.navStack.length - 1)
root.setActiveMenu(previous, false)
return true
}
var active = root.item(root.activeMenu)
root.setActiveMenu((active && active.parent) ? active.parent : "root", false)
return true
}
function activateIndex(index) {
if (index < 0 || index >= displayModel.count) return
var row = displayModel.get(index)
if (row.kind === "back") {
root.goBack()
} else if (row.kind === "menu" || row.kind === "link") {
root.setActiveMenu(row.target || row.itemId, true)
} else {
root.applySelected(row.itemId, row.action)
}
}
function releaseNextDoneFile() {
if (releaseProc.running || doneFilesToRelease.length === 0) return
var path = doneFilesToRelease.shift()
releaseProc.command = ["bash", "-lc", ": > " + shellQuote(path)]
releaseProc.running = true
}
function finishDoneFile(path) {
if (!path) return
doneFilesToRelease.push(path)
releaseNextDoneFile()
}
function resetRequest() {
requestActive = false
selectionFile = ""
doneFile = ""
}
function applySelected(id, action) {
if (!id || !selectionFile || !doneFile) {
cancel()
return
}
var activeSelectionFile = selectionFile
var activeDoneFile = doneFile
applySerial = requestSerial
resetRequest()
opened = false
applyProc.command = ["bash", "-lc", "printf '%s\\t%s\\n' " + shellQuote(id) + " " + shellQuote(action || "") + " > " + shellQuote(activeSelectionFile) + "; : > " + shellQuote(activeDoneFile)]
applyProc.running = true
}
function cancel() {
if (requestActive) finishDoneFile(doneFile)
resetRequest()
opened = false
filterText = ""
}
function closeMenu(nextDoneFile) {
requestSerial += 1
if (requestActive) finishDoneFile(doneFile)
if (nextDoneFile && nextDoneFile !== doneFile) finishDoneFile(nextDoneFile)
resetRequest()
opened = false
filterText = ""
}
function openExistingMenu(initialMenu, nextSelectionFile, nextDoneFile) {
requestSerial += 1
if (requestActive && doneFile && doneFile !== nextDoneFile) finishDoneFile(doneFile)
selectionFile = nextSelectionFile
doneFile = nextDoneFile
requestActive = !!doneFile
activeMenu = root.item(initialMenu) ? initialMenu : "root"
navStack = []
filterText = ""
selectedIndex = 0
opened = true
rebuildDisplay()
loadProviderForMenu(activeMenu)
Qt.callLater(function() { keyCatcher.forceActiveFocus() })
}
function openMenu(menuJson, initialMenu, nextSelectionFile, nextDoneFile, colorsRaw) {
loadMenuJson(menuJson)
if (colorsRaw) loadColors(colorsRaw)
providersLoaded = ({})
providerQueue = []
openExistingMenu(initialMenu, nextSelectionFile, nextDoneFile)
}
function loadColors(raw) {
try {
var colors = JSON.parse(raw || "{}")
root.accent = colors.accent || colors.primary || root.accent
root.background = colors.background || root.background
root.foreground = colors.foreground || colors.backgroundText || root.foreground
root.border = colors.border || root.foreground
} catch (e) {}
}
function loadStyle(raw) {
try {
var style = JSON.parse(raw || "{}")
root.cornerRadius = Number(style.radius || 0)
} catch (e) {}
}
ListModel { id: displayModel }
Process {
id: providerProc
property string menuId: ""
property string output: ""
stdout: SplitParser {
onRead: function(data) {
providerProc.output += data + "\n"
}
}
onExited: {
root.mergeProviderJson(output, menuId)
if (root.filterText.trim()) root.loadProvidersForSearch()
root.startNextProvider()
}
}
SocketServer {
active: true
path: root.socketPath
handler: Socket {
id: clientSocket
parser: SplitParser {
onRead: function(message) {
var fields = message.split("\t")
if (fields[0] === "open") {
root.openExistingMenu(fields[1] || "root", fields[2] || "", fields[3] || "")
} else {
root.closeMenu(fields[3] || "")
}
clientSocket.connected = false
}
}
}
}
FileView {
path: root.startupMenuJsonFile
onLoaded: root.openMenu(text(), root.startupInitialMenu, root.startupSelectionFile, root.startupDoneFile, root.decodeField(root.startupColorsRaw))
}
FileView {
path: root.colorsFile
watchChanges: true
onLoaded: root.loadColors(text())
onFileChanged: { reload(); root.loadColors(text()) }
}
FileView {
path: root.styleFile
watchChanges: true
onLoaded: root.loadStyle(text())
onFileChanged: { reload(); root.loadStyle(text()) }
}
Process {
id: applyProc
onExited: {
if (root.applySerial === root.requestSerial) root.opened = false
}
}
Process {
id: releaseProc
onExited: root.releaseNextDoneFile()
}
PanelWindow {
id: panel
visible: root.opened && root.rowsLoaded
anchors { top: true; bottom: true; left: true; right: true }
color: "transparent"
WlrLayershell.namespace: "omarchy-menu"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
exclusionMode: ExclusionMode.Ignore
MouseArea {
anchors.fill: parent
onClicked: root.cancel()
}
Rectangle {
id: card
width: root.cardWidth
height: root.cardHeight
radius: root.cornerRadius
anchors.centerIn: parent
color: root.background
border.color: root.withAlpha(root.border, 0.36)
border.width: 1
MouseArea { anchors.fill: parent; onClicked: {} }
Item {
id: keyCatcher
anchors.fill: parent
focus: true
Keys.priority: Keys.BeforeItem
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
if (root.filterText) root.setFilter("")
else root.cancel()
event.accepted = true
} else if (event.key === Qt.Key_Backspace) {
if (root.filterText.length > 0) root.setFilter(root.filterText.slice(0, -1))
else root.goBack()
event.accepted = true
} else if (event.key === Qt.Key_Up) {
root.select(-1)
event.accepted = true
} else if (event.key === Qt.Key_Down) {
root.select(1)
event.accepted = true
} else if (event.key === Qt.Key_PageUp) {
root.select(-6)
event.accepted = true
} else if (event.key === Qt.Key_PageDown) {
root.select(6)
event.accepted = true
} else if (event.key === Qt.Key_Left) {
if (!root.filterText) root.goBack()
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_Right) {
root.activateIndex(root.selectedIndex)
event.accepted = true
} else if (event.text && event.text.length === 1 && event.text.charCodeAt(0) >= 32 && event.text.charCodeAt(0) !== 127 && (event.modifiers === Qt.NoModifier || event.modifiers === Qt.ShiftModifier)) {
root.setFilter(root.filterText + event.text)
event.accepted = true
}
}
}
Column {
anchors.fill: parent
anchors.margins: root.contentMargin
spacing: root.contentSpacing
Rectangle {
width: parent.width
height: root.headerHeight
radius: root.cornerRadius
color: "transparent"
border.width: 0
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: root.filterText || ((root.item(root.activeMenu) ? root.item(root.activeMenu).label : "Go") + "…")
color: root.foreground
opacity: root.filterText ? 1 : 0.58
font.family: root.fontFamily
font.pixelSize: 16
elide: Text.ElideRight
}
}
Item {
width: parent.width
height: root.visibleRowsHeight
ListView {
id: resultList
anchors.fill: parent
model: displayModel
clip: true
spacing: root.rowSpacing
boundsBehavior: Flickable.StopAtBounds
section.property: "section"
section.criteria: ViewSection.FullString
section.delegate: Item {
required property string section
width: ListView.view.width
height: section === "drilldown" ? root.dividerHeight : 0
visible: section === "drilldown"
Rectangle {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.right: parent.right
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
height: 1
color: root.withAlpha(root.foreground, 0.2)
}
}
delegate: Rectangle {
id: row
required property int index
required property string itemId
required property string kind
required property string icon
required property string label
required property string target
required property string detail
required property string path
required property string action
required property int childCount
width: ListView.view.width
height: root.rowHeightForDetail(row.detail)
radius: root.cornerRadius
color: index === root.selectedIndex ? root.withAlpha(root.foreground, 0.08) : root.withAlpha(root.foreground, mouseArea.containsMouse ? 0.045 : 0)
border.color: "transparent"
border.width: 0
Rectangle {
visible: false
width: 4
height: parent.height - 18
radius: Math.min(root.cornerRadius, 4)
color: root.accent
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
}
Text {
id: iconText
text: row.icon
color: index === root.selectedIndex ? root.accent : root.foreground
opacity: row.kind === "back" ? 0.7 : 1
font.family: root.fontFamily
font.pixelSize: 18
width: 36
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.left: parent.left
anchors.leftMargin: 8
y: contentColumn.y + labelText.y + (labelText.height - height) / 2
}
Column {
id: contentColumn
anchors.left: iconText.right
anchors.leftMargin: 6
anchors.right: trail.left
anchors.rightMargin: 6
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Text {
id: labelText
width: parent.width
text: row.label
color: index === root.selectedIndex ? root.accent : root.foreground
font.family: root.fontFamily
font.pixelSize: 16
font.weight: Font.Medium
elide: Text.ElideRight
}
Text {
width: parent.width
text: row.detail
visible: root.filterText && row.detail.length > 0
color: root.foreground
opacity: 0.52
font.family: root.fontFamily
font.pixelSize: 11
elide: Text.ElideRight
}
}
Row {
id: trail
width: 14
anchors.right: parent.right
anchors.rightMargin: 8
y: contentColumn.y + labelText.y + (labelText.height - height) / 2
spacing: 0
Text {
visible: false
text: row.childCount
color: root.foreground
opacity: 0.45
font.family: root.fontFamily
font.pixelSize: 12
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: row.kind === "menu" || row.kind === "link" ? "" : (row.kind === "back" ? "" : "↵")
color: index === root.selectedIndex ? root.accent : root.foreground
opacity: row.kind === "back" ? 0 : 0.36
font.family: root.fontFamily
font.pixelSize: 16
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.activateIndex(row.index)
}
}
}
Column {
anchors.centerIn: parent
spacing: 8
visible: displayModel.count === 0
Text {
text: "󰈉"
color: root.accent
opacity: 0.8
font.family: root.fontFamily
font.pixelSize: 28
horizontalAlignment: Text.AlignHCenter
width: 320
}
Text {
text: root.filterText ? "No matches for “" + root.filterText + "”" : "Nothing here yet"
color: root.foreground
opacity: 0.7
font.family: root.fontFamily
font.pixelSize: 14
horizontalAlignment: Text.AlignHCenter
width: 320
}
}
}
Item {
width: parent.width
height: 0
}
}
}
}
}
+568
View File
@@ -0,0 +1,568 @@
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import QtQuick
import QtQuick.Effects
import QtQuick.Shapes
ShellRoot {
id: root
property string imageDirs: Quickshell.env("OMARCHY_IMAGE_SELECTOR_DIRS") || Quickshell.env("OMARCHY_IMAGE_SELECTOR_DIR") || Quickshell.env("OMARCHY_STOCK_BACKGROUNDS_DIR") || (Quickshell.env("HOME") + "/.config/omarchy/current/theme/backgrounds")
property string imageRows: ""
property string selectionFile: Quickshell.env("OMARCHY_IMAGE_SELECTOR_SELECTION_FILE") || Quickshell.env("OMARCHY_BACKGROUND_SELECTION_FILE")
property string selectedImage: Quickshell.env("OMARCHY_IMAGE_SELECTOR_SELECTED")
property string colorsFile: Quickshell.env("OMARCHY_IMAGE_SELECTOR_COLORS_FILE") || (Quickshell.env("HOME") + "/.config/omarchy/current/theme/quickshell.json")
property int selectedIndex: 0
property bool imagesLoaded: false
property bool opened: false
property bool showLabels: false
property bool filterable: false
property bool requestActive: false
property int requestSerial: 0
property int applySerial: 0
property string doneFile: ""
property string filterText: ""
property var doneFilesToRelease: []
property string socketPath: (Quickshell.env("XDG_RUNTIME_DIR") || ("/run/user/" + Quickshell.env("UID"))) + "/omarchy-image-selector.sock"
property color accent: "#798186"
property color background: "#101315"
property color foreground: "#cacccc"
property int expandedWidth: 768
property int expandedHeight: 475
property int sliceWidth: 108
property int sliceHeight: 432
property int sliceSpacing: -30
property int skewOffset: 28
property int bottomChromeHeight: showLabels ? (filterable ? 104 : 74) : (filterable ? 60 : 30)
function fileUrl(path) {
return "file://" + path.split("/").map(encodeURIComponent).join("/")
}
function shellQuote(value) {
return "'" + String(value).replace(/'/g, "'\\''") + "'"
}
function decodeField(value) {
return String(value || "").replace(/\v/g, "\n").replace(/\f/g, "\t")
}
function withAlpha(color, alpha) {
return Qt.rgba(color.r, color.g, color.b, alpha)
}
function currentPath() {
if (imageArray.length === 0 || !itemMatches(selectedIndex)) return ""
return imageArray[selectedIndex].filePath
}
function nameForPath(path) {
return path.split("/").pop().replace(/\.[^/.]+$/, "")
}
function labelForPath(path) {
return nameForPath(path).replace(/[-_]+/g, " ").replace(/\b\w/g, function(match) { return match.toUpperCase() })
}
function currentLabel() {
var path = currentPath()
if (!path) return filterText ? "No matches" : ""
return labelForPath(path)
}
function itemMatches(index) {
if (index < 0 || index >= imageArray.length) return false
if (!filterText) return true
var path = imageArray[index].filePath
var needle = filterText.toLowerCase()
return nameForPath(path).toLowerCase().indexOf(needle) !== -1 || labelForPath(path).toLowerCase().indexOf(needle) !== -1
}
function matchingCount() {
if (!filterText) return imageArray.length
var count = 0
for (var i = 0; i < imageArray.length; i++) {
if (itemMatches(i)) count++
}
return count
}
function firstMatchingIndex() {
for (var i = 0; i < imageArray.length; i++) {
if (itemMatches(i)) return i
}
return -1
}
function filteredPosition(index) {
if (!filterText) return index
var position = 0
for (var i = 0; i < index; i++) {
if (itemMatches(i)) position++
}
return position
}
function selectedFilteredPosition() {
if (!filterText) return selectedIndex
return itemMatches(selectedIndex) ? filteredPosition(selectedIndex) : 0
}
function select(index, immediate) {
if (imageArray.length === 0) return
if (index < 0) index = 0
else if (index >= imageArray.length) index = imageArray.length - 1
if (!itemMatches(index)) return
if (index === selectedIndex && immediate !== true) return
selectedIndex = index
}
function selectAdjacent(direction) {
var count = imageArray.length
if (count === 0) return
var index = selectedIndex
for (var i = 0; i < count; i++) {
index = (index + direction + count) % count
if (itemMatches(index)) {
select(index)
return
}
}
}
function updateFilter(nextFilterText) {
filterText = nextFilterText
if (!itemMatches(selectedIndex)) {
var first = firstMatchingIndex()
if (first >= 0) selectedIndex = first
}
}
function releaseNextDoneFile() {
if (releaseProc.running || doneFilesToRelease.length === 0) return
var path = doneFilesToRelease.shift()
releaseProc.command = ["bash", "-lc", ": > " + shellQuote(path)]
releaseProc.running = true
}
function finishDoneFile(path) {
if (!path) return
doneFilesToRelease.push(path)
releaseNextDoneFile()
}
function applySelected() {
var path = currentPath()
if (!path || !selectionFile) {
cancel()
return
}
var activeSelectionFile = selectionFile
var activeDoneFile = doneFile
applySerial = requestSerial
requestActive = false
selectionFile = ""
doneFile = ""
applyProc.command = ["bash", "-lc", "printf '%s\\n' " + shellQuote(path) + " > " + shellQuote(activeSelectionFile) + "; : > " + shellQuote(activeDoneFile)]
applyProc.running = true
}
function cancel() {
if (requestActive)
finishDoneFile(doneFile)
requestActive = false
selectionFile = ""
doneFile = ""
root.opened = false
}
function closeSelector(nextDoneFile) {
requestSerial += 1
if (requestActive)
finishDoneFile(doneFile)
if (nextDoneFile && nextDoneFile !== doneFile)
finishDoneFile(nextDoneFile)
requestActive = false
selectionFile = ""
doneFile = ""
filterText = ""
root.opened = false
}
function loadRows(rows) {
var newImages = []
var seen = {}
var paths = rows.split("\n")
for (var i = 0; i < paths.length; i++) {
var row = paths[i]
if (!row) continue
var columns = row.split("\t")
var path = columns[0]
if (!path) continue
var fileName = path.split("/").pop()
if (seen[fileName]) continue
seen[fileName] = true
newImages.push({
filePath: path,
fileName: fileName,
thumbnailPath: columns[1] || path
})
}
root.imageArray = newImages
root.select(root.selectedImageIndex(), true)
root.imagesLoaded = true
root.opened = true
carousel.forceActiveFocus()
}
function openSelector(nextImageDirs, nextImageRows, nextSelectedImage, nextSelectionFile, nextDoneFile, nextColorsFile, nextColorsRaw, nextShowLabels, nextFilterable) {
if (requestActive && doneFile && doneFile !== nextDoneFile)
finishDoneFile(doneFile)
requestSerial += 1
imageDirs = nextImageDirs
imageRows = nextImageRows
selectedImage = nextSelectedImage
selectionFile = nextSelectionFile
doneFile = nextDoneFile
requestActive = !!doneFile
showLabels = nextShowLabels === true || nextShowLabels === "true"
filterable = nextFilterable === true || nextFilterable === "true"
filterText = ""
colorsFile = nextColorsFile || (Quickshell.env("HOME") + "/.config/omarchy/current/theme/quickshell.json")
if (nextColorsRaw)
loadColors(nextColorsRaw)
imageArray = []
selectedIndex = 0
imagesLoaded = false
opened = false
if (imageRows) {
loadRows(imageRows)
} else {
loadImagesProc.output = ""
loadImagesProc.running = true
}
}
property var imageArray: []
function selectedImageIndex() {
for (var i = 0; i < imageArray.length; i++) {
if (imageArray[i].filePath === selectedImage)
return i
}
return 0
}
Process {
id: loadImagesProc
property string output: ""
command: ["bash", "-lc", "cache_dir=${XDG_CACHE_HOME:-$HOME/.cache}/omarchy/image-selector; while IFS= read -r dir; do [[ -n $dir && -d $dir ]] && find -L \"$dir\" -maxdepth 1 -type f \\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \\) -print0; done <<< " + shellQuote(root.imageDirs) + " | sort -z | while IFS= read -r -d '' image; do hash=$(md5sum \"$image\" | cut -d ' ' -f 1); thumb=\"$cache_dir/$hash.jpg\"; [[ -f $thumb ]] || thumb=$image; printf '%s\\t%s\\n' \"$image\" \"$thumb\"; done"]
stdout: SplitParser {
onRead: function(data) {
loadImagesProc.output += data + "\n"
}
}
onExited: {
root.loadRows(output)
}
}
Component.onCompleted: {
if (selectionFile)
openSelector(imageDirs, "", selectedImage, selectionFile, Quickshell.env("OMARCHY_IMAGE_SELECTOR_DONE_FILE"), colorsFile, "", false, false)
}
IpcHandler {
target: "image-selector"
function open(imageDirs: string, imageRows: string, selectedImage: string, selectionFile: string, doneFile: string, colorsFile: string): void {
root.openSelector(imageDirs, imageRows, selectedImage, selectionFile, doneFile, colorsFile, "", false, false)
}
}
SocketServer {
active: true
path: root.socketPath
handler: Socket {
id: clientSocket
parser: SplitParser {
onRead: function(message) {
var fields = message.split("\t")
if (root.opened) {
root.closeSelector(fields[3] || "")
clientSocket.connected = false
return
}
root.openSelector("", root.decodeField(fields[0]), fields[1] || "", fields[2] || "", fields[3] || "", "", root.decodeField(fields[4]), fields[5] || "false", fields[6] || "false")
clientSocket.connected = false
}
}
}
}
FileView {
path: root.colorsFile
watchChanges: true
onLoaded: root.loadColors(text())
onFileChanged: { reload(); root.loadColors(text()) }
}
function loadColors(raw) {
try {
var colors = JSON.parse(raw || "{}")
root.accent = colors.primary || root.accent
root.background = colors.background || root.background
root.foreground = colors.backgroundText || root.foreground
} catch (e) {}
}
Process {
id: applyProc
onExited: {
if (root.applySerial === root.requestSerial)
root.opened = false
}
}
Process {
id: releaseProc
onExited: root.releaseNextDoneFile()
}
PanelWindow {
id: panel
visible: root.opened && root.imagesLoaded
anchors { top: true; bottom: true; left: true; right: true }
color: "transparent"
WlrLayershell.namespace: "omarchy-image-selector"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
exclusionMode: ExclusionMode.Ignore
Rectangle {
anchors.fill: parent
color: root.withAlpha(root.background, 0.72)
}
MouseArea {
anchors.fill: parent
onClicked: root.cancel()
}
Item {
id: card
width: Math.min(parent.width - 80, root.expandedWidth + 13 * (root.sliceWidth + root.sliceSpacing) + 40)
height: root.expandedHeight + 30 + root.bottomChromeHeight
anchors.centerIn: parent
MouseArea { anchors.fill: parent; onClicked: {} }
Item {
id: carousel
anchors.top: parent.top
anchors.topMargin: 30
anchors.bottom: parent.bottom
anchors.bottomMargin: root.bottomChromeHeight
anchors.horizontalCenter: parent.horizontalCenter
width: root.expandedWidth + 13 * (root.sliceWidth + root.sliceSpacing)
clip: false
focus: true
readonly property real itemStep: root.sliceWidth + root.sliceSpacing
readonly property real previewX: (width - root.expandedWidth) / 2
Keys.priority: Keys.BeforeItem
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
if (root.filterText) {
root.updateFilter("")
} else {
root.cancel()
}
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
root.applySelected()
event.accepted = true
} else if (event.key === Qt.Key_Backspace && root.filterable) {
if (root.filterText.length > 0)
root.updateFilter(root.filterText.slice(0, -1))
event.accepted = true
} else if (event.key === Qt.Key_Left || (event.key === Qt.Key_Tab && event.modifiers & Qt.ShiftModifier) || event.key === Qt.Key_Backtab) {
root.selectAdjacent(-1)
event.accepted = true
} else if (event.key === Qt.Key_Right || event.key === Qt.Key_Tab) {
root.selectAdjacent(1)
event.accepted = true
} else if (root.filterable && event.text && event.text.length === 1 && event.text.charCodeAt(0) >= 32 && event.text.charCodeAt(0) !== 127 && (event.modifiers === Qt.NoModifier || event.modifiers === Qt.ShiftModifier)) {
root.updateFilter(root.filterText + event.text)
event.accepted = true
}
}
Component.onCompleted: forceActiveFocus()
Repeater {
model: root.imageArray.length
delegate: Item {
id: item
required property int index
readonly property var imageData: root.imageArray[index]
readonly property string filePath: imageData ? imageData.filePath : ""
readonly property string fileName: imageData ? imageData.fileName : ""
readonly property string thumbnailPath: imageData ? imageData.thumbnailPath : ""
readonly property bool matched: root.itemMatches(index)
readonly property int relativeIndex: root.filteredPosition(index) - root.selectedFilteredPosition()
readonly property bool selected: matched && index === root.selectedIndex
readonly property bool nearby: matched && Math.abs(relativeIndex) <= 16
visible: nearby
x: selected ? carousel.previewX : (relativeIndex < 0 ? carousel.previewX + relativeIndex * carousel.itemStep : carousel.previewX + root.expandedWidth + root.sliceSpacing + (relativeIndex - 1) * carousel.itemStep)
width: selected ? root.expandedWidth : root.sliceWidth
height: selected ? root.expandedHeight : root.sliceHeight
y: selected ? 0 : (root.expandedHeight - root.sliceHeight) / 2
z: selected ? 100 : 50 - Math.min(Math.abs(relativeIndex), 40)
readonly property real skAbs: Math.abs(root.skewOffset)
readonly property real topLeft: root.skewOffset >= 0 ? skAbs : 0
readonly property real topRight: root.skewOffset >= 0 ? width : width - skAbs
readonly property real bottomRight: root.skewOffset >= 0 ? width - skAbs : width
readonly property real bottomLeft: root.skewOffset >= 0 ? 0 : skAbs
Item {
id: maskShape
anchors.fill: parent
visible: false
layer.enabled: true
Shape {
anchors.fill: parent
antialiasing: true
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: "white"
strokeColor: "transparent"
startX: item.topLeft; startY: 0
PathLine { x: item.topRight; y: 0 }
PathLine { x: item.bottomRight; y: item.height }
PathLine { x: item.bottomLeft; y: item.height }
PathLine { x: item.topLeft; y: 0 }
}
}
}
Item {
anchors.fill: parent
layer.enabled: true
layer.smooth: true
layer.effect: MultiEffect {
maskEnabled: true
maskSource: maskShape
maskThresholdMin: 0.3
maskSpreadAtMin: 0.3
}
Image {
id: image
anchors.fill: parent
source: item.nearby ? root.fileUrl(item.thumbnailPath) : ""
fillMode: Image.PreserveAspectCrop
asynchronous: true
cache: true
smooth: true
}
Rectangle {
anchors.fill: parent
color: root.withAlpha(root.background, item.selected ? 0 : 0.42)
}
}
Shape {
anchors.fill: parent
antialiasing: true
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: "transparent"
strokeColor: item.selected ? root.accent : root.withAlpha(root.foreground, 0.28)
strokeWidth: item.selected ? 3 : 1
startX: item.topLeft; startY: 0
PathLine { x: item.topRight; y: 0 }
PathLine { x: item.bottomRight; y: item.height }
PathLine { x: item.bottomLeft; y: item.height }
PathLine { x: item.topLeft; y: 0 }
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: item.selected ? root.applySelected() : root.select(index)
}
}
}
}
Text {
id: selectedLabel
visible: root.showLabels
anchors.top: carousel.bottom
anchors.topMargin: 16
anchors.horizontalCenter: carousel.horizontalCenter
width: root.expandedWidth
text: root.currentLabel()
color: root.foreground
style: Text.Outline
styleColor: root.withAlpha(root.background, 0.7)
font.pixelSize: 24
font.weight: Font.DemiBold
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
Text {
visible: root.filterable && root.filterText
anchors.top: selectedLabel.bottom
anchors.topMargin: 8
anchors.horizontalCenter: carousel.horizontalCenter
width: root.expandedWidth
text: root.filterText
color: root.foreground
opacity: 0.85
style: Text.Outline
styleColor: root.withAlpha(root.background, 0.7)
font.pixelSize: 14
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
}
}
}
+116 -116
View File
@@ -1,137 +1,137 @@
-- Gum Style (generic) Variables
hl.env("FOREGROUND", "#{{ foreground }}")
hl.env("BACKGROUND", "#{{ background }}")
hl.env("BORDER_FOREGROUND", "#{{ accent }}")
hl.env("BORDER_BACKGROUND", "#{{ background }}")
hl.env("FOREGROUND", "{{ foreground }}")
hl.env("BACKGROUND", "{{ background }}")
hl.env("BORDER_FOREGROUND", "{{ accent }}")
hl.env("BORDER_BACKGROUND", "{{ background }}")
-- Gum Confirm Style Variables
hl.env("GUM_CONFIRM_PROMPT_FOREGROUND", "#{{ accent }}")
hl.env("GUM_CONFIRM_PROMPT_BACKGROUND", "#{{ background }}")
hl.env("GUM_CONFIRM_SELECTED_FOREGROUND", "#{{ selection_foreground }}")
hl.env("GUM_CONFIRM_SELECTED_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_CONFIRM_UNSELECTED_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_CONFIRM_UNSELECTED_BACKGROUND", "#{{ background }}")
hl.env("GUM_CONFIRM_PROMPT_FOREGROUND", "{{ accent }}")
hl.env("GUM_CONFIRM_PROMPT_BACKGROUND", "{{ background }}")
hl.env("GUM_CONFIRM_SELECTED_FOREGROUND", "{{ selection_foreground }}")
hl.env("GUM_CONFIRM_SELECTED_BACKGROUND", "{{ selection_background }}")
hl.env("GUM_CONFIRM_UNSELECTED_FOREGROUND", "{{ foreground }}")
hl.env("GUM_CONFIRM_UNSELECTED_BACKGROUND", "{{ background }}")
-- Gum Input Style Variables
hl.env("GUM_INPUT_PROMPT_FOREGROUND", "#{{ accent }}")
hl.env("GUM_INPUT_PROMPT_BACKGROUND", "#{{ background }}")
hl.env("GUM_INPUT_PLACEHOLDER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_INPUT_PLACEHOLDER_BACKGROUND", "#{{ background }}")
hl.env("GUM_INPUT_CURSOR_FOREGROUND", "#{{ cursor }}")
hl.env("GUM_INPUT_CURSOR_BACKGROUND", "#{{ background }}")
hl.env("GUM_INPUT_HEADER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_INPUT_HEADER_BACKGROUND", "#{{ background }}")
hl.env("GUM_INPUT_PROMPT_FOREGROUND", "{{ accent }}")
hl.env("GUM_INPUT_PROMPT_BACKGROUND", "{{ background }}")
hl.env("GUM_INPUT_PLACEHOLDER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_INPUT_PLACEHOLDER_BACKGROUND", "{{ background }}")
hl.env("GUM_INPUT_CURSOR_FOREGROUND", "{{ cursor }}")
hl.env("GUM_INPUT_CURSOR_BACKGROUND", "{{ background }}")
hl.env("GUM_INPUT_HEADER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_INPUT_HEADER_BACKGROUND", "{{ background }}")
-- Gum Choose Style Variables
hl.env("GUM_CHOOSE_CURSOR_FOREGROUND", "#{{ accent }}")
hl.env("GUM_CHOOSE_CURSOR_BACKGROUND", "#{{ background }}")
hl.env("GUM_CHOOSE_HEADER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_CHOOSE_HEADER_BACKGROUND", "#{{ background }}")
hl.env("GUM_CHOOSE_ITEM_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_CHOOSE_ITEM_BACKGROUND", "#{{ background }}")
hl.env("GUM_CHOOSE_SELECTED_FOREGROUND", "#{{ selection_foreground }}")
hl.env("GUM_CHOOSE_SELECTED_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_CHOOSE_CURSOR_FOREGROUND", "{{ accent }}")
hl.env("GUM_CHOOSE_CURSOR_BACKGROUND", "{{ background }}")
hl.env("GUM_CHOOSE_HEADER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_CHOOSE_HEADER_BACKGROUND", "{{ background }}")
hl.env("GUM_CHOOSE_ITEM_FOREGROUND", "{{ foreground }}")
hl.env("GUM_CHOOSE_ITEM_BACKGROUND", "{{ background }}")
hl.env("GUM_CHOOSE_SELECTED_FOREGROUND", "{{ selection_foreground }}")
hl.env("GUM_CHOOSE_SELECTED_BACKGROUND", "{{ selection_background }}")
-- Gum Filter Style Variables
hl.env("GUM_FILTER_PROMPT_FOREGROUND", "#{{ accent }}")
hl.env("GUM_FILTER_PROMPT_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_TEXT_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_FILTER_TEXT_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_MATCH_FOREGROUND", "#{{ accent }}")
hl.env("GUM_FILTER_CURSOR_TEXT_FOREGROUND", "#{{ cursor }}")
hl.env("GUM_FILTER_CURSOR_TEXT_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_SELECTED_FOREGROUND", "#{{ selection_foreground }}")
hl.env("GUM_FILTER_SELECTED_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_FILTER_INDICATOR_FOREGROUND", "#{{ accent }}")
hl.env("GUM_FILTER_HEADER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_FILTER_MATCH_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_HEADER_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_PLACEHOLDER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_FILTER_PLACEHOLDER_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_INDICATOR_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_SELECTED_PREFIX_FOREGROUND", "#{{ selection_foreground }}")
hl.env("GUM_FILTER_SELECTED_PREFIX_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_FILTER_UNSELECTED_PREFIX_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_FILTER_UNSELECTED_PREFIX_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILTER_PROMPT_FOREGROUND", "{{ accent }}")
hl.env("GUM_FILTER_PROMPT_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_TEXT_FOREGROUND", "{{ foreground }}")
hl.env("GUM_FILTER_TEXT_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_MATCH_FOREGROUND", "{{ accent }}")
hl.env("GUM_FILTER_CURSOR_TEXT_FOREGROUND", "{{ cursor }}")
hl.env("GUM_FILTER_CURSOR_TEXT_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_SELECTED_FOREGROUND", "{{ selection_foreground }}")
hl.env("GUM_FILTER_SELECTED_BACKGROUND", "{{ selection_background }}")
hl.env("GUM_FILTER_INDICATOR_FOREGROUND", "{{ accent }}")
hl.env("GUM_FILTER_HEADER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_FILTER_MATCH_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_HEADER_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_PLACEHOLDER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_FILTER_PLACEHOLDER_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_INDICATOR_BACKGROUND", "{{ background }}")
hl.env("GUM_FILTER_SELECTED_PREFIX_FOREGROUND", "{{ selection_foreground }}")
hl.env("GUM_FILTER_SELECTED_PREFIX_BACKGROUND", "{{ selection_background }}")
hl.env("GUM_FILTER_UNSELECTED_PREFIX_FOREGROUND", "{{ color8 }}")
hl.env("GUM_FILTER_UNSELECTED_PREFIX_BACKGROUND", "{{ background }}")
-- Gum Table Style Variables
hl.env("GUM_TABLE_HEADER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_TABLE_HEADER_BACKGROUND", "#{{ background }}")
hl.env("GUM_TABLE_CELL_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_TABLE_CELL_BACKGROUND", "#{{ background }}")
hl.env("GUM_TABLE_BORDER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_TABLE_BORDER_BACKGROUND", "#{{ background }}")
hl.env("GUM_TABLE_SELECTED_FOREGROUND", "#{{ selection_foreground }}")
hl.env("GUM_TABLE_SELECTED_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_TABLE_HEADER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_TABLE_HEADER_BACKGROUND", "{{ background }}")
hl.env("GUM_TABLE_CELL_FOREGROUND", "{{ foreground }}")
hl.env("GUM_TABLE_CELL_BACKGROUND", "{{ background }}")
hl.env("GUM_TABLE_BORDER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_TABLE_BORDER_BACKGROUND", "{{ background }}")
hl.env("GUM_TABLE_SELECTED_FOREGROUND", "{{ selection_foreground }}")
hl.env("GUM_TABLE_SELECTED_BACKGROUND", "{{ selection_background }}")
-- Gum Spin Style Variables
hl.env("GUM_SPIN_SPINNER_FOREGROUND", "#{{ accent }}")
hl.env("GUM_SPIN_SPINNER_BACKGROUND", "#{{ background }}")
hl.env("GUM_SPIN_TITLE_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_SPIN_TITLE_BACKGROUND", "#{{ background }}")
hl.env("GUM_SPIN_SPINNER_FOREGROUND", "{{ accent }}")
hl.env("GUM_SPIN_SPINNER_BACKGROUND", "{{ background }}")
hl.env("GUM_SPIN_TITLE_FOREGROUND", "{{ foreground }}")
hl.env("GUM_SPIN_TITLE_BACKGROUND", "{{ background }}")
-- Gum File Style Variables
hl.env("GUM_FILE_CURSOR_FOREGROUND", "#{{ cursor }}")
hl.env("GUM_FILE_CURSOR_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_SYMLINK_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_FILE_SYMLINK_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_DIRECTORY_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_FILE_DIRECTORY_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_FILE_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_FILE_FILE_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_PERMISSIONS_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_FILE_PERMISSIONS_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_SELECTED_FOREGROUND", "#{{ selection_foreground }}")
hl.env("GUM_FILE_SELECTED_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_FILE_FILE_SIZE_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_FILE_FILE_SIZE_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_HEADER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_FILE_HEADER_BACKGROUND", "#{{ background }}")
hl.env("GUM_FILE_CURSOR_FOREGROUND", "{{ cursor }}")
hl.env("GUM_FILE_CURSOR_BACKGROUND", "{{ background }}")
hl.env("GUM_FILE_SYMLINK_FOREGROUND", "{{ foreground }}")
hl.env("GUM_FILE_SYMLINK_BACKGROUND", "{{ background }}")
hl.env("GUM_FILE_DIRECTORY_FOREGROUND", "{{ foreground }}")
hl.env("GUM_FILE_DIRECTORY_BACKGROUND", "{{ background }}")
hl.env("GUM_FILE_FILE_FOREGROUND", "{{ foreground }}")
hl.env("GUM_FILE_FILE_BACKGROUND", "{{ background }}")
hl.env("GUM_FILE_PERMISSIONS_FOREGROUND", "{{ color8 }}")
hl.env("GUM_FILE_PERMISSIONS_BACKGROUND", "{{ background }}")
hl.env("GUM_FILE_SELECTED_FOREGROUND", "{{ selection_foreground }}")
hl.env("GUM_FILE_SELECTED_BACKGROUND", "{{ selection_background }}")
hl.env("GUM_FILE_FILE_SIZE_FOREGROUND", "{{ color8 }}")
hl.env("GUM_FILE_FILE_SIZE_BACKGROUND", "{{ background }}")
hl.env("GUM_FILE_HEADER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_FILE_HEADER_BACKGROUND", "{{ background }}")
-- Gum Pager Style Variables
hl.env("GUM_PAGER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_PAGER_BACKGROUND", "#{{ background }}")
hl.env("GUM_PAGER_LINE_NUMBER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_PAGER_LINE_NUMBER_BACKGROUND", "#{{ background }}")
hl.env("GUM_PAGER_MATCH_FOREGROUND", "#{{ accent }}")
hl.env("GUM_PAGER_MATCH_BACKGROUND", "#{{ background }}")
hl.env("GUM_PAGER_MATCH_HIGH_FOREGROUND", "#{{ accent }}")
hl.env("GUM_PAGER_MATCH_HIGH_BACKGROUND", "#{{ background }}")
hl.env("GUM_PAGER_HELP_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_PAGER_HELP_BACKGROUND", "#{{ background }}")
hl.env("GUM_PAGER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_PAGER_BACKGROUND", "{{ background }}")
hl.env("GUM_PAGER_LINE_NUMBER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_PAGER_LINE_NUMBER_BACKGROUND", "{{ background }}")
hl.env("GUM_PAGER_MATCH_FOREGROUND", "{{ accent }}")
hl.env("GUM_PAGER_MATCH_BACKGROUND", "{{ background }}")
hl.env("GUM_PAGER_MATCH_HIGH_FOREGROUND", "{{ accent }}")
hl.env("GUM_PAGER_MATCH_HIGH_BACKGROUND", "{{ background }}")
hl.env("GUM_PAGER_HELP_FOREGROUND", "{{ color8 }}")
hl.env("GUM_PAGER_HELP_BACKGROUND", "{{ background }}")
-- Gum Write Style Variables
hl.env("GUM_WRITE_BASE_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_WRITE_BASE_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_CURSOR_LINE_NUMBER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_WRITE_CURSOR_LINE_NUMBER_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_CURSOR_LINE_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_WRITE_CURSOR_LINE_BACKGROUND", "#{{ selection_background }}")
hl.env("GUM_WRITE_CURSOR_FOREGROUND", "#{{ cursor }}")
hl.env("GUM_WRITE_CURSOR_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_END_OF_BUFFER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_WRITE_END_OF_BUFFER_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_LINE_NUMBER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_WRITE_LINE_NUMBER_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_HEADER_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_WRITE_HEADER_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_PLACEHOLDER_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_WRITE_PLACEHOLDER_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_PROMPT_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_WRITE_PROMPT_BACKGROUND", "#{{ background }}")
hl.env("GUM_WRITE_BASE_FOREGROUND", "{{ foreground }}")
hl.env("GUM_WRITE_BASE_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_CURSOR_LINE_NUMBER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_WRITE_CURSOR_LINE_NUMBER_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_CURSOR_LINE_FOREGROUND", "{{ foreground }}")
hl.env("GUM_WRITE_CURSOR_LINE_BACKGROUND", "{{ selection_background }}")
hl.env("GUM_WRITE_CURSOR_FOREGROUND", "{{ cursor }}")
hl.env("GUM_WRITE_CURSOR_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_END_OF_BUFFER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_WRITE_END_OF_BUFFER_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_LINE_NUMBER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_WRITE_LINE_NUMBER_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_HEADER_FOREGROUND", "{{ foreground }}")
hl.env("GUM_WRITE_HEADER_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_PLACEHOLDER_FOREGROUND", "{{ color8 }}")
hl.env("GUM_WRITE_PLACEHOLDER_BACKGROUND", "{{ background }}")
hl.env("GUM_WRITE_PROMPT_FOREGROUND", "{{ foreground }}")
hl.env("GUM_WRITE_PROMPT_BACKGROUND", "{{ background }}")
-- Gum Log Style Variables
hl.env("GUM_LOG_LEVEL_FOREGROUND", "#{{ accent }}")
hl.env("GUM_LOG_LEVEL_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_TIME_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_LOG_TIME_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_PREFIX_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_LOG_PREFIX_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_MESSAGE_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_LOG_MESSAGE_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_KEY_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_LOG_KEY_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_VALUE_FOREGROUND", "#{{ foreground }}")
hl.env("GUM_LOG_VALUE_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_SEPARATOR_FOREGROUND", "#{{ color8 }}")
hl.env("GUM_LOG_SEPARATOR_BACKGROUND", "#{{ background }}")
hl.env("GUM_LOG_LEVEL_FOREGROUND", "{{ accent }}")
hl.env("GUM_LOG_LEVEL_BACKGROUND", "{{ background }}")
hl.env("GUM_LOG_TIME_FOREGROUND", "{{ color8 }}")
hl.env("GUM_LOG_TIME_BACKGROUND", "{{ background }}")
hl.env("GUM_LOG_PREFIX_FOREGROUND", "{{ foreground }}")
hl.env("GUM_LOG_PREFIX_BACKGROUND", "{{ background }}")
hl.env("GUM_LOG_MESSAGE_FOREGROUND", "{{ foreground }}")
hl.env("GUM_LOG_MESSAGE_BACKGROUND", "{{ background }}")
hl.env("GUM_LOG_KEY_FOREGROUND", "{{ foreground }}")
hl.env("GUM_LOG_KEY_BACKGROUND", "{{ background }}")
hl.env("GUM_LOG_VALUE_FOREGROUND", "{{ foreground }}")
hl.env("GUM_LOG_VALUE_BACKGROUND", "{{ background }}")
hl.env("GUM_LOG_SEPARATOR_FOREGROUND", "{{ color8 }}")
hl.env("GUM_LOG_SEPARATOR_BACKGROUND", "{{ background }}")
+6
View File
@@ -0,0 +1,6 @@
{
"accent": "{{ accent }}",
"background": "{{ background }}",
"foreground": "{{ foreground }}",
"border": "{{ foreground }}"
}
+5
View File
@@ -0,0 +1,5 @@
{
"primary": "{{ accent }}",
"background": "{{ background }}",
"backgroundText": "{{ foreground }}"
}
+2 -1
View File
@@ -4,7 +4,6 @@
1password-beta
1password-cli
aether
alacritty
alsa-utils
asdcontrol
avahi
@@ -39,6 +38,7 @@ fcitx5-qt
fd
ffmpegthumbnailer
fontconfig
foot
fzf
github-cli
gnome-calculator
@@ -106,6 +106,7 @@ python-gobject
python-poetry-core
python-terminaltexteffects
qt5-wayland
quickshell
ripgrep
ruby
rust
+1 -1
View File
@@ -4,7 +4,7 @@ run_logged $OMARCHY_INSTALL/packaging/nvim.sh
run_logged $OMARCHY_INSTALL/packaging/icons.sh
run_logged $OMARCHY_INSTALL/packaging/webapps.sh
run_logged $OMARCHY_INSTALL/packaging/tuis.sh
run_logged $OMARCHY_INSTALL/packaging/npx.sh
run_logged $OMARCHY_INSTALL/packaging/npm.sh
run_logged $OMARCHY_INSTALL/packaging/asus-rog.sh
run_logged $OMARCHY_INSTALL/packaging/framework16.sh
run_logged $OMARCHY_INSTALL/packaging/dell-xps-touchpad-haptics.sh
+8
View File
@@ -0,0 +1,8 @@
omarchy-npm-install @openai/codex codex
omarchy-npm-install @google/gemini-cli gemini
omarchy-npm-install @github/copilot copilot
omarchy-npm-install opencode-ai opencode
omarchy-npm-install playwright playwright-cli
omarchy-npm-install @earendil-works/pi-coding-agent pi
omarchy-npm-install @kitlangton/ghui ghui
omarchy-npm-install hunkdiff hunk
-8
View File
@@ -1,8 +0,0 @@
omarchy-npx-install @openai/codex codex
omarchy-npx-install @google/gemini-cli gemini
omarchy-npx-install @github/copilot copilot
omarchy-npx-install opencode-ai opencode
omarchy-npx-install playwright playwright-cli
omarchy-npx-install @earendil-works/pi-coding-agent pi
omarchy-npx-install @kitlangton/ghui ghui
omarchy-npx-install hunkdiff hunk
-5
View File
@@ -1,5 +0,0 @@
echo "Add .config/brave-flags.conf by default to ensure Brave runs under Wayland"
if [[ ! -f ~/.config/brave-flags.conf ]]; then
cp $OMARCHY_PATH/config/brave-flags.conf ~/.config/
fi
-10
View File
@@ -1,10 +0,0 @@
echo "Checking and correcting Snapper configs if needed"
if command -v snapper &>/dev/null; then
if ! sudo snapper list-configs 2>/dev/null | grep -q "root"; then
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

Some files were not shown because too many files have changed in this diff Show More