7.8 KiB
AGENTS.md
Guidance for AI coding agents working on this repository. See README.md
for what the script does from a user's point of view.
Project overview
A bash wizard that makes CachyOS (KDE Plasma 6 + plasma-login-manager)
boot into a SteamOS-style gamescope session, with working switching between
gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
(DMI Valve/Fremont) running CachyOS Desktop edition.
Layout
setup-gamescope-boot.sh- the only entry point. Pre-flight checks, sourceslib/*.sh, runs the menu and applies the plan. No component logic here.lib/*.sh- one file per responsibility, each defining functions only (no top-level side effects besides constants). See the table inREADME.md.- Components. Every menu item
<id>(listed inCOMPONENTSandLABELinlib/menu.sh) provides<id>_status(return 0 if on, detected from the system, no state file needed),<id>_enableand<id>_disable, all idempotent.<id>_enableis also used to re-apply. Optional<id>_availableis checked viacomponent_available(e.g.machineonly on Fremont). Turn-on order isCOMPONENTSorder, turn-off reverse;gamingmust stay first. Dependencies live intoggle_component. - Reversibility. Every per-user KDE setting a component changes goes
through
kset <component> <file> <group|group> <key> <value>(lib/state.sh), which records the old value once;<id>_disablecallskrevert <component>. Never callkwriteconfig6directly for settings a component owns. System files are backed up withbackup_fileand restored on disable. - Single-file build.
.github/tools/bundle.shinlineslib/*.shin the order of the entry point'sfor lib in ...; dosource loop and wraps everything after that loop inmain(). Keep that loop on one line, keep all logic in functions, and don't rely onSCRIPT_DIRfor anything but sourcing. CI (.github/workflows/bundle.yml) publishes the bundle to thelatestrelease on pushes tomain.
Conventions
-
Bash,
set -uo pipefail(no-e): check exit codes of steps that matter explicitly (|| { err ...; exit 1; }or|| return 1). -
Use the helpers from
lib/common.sh(info,ok,warn,err,ask_yn,backup_file) for all output and prompts. -
Runs as the normal user; use
sudoper command, never require root. Per-user files go in$HOMEof the invoking user (the script refuses to configure another user). -
Idempotent: every step must be safe to re-run without duplicating lines or settings. Back up system files with
backup_filebefore the first edit. -
Don't overwrite package-owned files in
/etc/xdgor/usr. KDE settings go into the user's config viakwriteconfig6(ormerge_kde_configfor whole Valve ini files). -
Package installs after a user already confirmed use
--noconfirm: a second pacman prompt consumes the next scripted answer. -
Comments explain why (the CachyOS/Plasma quirk being worked around), not what the next line does.
-
Versioning. SemVer in
VERSION(setup-gamescope-boot.sh, shown in the menu header and the bundle). Every commit gets an entry inCHANGELOG.mdunder its version; a new PR/branch bumps the version.
Non-obvious behaviour to preserve
-
apply_changessets$LOGIN_MANAGERfrom the menu:sddmwhen single user mode is wanted, elseplasmalogin. Toggling single user re-appliesgamingso it moves to the other login manager. Single user mode hides the launcher's Session dropdown via kickoffprimaryActions=3(restrictingaction/logoutalso hides Restart/Shut Down). Two login-manager paths: sddm (like SteamOS:steam-set-sessionwrites/etc/sddm.conf.d/zz-steamos-autologin.conf, which SDDM honours; we addUser=/Relogin=in10-gamescope-autologin.conf, and/etc/sddm.confmust not contain[Autologin]since it's read last) and plasmalogin (needs the sync bridge and the shortcut's sudoers rule). Both must keep working. -
steam-set-sessiononly writes/etc/plasmalogin.conf.d/zz-steamos-autologin.conf; the base/etc/plasmalogin.confwins, hence the sync bridge. The sync service needsStartLimitIntervalSec=0, or bursts of session switches get it rate-limited and all later switches silently stop working. -
The sync script must only edit
Session=inside[Autologin]. -
The Steam desktop autostart unit is guarded with
ExecCondition=... XDG_CURRENT_DESKTOP = KDE, so it doesn't start a second Steam inside gamescope. -
Vapor theme: comes from the
cachyos-vaporpackage (system-wide, in/usr/share); only remove it on disable if we installed it. It is applied withlookandfeeltool --resetLayout("Desktop and window layout"), which replaces the panel/desktop layout: the layout files are backed up to$STATE_DIR/theme-layoutand restored, and every key from Vapor'scontents/defaultsgoes throughksetfirst.plasma-apply-colorschemeruns with theColorSchemekey cleared, since it skips a scheme already named there. The layout reset drops single user's launcher settings, sosingle_launcheris re-applied. -
SteamOS extras (
lib/steamos-extras.sh, part of the theme): downloaded from Valve's neweststeamdeck-kde-presets(repo db gives name + SHA-256) into/usr/local, never/usr.gaming-return.svgis a symlink in the package: installsteam-gaming-return.svgunder that name. The shortcut's icon is switched withset_shortcut_icon, since the conversion is created before the theme. An existing KWallet is never replaced or removed. -
Plasma 6 has no separate systemtray containment: tray settings live on the systemtray applet itself (Valve's setup script targets Plasma 5).
-
Restart plasmashell via
systemctl --user(plasma-plasmashell.service), notplasmashell --replacefrom the script's shell: a shell without the session environment yields a light-themed desktop (context menus, apps it launches). -
Live Plasma changes (
qdbus6 ... evaluateScript,lookandfeeltool) only run whenplasmashellis running; config-file fallbacks cover the rest. -
plasmashell writes its in-memory config back on exit: edit panel/applet/ wallpaper files only between
stop_plasmashell_for_editandrestart_plasmashell_if_stopped(lib/common.sh). -
LED driver:
leds-valve-dkms-git's Makefile builds againstuname -r, not DKMS's target kernel:/etc/dkms/leds-valve-dkms.confsetsMAKE[0]="make KVERSION=${kernelver}"(written before the AUR install). Without it, other kernels build against the running kernel's tree and fail (CachyOS kernels are clang-built; DKMS addsLLVM=1only for the target's tree). Headers for every installed kernel are installed first, andensure-kernel-headers.serviceinstalls missing ones at boot (a pacman hook can't run pacman), which triggers DKMS's install hook. The module creates/sys/class/leds/valve-leds*. -
Relogin=truemeans a gamescope that fails to start is relaunched in a tight loop; keep that in mind when changing session handling.
Checking changes
There is no test suite. At minimum:
for f in setup-gamescope-boot.sh lib/*.sh; do bash -n "$f"; done
shellcheck -S warning setup-gamescope-boot.sh lib/*.sh # if available
Behaviour is verified in a CachyOS QEMU/KVM test VM. The VM scripts and a
Claude Code skill describing the whole test workflow (snapshots, SSH, running
the wizard with scripted menu input such as printf '2\n\ny\nn\n', the
per-component checks; when stdin is not a terminal the menu falls back to a
numbered prompt, which is what scripted runs use, reboot checks, the full test matrix, --fremont to
fake Steam Machine hardware) live in
cachyos-gamescope-boot-dev-env.
Gamescope itself and the real LED bar can only be verified on hardware.