Creating a custom screensaver on Omarchy
Replace Omarchy's ASCII art screensaver with a TTE-animated dashboard showing the clock, date, and weather.
The problem
Omarchy ships with a screensaver that runs Terminal Text Effects (tte) on ASCII art from ~/.config/omarchy/branding/screensaver.txt. It looks great: random effects, fullscreen on every monitor, exits on any keypress.
I wanted something more practical in the center of the screen: the clock, today’s date, and the weather. I still wanted the TTE animations though, so I kept the same launcher and lifecycle hooks and only swapped what tte renders.
The solution
You need three scripts. Make them executable after you create them:
1
2
3
chmod +x ~/.config/omarchy/bin/omarchy-dashboard-frame
chmod +x ~/.local/share/omarchy/bin/omarchy-screensaver-mine
chmod +x ~/.local/share/omarchy/bin/omarchy-launch-screensaver
Step 1: The dashboard frame
This script prints the static text that tte will animate. Weather comes from wttr.in; override the city with SCREENSAVER_CITY (defaults to Sofia).
~/.config/omarchy/bin/omarchy-dashboard-frame:
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
CITY="${SCREENSAVER_CITY:-Sofia}"
weather=$(curl -s "wttr.in/${CITY}?format=%t+%C" 2>/dev/null || echo "--")
cat <<EOF
$(date +"%H:%M")
$(date +"%A · %d %B")
${CITY} · ${weather}
EOF
Step 2: The screensaver loop
I named mine omarchy-screensaver-mine so the stock omarchy-screensaver stays available if I want to switch back.
~/.local/share/omarchy/bin/omarchy-screensaver-mine:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash
# omarchy:summary=Run Omarchy screensaver with a stable dashboard (time + weather)
screensaver_in_focus() {
hyprctl activewindow -j 2>/dev/null | jq -e '.class == "org.omarchy.screensaver"' >/dev/null 2>&1
}
exit_screensaver() {
hyprctl keyword cursor:invisible false &>/dev/null || true
pkill -x tte 2>/dev/null
pkill -f org.omarchy.screensaver 2>/dev/null
exit 0
}
trap exit_screensaver SIGINT SIGTERM SIGHUP SIGQUIT
printf '\033]11;rgb:00/00/00\007'
hyprctl keyword cursor:invisible true &>/dev/null
tty=$(tty 2>/dev/null)
while true; do
# One stable TTE instance per activation
tte -i <(~/.config/omarchy/bin/omarchy-dashboard-frame) \
--frame-rate 30 \
--canvas-width 0 --canvas-height 0 \
--reuse-canvas \
--anchor-canvas c --anchor-text c \
--no-eol --no-restore-cursor \
--random-effect &
tte_pid=$!
# Monitor lifecycle (NO respawn spam)
while kill -0 "$tte_pid" 2>/dev/null; do
if read -n1 -t 1 || ! screensaver_in_focus; then
exit_screensaver
fi
done
wait "$tte_pid" 2>/dev/null
done
Step 3: The launcher
~/.local/share/omarchy/bin/omarchy-launch-screensaver:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/bin/bash
# omarchy:summary=Launch the Omarchy screensaver in the default terminal on the system with the correct font configuration.
if ! command -v tte &>/dev/null; then
exit 1
fi
# Exit early if screensave is already running
pgrep -f org.omarchy.screensaver && exit 0
# Allow screensaver to be turned off but also force started
if omarchy-toggle-enabled screensaver-off && [[ $1 != "force" ]]; then
exit 1
fi
# Silently quit Walker on overlay
walker -q
focused=$(omarchy-hyprland-monitor-focused)
terminal=$(xdg-terminal-exec --print-id)
for m in $(hyprctl monitors -j | jq -r '.[] | .name'); do
hyprctl dispatch focusmonitor $m
case $terminal in
*Alacritty*)
hyprctl dispatch exec -- \
alacritty --class=org.omarchy.screensaver \
--config-file ~/.local/share/omarchy/default/alacritty/screensaver.toml \
-e omarchy-screensaver-mine
;;
*ghostty*)
hyprctl dispatch exec -- \
ghostty --class=org.omarchy.screensaver \
--config-file=~/.local/share/omarchy/default/ghostty/screensaver \
--font-size=18 \
-e omarchy-screensaver-mine
;;
*foot*)
hyprctl dispatch exec -- \
foot --app-id=org.omarchy.screensaver \
--config="$OMARCHY_PATH/default/foot/screensaver.ini" \
-e omarchy-screensaver-mine
;;
*kitty*)
hyprctl dispatch exec -- \
kitty --class=org.omarchy.screensaver \
--override font_size=18 \
--override window_padding_width=0 \
-e omarchy-screensaver-mine
;;
*)
notify-send -u low "✋ Screensaver only runs in Alacritty, Foot, Ghostty, or Kitty"
;;
esac
done
hyprctl dispatch focusmonitor $focused
Try it
Force-start the screensaver without waiting for hypridle:
1
omarchy-launch-screensaver
Press any key to dismiss.
Conclusion
The whole trick is that Omarchy’s screensaver is just a bash loop around tte inside a specially-classed terminal window. Swap the input, keep the launcher, and you get a useful at-a-glance display that still feels like the stock screensaver.
If you want the ASCII art back, point the launcher at omarchy-screensaver again or just keep both scripts and switch whenever you feel like it.