Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
e0a8581
Add omarchy-hw-platform to tell Apple Silicon and Qualcomm machines a…
maralcbr Sep 25, 2026
66981a4
Reject platform gates keyed only on the CPU architecture
maralcbr Sep 25, 2026
5b1730f
Compose default packages from base, architecture and platform lists
maralcbr Sep 25, 2026
c35ea70
Early-load thunderbolt only where the kernel builds the module
maralcbr Sep 25, 2026
aaa3cc7
Compose mkinitcpio HOOKS from an early baseline drop-in
maralcbr Sep 25, 2026
d53ccc4
Resolve the LUKS parent from raw lsblk output
maralcbr Sep 21, 2026
3ff77f8
Check the factory-reset passphrase against keyslots only
maralcbr Sep 26, 2026
f133ad8
Test LUKS parent lookup during owner setup and factory reset
scottjones Sep 21, 2026
c398d23
Cover LUKS parent lookup through an LVM volume group
maralcbr Sep 25, 2026
b77b9b2
Journal the first-boot LUKS re-key so an interrupted attempt resumes
maralcbr Sep 25, 2026
0eb79b2
Change the root volume's LUKS key before the login and root passwords
maralcbr Sep 25, 2026
699bc69
Add omarchy-lifecycle-dispatch for platform boot operations
maralcbr Sep 26, 2026
d4fe519
Let the platform's boot package own first-boot setup's boot chain and…
maralcbr Sep 26, 2026
38e079b
Reset through the platform's boot package where it owns the boot chain
maralcbr Sep 26, 2026
3598a76
Check the platform's boot chain after an update
maralcbr Sep 27, 2026
9aa1508
Hand a machine to its platform's migration through lifecycle dispatch
maralcbr Sep 26, 2026
cd2c9ea
Refuse packages tagged for another platform in a pacman hook
maralcbr Sep 26, 2026
8280ba0
Enable Voxtype's Vulkan backend only when it is installed
maralcbr Sep 25, 2026
1e54ed9
Link the system Widevine CDM into Brave
maralcbr Sep 26, 2026
6494409
Report failed setup steps on the console
maralcbr Sep 25, 2026
949b439
Let a migration defer itself without stopping the update
maralcbr Sep 26, 2026
ad6fc66
Keep Apple Silicon's systemd initramfs on the HOOKS baseline
maralcbr Sep 27, 2026
65fb14e
Hide optional installs that have no package on this machine
maralcbr Sep 27, 2026
f200105
Run 1Password with software GL where there is no render GPU
maralcbr Sep 27, 2026
166ee06
Record with wf-recorder when gpu-screen-recorder can't start
maralcbr Sep 27, 2026
56ce28d
Hold logind's lid switch while a display it doesn't count is in use
maralcbr Sep 27, 2026
802591d
Keep the focused workspace in front when a monitor goes away
maralcbr Sep 27, 2026
789b391
Drive the keyboard backlight from the ambient light sensor
maralcbr Sep 27, 2026
c98615d
Defer an image build's hardware setup to the machine's first boot
maralcbr Sep 27, 2026
2d2b63e
Give an image-built root a UTF-8 locale when LANG is still C
maralcbr Sep 27, 2026
62b9ff6
Let a platform's packages run their own boot, system and user setup
maralcbr Sep 27, 2026
84d8f49
Find batteries, lids and panels that aren't named like a PC's
maralcbr Sep 27, 2026
da11f6a
Keep the user's XDG config and state directories in platform user setup
maralcbr Sep 27, 2026
66b9e3e
Let a platform package add Hyprland defaults of its own
maralcbr Sep 27, 2026
5228cba
Let a platform package name keys in the keybindings menu
maralcbr Sep 27, 2026
60e3376
Keep the top bar out of a panel's camera cutout
maralcbr Sep 27, 2026
6c941e2
Keep PC and Intel Mac quirks off Apple Silicon
maralcbr Sep 27, 2026
72af019
Let a platform's runtime package adjust the apps it needs to
maralcbr Sep 27, 2026
b2a1d69
Ask the platform's boot package before an update takes over its files
maralcbr Sep 27, 2026
2200717
Install the Mac's package set on Apple Silicon
maralcbr Sep 27, 2026
a685357
Give existing aarch64 machines the zram swap Omarchy configures
maralcbr Sep 27, 2026
213ddfb
Keep an ARM machine's repositories when it changes channel
maralcbr Sep 27, 2026
c1b0483
Keep Arch Linux ARM's signing keys current on ARM machines
maralcbr Sep 27, 2026
27d40f7
Mark the runtime's platform files as deciding at runtime
maralcbr Sep 27, 2026
58be18a
Set the wireless regulatory domain from the owner's timezone at first…
maralcbr Sep 28, 2026
a5786a9
Ask again for a keyboard layout first-boot setup could not apply
maralcbr Sep 28, 2026
a159a3b
Refresh a platform's own signing keyrings before an update
maralcbr Sep 28, 2026
570b231
Drive an untyped default input from the audio panel
maralcbr Sep 28, 2026
c08b056
Give first-boot setup an XKB layout for keymaps systemd cannot map
ryanrhughes Oct 1, 2026
8a4b86c
Leave keys a firmware key turned off dark
ryanrhughes Oct 1, 2026
2260b6d
Drop the optional-install availability guards
ryanrhughes Oct 1, 2026
b94e15d
Put the current root back when the factory root cannot take its place
maralcbr Oct 2, 2026
1ca672f
Leave other recorders alone when the saved recorder pid is stale
maralcbr Oct 2, 2026
2c06cdd
Name the audio a wf-recorder recording could not capture
maralcbr Oct 2, 2026
2b9b988
Show the Edge, Spotify and Dropbox installers on x86_64 only
maralcbr Oct 2, 2026
2874ad6
Revoke the generic reset's throwaway slot when the reset fails
maralcbr Oct 2, 2026
9d131c9
Clear a stale recorder pid when a recording starts
maralcbr Oct 2, 2026
f119249
Word the dropped-audio notice for every reason a source is left out
maralcbr Oct 2, 2026
a6a7e2f
Show the Heroic and Minecraft installers on x86_64 only
maralcbr Oct 2, 2026
8ab1dd1
Ask the recorder script whether its stop has a recording to end
maralcbr Oct 2, 2026
66e546b
Copy every platform's pacman templates into place, as x86_64 does
ryanrhughes Oct 2, 2026
fb68056
Revert "Copy every platform's pacman templates into place, as x86_64 …
ryanrhughes Oct 2, 2026
9c6f2d1
Copy every platform's pacman templates into place, as x86_64 does
ryanrhughes Oct 2, 2026
853b9d8
Drop the migrations no installed machine needs
ryanrhughes Oct 2, 2026
ccb123a
Drop the generic changes Mac support doesn't need
ryanrhughes Oct 2, 2026
e76b9cb
Drop the platform Hyprland slots
ryanrhughes Oct 2, 2026
2907d02
Keep aarch64 machines off the release channels until a release suppor…
maralcbr Oct 2, 2026
1614977
Leave a filter's own capture alone when choosing an input again
maralcbr Oct 2, 2026
b6151ec
Say aarch64 offers edge alone where the templates are described
maralcbr Oct 2, 2026
b905116
Point the Mac packages at omacom/omarchy-mac-pkgs
maralcbr Oct 4, 2026
e7b9848
Stop naming a platform migration among the dispatcher's callers
maralcbr Oct 4, 2026
c69afd4
Keep the Intel Mac Broadcom migration off Apple Silicon again
maralcbr Oct 4, 2026
2827c5e
Say when Steam's post-install hook runs now that the drivers go first
maralcbr Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions agents/skills/install-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ commands and reusable setup leaves:
- avoid `exit` in sourced setup scripts unless intentionally aborting setup.
- use `$OMARCHY_INSTALL` and `$OMARCHY_PATH` instead of hard-coded Omarchy paths.
- keep root-scoped hardware setup under `install/hardware/` and orchestrate it through `install/hardware/all.sh`.
- in an image build every `run_logged` leaf in `install/hardware/all.sh` is queued and runs on the machine's first boot instead (`bin/omarchy-provision-hardware`, see `docs/file-layout.md`), possibly offline, using packages already in the image, and before any user exists; keep those leaves idempotent and put nothing but `run_logged` lines in `all.sh`.
- gate platform-specific setup on `omarchy-hw-platform` or a predicate built on it, not on `uname -m`; architecture checks are only for ABI, binary availability or a repository's `$arch` (see `docs/file-layout.md`).
- keep every per-user setup leaf under `install/user/` (including `install/user/hardware/` and `install/user/first-run/`) so it is clear what must run for each user.
- The base install supplies matching kernel headers before hardware setup. DKMS installers should install their driver packages and assume the headers exist.
- prefer helper commands for package and command checks where available.
Expand Down
16 changes: 15 additions & 1 deletion bin/omarchy-apply-hardware
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ for diagnostics or after hardware/package updates.

--defer-provisioning runs without an install user (deferred-provisioning installs create the user at
first boot); group grants are recorded in /var/lib/omarchy/provisioning/groups.

In an image build (/var/lib/omarchy/image/target exists) nothing runs here: every step is queued
for omarchy-provision-hardware on the machine's first boot.
USAGE
}

Expand Down Expand Up @@ -66,10 +69,21 @@ else
fi

export OMARCHY_INSTALL_USER="$install_user"
# Only omarchy-provision-hardware runs steps as an image's first boot.
unset OMARCHY_IMAGE_DEFERRED_HARDWARE
export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
export OMARCHY_INSTALL="${OMARCHY_INSTALL:-$OMARCHY_PATH/install}"
export OMARCHY_INSTALL_LOG_FILE="${OMARCHY_INSTALL_LOG_FILE:-/var/log/omarchy-install.log}"
export PATH="$OMARCHY_PATH/bin:$PATH"

source "$OMARCHY_INSTALL/helpers/logging.sh"
source "$OMARCHY_INSTALL/hardware/all.sh"
source "$OMARCHY_INSTALL/helpers/image-target.sh"

omarchy_image_init
omarchy_image_lock
if omarchy_image_manifest_present; then
omarchy_image_read_manifest
omarchy_image_defer_hardware
else
source "$OMARCHY_INSTALL/hardware/all.sh"
fi
10 changes: 9 additions & 1 deletion bin/omarchy-audio-input-set-default
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ fi
wpctl set-default "$node_id" 2>/dev/null || true
pactl set-default-source "$source_name" 2>/dev/null || true

pactl list short source-outputs 2>/dev/null | awk '{ print $1 }' | while read -r output; do
# A filter's own capture (the input half of a filter chain, loopback or echo
# canceller, which PipeWire joins to its output by node.link-group) is the
# processing, not an app: moving it would feed the filter from the new input, or
# from its own output. pactl translates the listing, so it is read in the C
# locale.
LC_ALL=C pactl list source-outputs 2>/dev/null | awk '
/^Source Output #/ { if (id != "" && !filter) print id; id = substr($3, 2); filter = 0 }
/^[[:space:]]*node\.link-group = / { filter = 1 }
END { if (id != "" && !filter) print id }' | while read -r output; do
[[ -n $output ]] && pactl move-source-output "$output" "$source_name" 2>/dev/null || true
done
21 changes: 17 additions & 4 deletions bin/omarchy-audio-sink-availability
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
#!/bin/bash

# omarchy:summary=Print PulseAudio sink availability for the shell
# omarchy:summary=Print PulseAudio sink or source availability for the shell
# omarchy:group=audio
# omarchy:args=[sources]

# With "sources", print source availability instead: a jack input such as a
# headset microphone reports its port unavailable while nothing is plugged in.
# pactl translates the listing ("not available" too), so it is read in the C
# locale.
kind=sinks
header="Sink #"
if [[ ${1:-} == "sources" ]]; then
kind=sources
header="Source #"
fi

# A speaker tuning is a virtual sink in front of the real speakers. Both exist
# in the graph, but selecting the physical one would only bypass the tuning, so
# report it unavailable and keep it out of the output list.
fronted="$(omarchy-audio-tuning fronted-sink 2>/dev/null || true)"
fronted=""
[[ $kind == sinks ]] && fronted="$(omarchy-audio-tuning fronted-sink 2>/dev/null || true)"

pactl list sinks 2>/dev/null | awk -v fronted="$fronted" '
LC_ALL=C pactl list "$kind" 2>/dev/null | awk -v fronted="$fronted" -v header="$header" '
function emit_sink() {
if (name == "") return
if (fronted != "" && name == fronted) {
Expand All @@ -18,7 +31,7 @@ pactl list sinks 2>/dev/null | awk -v fronted="$fronted" '
print name "\t" ((port_count == 0 || available) ? 1 : 0)
}

/^Sink #/ {
index($0, header) == 1 {
emit_sink()
name = ""
in_ports = 0
Expand Down
76 changes: 76 additions & 0 deletions bin/omarchy-audio-source-level
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/python3
# omarchy:summary=Print an audio input's level for the audio panel
# omarchy:group=audio
# omarchy:args=<source-name>
# omarchy:hidden=true

# The panel meters a typed input with Quickshell's peak monitor, which takes
# only nodes of an exact media class. A virtual source (an
# Audio/Source/Virtual) is untyped there, so this records it, as apps do, and
# prints one peak per 40 ms on the panel's scale (the cube root of the sample
# peak). Samples are inspected, never kept.

import array
import ctypes
import os
import signal
import subprocess
import sys

RATE = 48000
CHUNK = RATE // 25 * 4
NAME = 'omarchy-audio-level'


def level(samples):
peak = max((abs(sample) for sample in samples), default=0.0)
return min(1.0, peak) ** (1 / 3)


def die_with(parent):
# parec must not outlive this helper, even one killed outright; a parent
# already gone before the request would never send the signal.
def request():
try:
ctypes.CDLL(None, use_errno=True).prctl(1, signal.SIGTERM)
except (AttributeError, OSError):
pass
if os.getppid() != parent:
os._exit(0)
return request


def main():
if len(sys.argv) != 2 or not sys.argv[1] or sys.argv[1].startswith('-'):
print('Usage: omarchy-audio-source-level <source-name>', file=sys.stderr)
return 2
try:
process = subprocess.Popen(['parec', '--device=' + sys.argv[1], '--raw', '--format=float32le', '--channels=1',
'--rate=' + str(RATE), '--latency-msec=40', '--client-name=' + NAME,
'--property=node.name=' + NAME, '--property=media.category=Monitor'],
stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
preexec_fn=die_with(os.getpid()))
except OSError as error:
print('Could not read the input level: ' + str(error), file=sys.stderr)
return 1
signal.signal(signal.SIGTERM, lambda *_: sys.exit(0))
pending = b''
try:
while True:
chunk = os.read(process.stdout.fileno(), CHUNK)
if not chunk:
return 0
pending += chunk
while len(pending) >= CHUNK:
print('%.3f' % level(array.array('f', pending[:CHUNK])), flush=True)
pending = pending[CHUNK:]
except (BrokenPipeError, KeyboardInterrupt):
os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())
return 0
finally:
process.kill()
process.wait()


if __name__ == '__main__':
raise SystemExit(main())
14 changes: 10 additions & 4 deletions bin/omarchy-battery-present
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@

# omarchy:summary=Returns true if a battery is present on the system.

for bat in /sys/class/power_supply/BAT*; do
[[ -r $bat/present ]] &&
[[ $(cat $bat/present) == "1" ]] &&
[[ $(cat $bat/type) == "Battery" ]] &&
# Not every battery is called BAT*: Apple Silicon reports macsmc-battery and
# some Framework and Chromebook firmware CMB0, so decide by type, not by name.
power_supply_path="${OMARCHY_POWER_SUPPLY_PATH:-/sys/class/power_supply}"

for bat in "$power_supply_path"/*; do
[[ -r $bat/present && $(<"$bat/present") == "1" ]] || continue
[[ -r $bat/type && $(<"$bat/type") == "Battery" ]] || continue
# A wireless mouse or keyboard registers a Battery too, scoped Device. The
# one that powers the machine is scoped System, or unscoped on older drivers.
[[ -r $bat/scope && $(<"$bat/scope") == "Device" ]] && continue
exit 0
done

Expand Down
33 changes: 27 additions & 6 deletions bin/omarchy-battery-status
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,23 @@ case "${1:-}" in
;;
esac

battery=$(upower -e 2>/dev/null | grep BAT | head -n 1)
# UPower names the device after the sysfs entry, and only some kernels call
# that BAT*: Apple Silicon reports battery_macsmc_battery. Match on the class,
# then take the first one that powers the machine: a wireless mouse or keyboard
# is a battery_ device too, and UPower marks it "power supply: no".
battery=""
battery_info=""
while read -r candidate; do
[[ -n $candidate ]] || continue
candidate_info=$(upower -i "$candidate" 2>/dev/null) || continue
if grep -qE '^\s*power supply:\s+yes' <<<"$candidate_info"; then
battery=$candidate
battery_info=$candidate_info
break
fi
done < <(upower -e 2>/dev/null | grep '/battery_')
[[ -z $battery ]] && exit 0

battery_info=$(upower -i "$battery")

percentage=$(awk '/percentage/ { print int($2); exit }' <<<"$battery_info")
Comment thread
greptile-apps[bot] marked this conversation as resolved.
capacity=$(awk '/energy-full:/ { printf "%d", $2; exit }' <<<"$battery_info")
time_remaining=$(awk '/time to (empty|full)/ {
Expand Down Expand Up @@ -56,7 +68,10 @@ elif [[ -r $battery_path/current_now && -r $battery_path/voltage_now ]]; then
'BEGIN { print microamps * microvolts / 1000000000000 }')
fi

# Some kernels sign power_now by direction (negative while discharging on
# Apple Silicon); the state field already says which way it flows.
power_rate=$(awk -v rate="${power_rate_raw:-0}" 'BEGIN {
if (rate < 0) rate = -rate
rounded = sprintf("%.1f", rate)
sub(/\.0$/, "", rounded)
print rounded
Expand All @@ -65,8 +80,12 @@ state=$(awk '/state/ { print $2; exit }' <<<"$battery_info")
threshold_start=$(awk '/charge-start-threshold:/ { gsub(/%/, "", $2); print int($2); exit }' <<<"$battery_info")
threshold_end=$(awk '/charge-end-threshold:/ { gsub(/%/, "", $2); print int($2); exit }' <<<"$battery_info")

[[ -z $threshold_end ]] && threshold_end=$(cat "$power_supply_path"/BAT*/charge_control_end_threshold 2>/dev/null | head -1)
[[ -z $threshold_start ]] && threshold_start=$(cat "$power_supply_path"/BAT*/charge_control_start_threshold 2>/dev/null | head -1)
# Read the thresholds from the battery UPower resolved rather than a BAT* glob,
# which misses every battery with another name.
[[ -n $threshold_end || ! -r $battery_path/charge_control_end_threshold ]] || threshold_end=$(<"$battery_path/charge_control_end_threshold")
[[ -n $threshold_start || ! -r $battery_path/charge_control_start_threshold ]] || threshold_start=$(<"$battery_path/charge_control_start_threshold")
[[ -n $threshold_end ]] || threshold_end=$(cat "$power_supply_path"/BAT*/charge_control_end_threshold 2>/dev/null | head -1)
[[ -n $threshold_start ]] || threshold_start=$(cat "$power_supply_path"/BAT*/charge_control_start_threshold 2>/dev/null | head -1)

ac_online=false
for supply in "$power_supply_path"/*; do
Expand Down Expand Up @@ -107,7 +126,9 @@ if [[ $shell_output == "true" ]]; then
printf 'size\t%s\n' "${capacity}Wh"
printf 'time\t%s\n' "$time_remaining"

cycles=$(cat "$power_supply_path"/BAT*/cycle_count 2>/dev/null | head -1)
cycles=""
[[ ! -r $battery_path/cycle_count ]] || cycles=$(<"$battery_path/cycle_count")
[[ -n $cycles ]] || cycles=$(cat "$power_supply_path"/BAT*/cycle_count 2>/dev/null | head -1)

[[ -n $cycles ]] && printf 'cycles\t%s\n' "$cycles"

Expand Down
29 changes: 28 additions & 1 deletion bin/omarchy-brightness-display
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,30 @@ use_apple_display() {
}

use_ddc_display() {
[[ -n $monitor ]] && ! monitor_is_internal
[[ -n $monitor ]] && ! monitor_is_internal && monitor_may_have_ddc
}

# A platform whose display driver registers no DDC channel says so in its
# displays.conf (see docs/file-layout.md): there a probe finds only unrelated
# I2C buses, slowly, so only a connector with a ddc node is probed. Everywhere
# else every external monitor is.
monitor_may_have_ddc() {
local displays_conf=/usr/share/omarchy-platform/displays.conf directive argument
[[ -r $displays_conf ]] || return 0

while IFS=$' \t\r' read -r directive argument || [[ -n $directive ]]; do
if [[ $directive == "ddc-require-connector-ddc" && -z $argument ]]; then
compgen -G "/sys/class/drm/card*-$monitor/ddc" >/dev/null
return
fi
done <"$displays_conf"
return 0
}

# The kernel backlight is the built-in panel's, so an external monitor without
# DDC fails rather than dimming the panel.
use_backlight_display() {
[[ -z $monitor ]] || monitor_is_internal
}

if (( $# == 0 )); then
Expand All @@ -50,6 +73,8 @@ if (( $# == 0 )); then
elif use_ddc_display; then
omarchy-brightness-display-ddc "$monitor"
exit
elif ! use_backlight_display; then
exit 1
fi

device="$(omarchy-hw-display)" || exit 1
Expand Down Expand Up @@ -85,6 +110,8 @@ if use_apple_display; then
elif use_ddc_display; then
brightness="$(omarchy-brightness-display-ddc "$monitor" "$step")" || exit 1
(( no_osd )) || omarchy-osd -i brightness -p "$brightness"
elif ! use_backlight_display; then
exit 1
else
# Current device highlighted
device="$(omarchy-hw-display)" || exit 1
Expand Down
26 changes: 24 additions & 2 deletions bin/omarchy-brightness-keyboard
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ direction="${1:-up}"

# Find keyboard backlight device (look for *kbd_backlight* pattern in leds class).
device=""
for candidate in /sys/class/leds/*kbd_backlight*; do
for candidate in "${OMARCHY_LEDS_DIR:-/sys/class/leds}"/*kbd_backlight*; do
if [[ -e $candidate ]]; then
device="$(basename "$candidate")"
break
Expand All @@ -25,11 +25,31 @@ if [[ -z $device ]]; then
exit 1
fi

# Record each level chosen here, and "blank" for the lock screen's off, so the
# ambient light loop (omarchy-brightness-keyboard-auto) can tell the lock's
# blank and leftovers from keys turned off on purpose, by these keys or a
# firmware Fn key. Per user, never under a fixed name in /tmp: the session's
# runtime directory, or a private state directory without one.
if [[ -n ${XDG_RUNTIME_DIR:-} ]]; then
manual_dir=$XDG_RUNTIME_DIR
else
manual_dir=${XDG_STATE_HOME:-$HOME/.local/state}/omarchy
mkdir -p "$manual_dir" 2>/dev/null && chmod 700 "$manual_dir" 2>/dev/null
fi
manual_file=$manual_dir/omarchy-brightness-keyboard-manual

# One at a time, so a lock blank racing a wake can't leave the LED and the
# record disagreeing.
{ exec {lock_fd}>>"$manual_file.lock"; } 2>/dev/null && flock -w 2 "$lock_fd" 2>/dev/null

if [[ $direction == "off" ]]; then
{ echo blank >"$manual_file"; } 2>/dev/null || true
brightnessctl -sd "$device" set 0 >/dev/null
exit 0
elif [[ $direction == "restore" ]]; then
brightnessctl -rd "$device" >/dev/null
# A failed restore leaves the keys blank, so the record must still say so.
brightnessctl -rd "$device" >/dev/null || exit 1
rm -f "$manual_file" 2>/dev/null
exit 0
fi

Expand All @@ -53,6 +73,8 @@ else
(( new_brightness < 0 )) && new_brightness=0
fi

{ printf '%s\n' "$new_brightness" >"$manual_file"; } 2>/dev/null || true

# Set the new brightness.
brightnessctl -d "$device" set "$new_brightness" >/dev/null
(( no_osd )) || omarchy-osd -i keyboard -p "$(( new_brightness * 100 / max_brightness ))"
Loading