mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
389 lines
26 KiB
Markdown
389 lines
26 KiB
Markdown
# 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
|
|
|
|
**Steamify CachyOS**: 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
|
|
|
|
- `steamify.sh` - the only entry point. Pre-flight checks,
|
|
sources `lib/*.sh`, runs the menu and applies the plan. No component
|
|
logic here.
|
|
- `patches/` - kernel module sources and patches the scripts build or
|
|
apply, never inline in the shell code. Read them with `patch_file
|
|
<name>` (`lib/common.sh`, from the checkout); the bundle embeds every file
|
|
in `patches/` and overrides `patch_file`. Add new ones to its README.
|
|
- `services/` - the systemd units the scripts install (`.service`,
|
|
`.timer`, `.path`), never inline in the shell code. Read them with
|
|
`service_file <name> [KEY=value...]` (`lib/common.sh`), which fills in
|
|
`@KEY@` placeholders; the bundle embeds every file in `services/` too
|
|
(`service_raw`). Add new ones to its README. Small drop-ins for other
|
|
packages' units stay inline.
|
|
- `ui/` - the app: `steamify-ui` (PySide6; runs `steamify.sh --backend`,
|
|
`lib/backend.sh`) and `ui/qml/`: `Main.qml` (window, header, which screen
|
|
shows), `AppState.qml` (all state and logic, input actions), one
|
|
`*Screen.qml` per screen, small widgets (`Btn`, `Chip`, `Badge`, ...), and
|
|
the singletons `Theme` (colours, fonts), `Texts` (item texts) and `Input`
|
|
(controller/keyboard/remote and its button names), listed in `qmldir`.
|
|
Screens get the `AppState` as `app` and only show it or call its functions.
|
|
- **Paths.** Everything in the home folder lives under `steamify`:
|
|
`$STATE_DIR` (`~/.local/state/steamify`), `$STEAMIFY_DATA`/`$STEAMIFY_BIN`
|
|
(`~/.local/share/steamify/{app,bin}`), `lib/state.sh`. Never add files
|
|
under the old name `cachyos-gamescope-boot`; `migrate_layout` moves those
|
|
of older versions (symlinks keep older releases working). Keep the
|
|
`.bak-gamescope-wizard` backup suffix: existing backups are found by it.
|
|
- `lib/*.sh` - one file per responsibility, each defining functions only
|
|
(no top-level side effects besides constants). See the table in
|
|
`TECHNICAL.md`.
|
|
- **Components.** Every menu item `<id>` (listed in `COMPONENTS` and `LABEL`
|
|
in `lib/menu.sh`) provides `<id>_status` (return 0 if on, detected from
|
|
the system, no state file needed), `<id>_enable` and `<id>_disable`, all
|
|
idempotent. `<id>_enable` is also used to re-apply. Optional
|
|
`<id>_available` is checked via `component_available` (e.g. `machine`
|
|
only on Fremont). Turn-on order is `COMPONENTS` order, turn-off reverse;
|
|
`gaming` must stay first. Dependencies live in `toggle_component`.
|
|
- **NVIDIA** (`lib/nvidia.sh`): gamescope's session is broken on NVIDIA, so the SteamOS conversion (`gaming`, `boot`, `single`,
|
|
`glyphs`) is hidden there (unless already on) and `nvidia` + its sub-option `bigpicture` ("Gaming on NVIDIA") replace it:
|
|
Steam on the Plasma desktop, started at login. Never reintroduce a gamescope session for NVIDIA without re-testing on the
|
|
hardware (notes: steamify-cachyos-dev, `nvidia/`). It can't be tested without the hardware: keep the branch behind
|
|
`.no-release-yet` until it was.
|
|
- **Feature versions.** Set `FEATURE_VERSION[<id>]` (`lib/menu.sh`) to the new
|
|
`VERSION` whenever what `<id>_enable` sets up changes (a new component gets
|
|
one too): installs recorded with an older version
|
|
are ticked and re-applied ("update" in the plan and the app). New default
|
|
options are ticked for installs whose parent (top-level: `gaming`) is on
|
|
(`feature_new`, shown as "new"). New opt-in options (`NO_PRESELECT`) get the
|
|
same "new" badge without being ticked (`feature_new_optin`). Both count "Gaming
|
|
on NVIDIA" as a parent where the conversion isn't offered.
|
|
Options shown but left unticked in a confirmed run are recorded as
|
|
`off` (`feature_record_unticked`), or `feature_new` would tick them again.
|
|
Status still comes from the system; don't add ad-hoc `<id>_repair` checks
|
|
for new changes.
|
|
- **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>_disable` calls
|
|
`krevert <component>`. Never call `kwriteconfig6` directly for settings a
|
|
component owns. System files are backed up with `backup_file` and restored
|
|
on disable.
|
|
- **Single-file build.** `.github/tools/bundle.sh` inlines `lib/*.sh` in the order of
|
|
the entry point's `for lib in ...; do` source loop and wraps everything
|
|
after that loop in `main()`. Keep that loop on one line, keep all logic in
|
|
functions, and don't rely on `SCRIPT_DIR` for anything but sourcing.
|
|
The workflow is one file for GitHub and a Gitea mirror (`github.server_url`): build and check run on both
|
|
(shellcheck through `ludeeus/action-shellcheck`, which brings its own binary; the artifact with
|
|
`upload-artifact@v4` on GitHub and `christopherhx/gitea-upload-artifact@v4` elsewhere: never mention
|
|
`upload-artifact@v3`, GitHub fails a workflow for a deprecated version even in a skipped step); the
|
|
release is `gh` on GitHub and `akkuman/gitea-release-action` on Gitea. A new release on GitHub also starts the
|
|
Steamify ISO's release (`gh workflow run iso-1-github-tag.yml` in steamify-cachyos-live-iso, secret
|
|
`ISO_DISPATCH_TOKEN`; skipped without it): the ISO repo's GitHub tag names it, the Gitea mirror builds it.
|
|
CI (`.github/workflows/bundle.yml`) publishes the bundle as release
|
|
`v$VERSION` on pushes to `main`; an existing version is never overwritten,
|
|
so bump `VERSION` for every release.
|
|
|
|
## 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 `sudo` per command, never require root.
|
|
Per-user files go in `$HOME` of 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_file` before the
|
|
first edit.
|
|
- Don't overwrite package-owned files in `/etc/xdg` or `/usr`. KDE settings
|
|
go into the user's config via `kwriteconfig6` (or `merge_kde_config` for
|
|
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 and releases.** SemVer in `VERSION` (`steamify.sh`,
|
|
shown in the menu header and the bundle header).
|
|
- Every commit gets an entry in `CHANGELOG.md` under its version (short hash
|
|
+ subject; a commit can't contain its own hash, so fill it in with the
|
|
next commit). The section heading must be `## <VERSION> - <date>`: CI
|
|
cuts the release notes out of the changelog by that heading.
|
|
- **Branches: one release branch per version.** Work for a release goes
|
|
into `release/X.Y.Z` (e.g. `release/2.7.0`), branched from `main` when
|
|
that version starts. That branch bumps `VERSION` to `X.Y.Z` and adds the
|
|
`## X.Y.Z - <date>` changelog section (first commit on it).
|
|
- Every change gets its own branch from the release branch:
|
|
`feature/<name>` (new behaviour) or `bugfix/<name>` (a fix), and a
|
|
pull request **into the release branch**, not into `main`. Its commits
|
|
add their changelog lines to that version's section.
|
|
- When the release is done and tested (the test plan in
|
|
steamify-cachyos-dev, `TESTPLAN.md`), the release branch gets a pull
|
|
request **into `main`**. Merging it publishes the release (below).
|
|
- A fix for a released version: a new `release/X.Y.Z+1` from `main`,
|
|
with the `bugfix/` branch into it; don't reopen an old release branch.
|
|
- Up to the release branch, the agent manages it: create the
|
|
`feature/`/`bugfix/` branches, commit, push, and merge them into the
|
|
release branch itself once tested (with `gh`: `gh pr create --base
|
|
release/X.Y.Z` + `gh pr merge --merge`; no review needed). Without
|
|
`gh` (`command -v gh`), ask the user to install it (Ubuntu:
|
|
`sudo apt install gh`, then `gh auth login`) instead of working around
|
|
it. Only the
|
|
release branch's pull request into `main` is the user's: never commit
|
|
or merge to `main`, the user merges that one. Never work directly on
|
|
`main` or a `release/*` branch either: edits, even uncommitted ones,
|
|
go on a `feature/`/`bugfix/` branch (create it before editing; the
|
|
release branch only gets the version-bump commit and merged PRs).
|
|
Don't push a new `release/*` branch before it's needed: a push can
|
|
start CI builds (a dev ISO).
|
|
A machine without a git identity: pass the repo's author per command
|
|
(`git -c user.name=... -c user.email=... commit`, taken from `git
|
|
log`) instead of changing the git config.
|
|
A `.no-release-yet` file at the root of a feature/bugfix branch means
|
|
it must not be merged into the release branch yet (work in progress,
|
|
untested on hardware). When the feature is complete, ask the user
|
|
whether it may be released; on a yes, delete the file, then open the
|
|
pull request and merge it.
|
|
Keep a feature/bugfix branch up to date by merging (or rebasing on)
|
|
its release branch, the release branch by merging `main` when that
|
|
moved.
|
|
- A push to `main` publishes release `v$VERSION` (tag + bundle + that
|
|
changelog section) and marks it latest. An existing version is never
|
|
overwritten: without a bump nothing is released, and pull requests show
|
|
a warning when `VERSION` is a version that's already released (so a
|
|
release branch that forgot its bump shows it on every PR).
|
|
- A release that adds, removes or renames a menu row also retakes the
|
|
README screenshots (`assets/screenshot-menu-steam-machine.png` and
|
|
`assets/screenshot-menu-nvidia.png`, side by side in the README): the app from the branch on a Steam Machine and on a PC
|
|
with an NVIDIA card, every row visible and each window only as tall as its options need, the header showing the new
|
|
`VERSION`, 1600 px wide. Size the window with a KWin script (match the `steamify-ui` class exactly: a title match also hits
|
|
Konsole and editor windows) and crop the full-screen capture to the client rectangle; mind the display scale (the Steam
|
|
Machine runs at 1.75).
|
|
- Users install through `releases/latest/download/steamify.sh`
|
|
(GitHub's newest release). The `latest` tag and release follow the newest
|
|
version tag too (moved, asset replaced, when a new version is released),
|
|
so the older URL `releases/download/latest/...` keeps working.
|
|
|
|
## Non-obvious behaviour to preserve
|
|
|
|
- `apply_changes` sets `$LOGIN_MANAGER` from the menu: `sddm` when single
|
|
user mode is wanted, else `plasmalogin`. Toggling single user re-applies
|
|
`gaming` so it moves to the other login manager. Single user mode hides
|
|
the launcher's Session dropdown via kickoff `primaryActions=3` (restricting
|
|
`action/logout` also hides Restart/Shut Down). Two login-manager paths:
|
|
**sddm** (like SteamOS: `steam-set-session` writes
|
|
`/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM honours; we add
|
|
`User=`/`Relogin=` in `10-gamescope-autologin.conf`, and `/etc/sddm.conf`
|
|
must 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-session` only writes `/etc/plasmalogin.conf.d/zz-steamos-autologin.conf`;
|
|
the base `/etc/plasmalogin.conf` wins, hence the sync bridge. The sync
|
|
service needs `StartLimitIntervalSec=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-vapor` package (system-wide, in
|
|
`/usr/share`); only remove it on disable if we installed it. It is applied
|
|
with `lookandfeeltool --resetLayout` ("Desktop and window layout"), which
|
|
replaces the panel/desktop layout: the layout files are backed up to
|
|
`$STATE_DIR/theme-layout` and restored, and every key from Vapor's
|
|
`contents/defaults` goes through `kset` first. `plasma-apply-colorscheme`
|
|
runs with the `ColorScheme` key cleared, since it skips a scheme already
|
|
named there. The layout reset drops single user's launcher settings, so
|
|
`single_launcher` is re-applied.
|
|
- SteamOS extras (`lib/steamos-extras.sh`, part of the theme): downloaded from
|
|
Valve's newest `steamdeck-kde-presets` (repo db gives name + SHA-256) into
|
|
`/usr/local`, never `/usr`. `gaming-return.svg` is a symlink in the package:
|
|
install `steam-gaming-return.svg` under that name. The shortcut's icon is
|
|
switched with `set_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`),
|
|
not `plasmashell --replace` from 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 when `plasmashell` is 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_edit` and
|
|
`restart_plasmashell_if_stopped` (`lib/common.sh`).
|
|
- LED driver: `leds-valve-dkms-git`'s Makefile builds against `uname -r`,
|
|
not DKMS's target kernel: `/etc/dkms/leds-valve-dkms.conf` sets
|
|
`MAKE[0]="make KVERSION=${kernelver}"` (written before the AUR install;
|
|
someone's own override there is backed up, kept with ours appended, and
|
|
restored on disable).
|
|
Without it, other kernels build against the running kernel's tree and
|
|
fail (CachyOS kernels are clang-built; DKMS adds `LLVM=1` only for the
|
|
target's tree). Headers for every installed kernel are installed first,
|
|
and `ensure-kernel-headers.service` installs 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*`.
|
|
- `boot` ("Boot into: [gamescope] / desktop") is a choice row, not a
|
|
checkbox: on = desktop. It's a sub-option of the conversion: `menu_visible`
|
|
only shows it (indented, `└`) while `gaming` is ticked, so menu numbers
|
|
after it shift by one when the conversion is unticked. It needs `gaming` (ticking it ticks gaming,
|
|
unticking gaming unticks it) and is never preselected (`NO_PRESELECT`), so
|
|
the conversion boots into gamescope by default. Desktop is
|
|
`steamify-boot-desktop.service`, ordered `Before=` the login managers:
|
|
`steam-set-session plasma.desktop` plus the plasmalogin sync bridge when it
|
|
exists, at every boot. CachyOS's `cachyos-gamescope-autologin` still sets
|
|
gamescope during each desktop session; the unit corrects it at boot.
|
|
- `bios` is an *action* (`ACTIONS` in `lib/menu.sh`) and a sub-option of `machine`, not an on/off
|
|
component: never preselected (not even on a first run), never re-applied
|
|
by `a`, not listed in the state overview, and `bios_status` is always off.
|
|
Only selectable when Valve's version differs from the installed one
|
|
(`component_selectable`, greyed out otherwise). Download, SHA-256 and the
|
|
fwupd device check (`get-details --json`: no `UpdateError`) come before the
|
|
warnings. The warning box uses `█` for its frame: Konsole draws a long
|
|
coloured row of `#` narrower, so the right edge wouldn't line up.
|
|
Keep both confirmations (y/N, then typing `UPDATE`) and the warnings; the
|
|
firmware comes from the newest `holo-X.Y` repo (`.files` db names the
|
|
`.cab`, `.db` gives the SHA-256), and fwupd itself refuses non-Fremont
|
|
hardware. In the VM, test it with `WIZARD_BIOS_DRY_RUN=1` (skips only the
|
|
device check, never flashes) and a faked version (dev-env
|
|
`BIOS_VERSION=F7F0107 ./run.sh --fremont`).
|
|
- The entry point loops: menu, run, "back to the menu" (or `[m]`/`[r]` when a
|
|
restart is needed), until `q`. When a restart is needed, `q` asks "Restart
|
|
now? [Y/n]" (`quit_prompt`): `n` goes back to the menu, the next `q` asks
|
|
again. Scripted input that runs out quits without restarting (never
|
|
restart on EOF: `ask_yn` would take its default).
|
|
- Steamify shortcut (`launcher`): "Steamify CachyOS" (desktop and launcher,
|
|
id `steamify-ui.desktop`, the app's own id) runs `curl | bash` of
|
|
`releases/latest/download/steamify-app.sh` without a terminal (in Konsole
|
|
only while PySide6 is missing, for sudo); "Steamify Terminal" (launcher)
|
|
runs `steamify.sh` in Konsole. Both always the newest release. The entry
|
|
has `X-Steamify-Shortcut=true`: steamify-app.sh doesn't overwrite it, and
|
|
disable only removes it then. A pre-2.0.1 shortcut (terminal only) is
|
|
ticked by `launcher_repair`. Its icon, `assets/steam-gaming-settings.svg`
|
|
(Valve's GPL-2.0 return icon with a gear), is a release asset too, and is
|
|
downloaded from there (Steam's icon if that fails). Desktop files are
|
|
written with their mode already set (`install_executable`): Plasma opens a
|
|
desktop icon it first saw non-executable in an editor.
|
|
The start script closes its window after a 10-second countdown on success
|
|
and waits for Enter after an error; it uses `pipefail`, or a failed
|
|
download would run an empty script and count as success.
|
|
- HDMI refresh boost (`hdmi`, `lib/hdmi-refresh.sh`): retired in 2.2.0
|
|
(it needed the pinned kernel); only removal is left (see the power-off
|
|
fix below). `hdmi_enable` refuses. debugfs is root-only (glob it under
|
|
sudo), and `edid_override` takes exactly `reset` with no newline.
|
|
- Steam Machine CEC driver (`cec_driver_enable`, `lib/cec.sh`): mainline
|
|
`cros_ec_cec` lacks Fremont, so HDMI-CEC builds Valve's copy (evlaV
|
|
`linux-integration`, pinned commit + SHA-256) with DKMS for every kernel.
|
|
It's patched to register its notifier without a port name when the board
|
|
has one CEC port: amdgpu registers its HDMI notifier nameless, and the
|
|
kernel only pairs that with a named lookup ("Port C") when the CEC driver
|
|
registered first, which never happens since amdgpu loads from the
|
|
initramfs. Without it `/dev/cec0` exists but stays at `f.f.f.f`.
|
|
The source comes from one raw.githubusercontent.com download, which GitHub rate-limits (HTTP 429 after a
|
|
day of test installs, per address): it's kept in `/var/cache/steamify/cros-ec-cec-<sha256:12>.c` and reused
|
|
while its checksum matches. The name carries the checksum, so a new pin (commit + SHA-256 in `lib/cec.sh`)
|
|
downloads its own file once and removes the old one. The repo is an unofficial mirror of Valve's kernel
|
|
without releases: if it ever disappears, ship the file with Steamify. The test VMs share the host's cache.
|
|
- Power-off fix (`poweroff`, `lib/fremont-poweroff.sh`, a default sub-option
|
|
of `machine`): recent kernels (7.2 and the 6.x/7.0/7.1 updates with the
|
|
backport) keep the firmware's S4/S5 wake bit on GPIO
|
|
pin 18, so the Steam Machine boots again right after powering off
|
|
(Valve's kernel clears it at probe, not for upstream). The DKMS module
|
|
`steamify-fremont-poweroff` (`patches/steamify-fremont-poweroff.c`) clears
|
|
it in a power-off-prepare handler, built for each kernel. It made the kernel pin
|
|
unnecessary: `kpin` is only available while on (`kpin_available`), and
|
|
`detect_components` unticks it, so a normal run removes an existing pin.
|
|
`hdmi` (it needed the pin) is retired the same way: `hdmi_status` is on
|
|
while anything of it is left (saved displays, hotplug unit, EDID files,
|
|
old kernel parameter), `hdmi_available` only then, it's always unticked,
|
|
and `hdmi_disable` removes all of it. CachyOS's
|
|
`linux-cachyos` is clang-built, `-bore` GCC-built: let DKMS pick the
|
|
compiler, never pass `LLVM=1`. Test shutdown on the real machine for every
|
|
new major kernel.
|
|
- Add as non-Steam game (`steamgame`, `lib/steam-game.sh`, sub-option of
|
|
`launcher`, ticked along with it, 2.5.1): edits Steam's `shortcuts.vdf`
|
|
with `patches/steam-shortcuts.py` only while Steam is closed (Steam
|
|
rewrites it on exit), then starts Steam again. Never close Steam in gaming
|
|
mode or when `SteamGameId` is set (the run is a Steam game). An existing
|
|
entry for the start script is updated, not doubled; removal takes every
|
|
entry for it. Controller input through Steam's desktop layout arrives as
|
|
keys: Enter must select (A), Esc must never quit (B); the app re-execs
|
|
without Steam's overlay preload.
|
|
- Update notifications (`notify`, `lib/update-notifier.sh`, top-level,
|
|
ticked by default, 2.5.0): a user timer (daily, and the service is wanted
|
|
by `plasma-workspace.target`) runs `patches/steamify-notifier.py`, which
|
|
compares GitHub's newest release with the `seen` version every run records
|
|
(`notify_seen` in the entry point, only while it's on, with `frontend`: app or terminal, which Open Steamify starts again, in a `systemd-run --scope` since the check's own unit is stopped when it exits). It must never
|
|
update anything itself: notification + tray icon, Open Steamify / Skip
|
|
this version (`skipped`). Desktop only (exits without `plasmashell`).
|
|
- VRAM booster (`vram`, `lib/vram-booster.sh`, top-level, ticked by
|
|
default, 2.3.0; only available when `/sys/fs/cgroup/dmem.capacity` lists a
|
|
`vram`/`vidmem` region (numbered too) of at least 2 GB, whatever the brand;
|
|
greyed out with an NVIDIA card whose driver lists none, `vram_selectable`,
|
|
faked with `WIZARD_VRAM_FAKE_NVIDIA=1`; `WIZARD_VRAM_CAPACITY=<file>` reads
|
|
the regions from a copy): CachyOS's `dmemcg-booster` (system + user service) and
|
|
`plasma-foreground-booster`, like SteamOS 3.9's VRAM management. The
|
|
latter only starts with `kcgroupsrc [Foreground Booster] autostart=true`
|
|
(set with `kset`). Disable removes only the packages it installed
|
|
(`state_get vram installed_pkgs`).
|
|
- Install-time mode (`steamify.sh --defaults`, 2.6.0): applies what the menu
|
|
would preselect, no menu or prompts (needs passwordless sudo). The Steam
|
|
Machine ISO ([steamify-cachyos-live-iso](https://github.com/theupriser/steamify-cachyos-live-iso))
|
|
runs it in the installer for a user who has never logged in: no session
|
|
bus, user systemd or plasmashell. So every `systemctl --user` goes through
|
|
`user_systemctl` (`lib/common.sh`; without a session only unit files change,
|
|
via `--root=/`), and the theme, when the layout is still `/etc/skel`'s,
|
|
removes it so Plasma builds Vapor's layout at the first login. What needs
|
|
that layout (single user's launcher) runs then, from a one-time autostart
|
|
(`lib/first-login.sh`, `--first-login`) that also opens the app.
|
|
`--options <id>,...` (exactly these on, the rest off; an item on brings its
|
|
parent) and `--boot gamescope|desktop` (desktop only with `gaming`) (2.7.0,
|
|
`defaults_options` in `lib/menu.sh`); the ISO's installer page passes them.
|
|
Items this PC can't use are left off with a warning, not an error.
|
|
`steamify.sh --boot gamescope|desktop` on its own (2.7.0, for scripts) only
|
|
switches `boot` on an installed conversion: `WANTED` is `CURRENT` plus
|
|
that, so no updates or removals a normal run would pick.
|
|
- What Steam's System settings show (SteamOS conversion, 2.9.0): the OS name
|
|
stays CachyOS's everywhere (legal clarity; Steam's OS Name is
|
|
`lsb_release -d`, not touched). `/etc/os-release` gets `VERSION_ID=steamos-X.Y`
|
|
(Steam's OS Version: Valve's newest jupiter repo; offline, the previous
|
|
value), `VERSION_CODENAME=steam-machine`, `VARIANT="Steamify <version>"` and
|
|
`VARIANT_ID=steamify-<version>` (Steam shows VARIANT_ID as OS Variant),
|
|
refreshed by `os_version_refresh` after every run that changes something; a
|
|
pacman hook (`zz-steamify-os-release`) runs after cachyos-hooks. KDE's About
|
|
this System would show VERSION_ID after the name: `kcm-about-distrorc`
|
|
`UseOSReleaseVersion=true` (kset) makes it show os-release's VERSION, which
|
|
CachyOS doesn't have. Never `NAME` or `PRETTY_NAME`: limine-snapper-sync
|
|
finds the boot entries by the OS name ("Target OS name ... not found in
|
|
/boot/limine.conf"); `/etc/default/limine` gets `TARGET_OS_NAME="CachyOS"`
|
|
when it has none, as a guard. The serial number (tmpfiles rule) is Steam
|
|
Machine support's, so Fremont only.
|
|
- `Relogin=true` means a gamescope that fails to start is relaunched in a
|
|
tight loop; keep that in mind when changing session handling.
|
|
|
|
## Checking changes
|
|
|
|
The bundle puts every module in one file, so shellcheck sees all their
|
|
`local` variables together: don't reuse a name another module uses as an
|
|
array (e.g. `g` in `lib/state.sh`), or CI's shellcheck on the bundle fails.
|
|
|
|
|
|
There is no test suite. At minimum:
|
|
|
|
```bash
|
|
for f in steamify.sh lib/*.sh; do bash -n "$f"; done
|
|
shellcheck -S warning steamify.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
|
|
[steamify-cachyos-dev](https://github.com/theupriser/steamify-cachyos-dev).
|
|
Gamescope itself and the real LED bar can only be verified on hardware.
|