targets.genericLinux.gpu would ask for a root setup (a tmpfiles.d link
under /etc) for drivers that Nix-built GUI apps need and steam-frame-nix
doesn't; news.display = "silent" drops the unread news notice on each
switch (home-manager news still lists them).
It is built from source, which makes the first switch long. The template
lists it as a commented option; status shows clipboard-sync only while it
runs or its autostart link exists.
create_config locks the template as a path (not the git repository) and
commits everything once, with the user's git identity or, without one,
a fallback passed with -c for that commit only. The template switch no
longer warns that the tree is dirty; the marker and the one-commit rule
are unchanged.
- One systemctl --user wrapper (user_systemctl, with the test override)
instead of outer_systemctl, outer_bus_ok and c_systemctl.
- link_config for the three places that link ~/.config/home-manager;
git_noprompt, receipt_planner, FLAKES_LINE and c_done inlined.
- c_rm_link for the artifacts proven by their link target (screenshots,
the VR pet icon); a foreign link is reported with its target.
- Shorter help (--clone, cleanup, restart-check) and comments that
repeated docs/cleanup.md.
No cleanup path changes: every artifact an older published version wrote
still has its rule.
Without ~/.config/home-manager and --flake, a flake in ~/nix-config
(e.g. left by uninstall) is used as it is, like --flake ~/nix-config,
and linked to ~/.config/home-manager. A directory there without
flake.nix still stops the install.
The switch already ran, so the note only says to open a new terminal,
where the configuration is and how to apply changes. Dropped: the
"uncomment the steamFrame block" hint, the Konsole/Developer Mode hint
and the status/uninstall line.
The closing message no longer lists generic "left in place" items
(*.hm-backup-<time> files that usually don't exist, app data, Flatpak
apps). It says where the configuration stays and how install uses it
again, lists the *.hm-backup-* files Home Manager actually made (if
any), and asks to log out or reboot.
- The nix.mount drop-in is also removed when the uninstall fails or is
interrupted (exit trap), and when daemon-reload failed after writing it.
- --dir with a trailing slash no longer puts the temporary clone inside
the directory it replaces.
- The template's repository uses Nix's git when SteamOS has none, so the
template marker exists there too (--clone needs it).
- A failed Nix uninstall during the reinstall of a broken Nix says so.
- clone_config: one branch per case; shorter comments, help and docs.
- Tests: an interrupted uninstall, --dir with a trailing slash; a
redundant "used as it is" case dropped.
README: what --clone does for a private repository (the template's
gh/store helpers, the gh auth login offer, keep those lines in your
config, what gets cloned into and that re-running continues), the
git/gh lines in the usage example, and that uninstall no longer waits
for programs from the Nix store. docs/cleanup.md: the clone steps, the
untouched-template marker, and the LazyUnmount= drop-in.
The template now enables git (SteamOS's own, package = null; Home
Manager writes its config) with the GitHub CLI's credential helper for
github.com and `store` (~/.git-credentials) for other hosts.
Without a Home Manager configuration, `install --clone` first creates
and activates the template in the target directory, then clones next to
it with git's helpers and GIT_TERMINAL_PROMPT=0 (never a password
prompt). If that fails with a terminal, it offers `gh auth login` and
retries once; otherwise the template stays active and the message says
how to continue. After the clone the template is removed, the clone
takes its place and Home Manager switches to it.
Only a missing (or empty) target or the untouched template is cloned
into: create_config marks its configuration with the hash of its files
in .git/steam-frame-nix-template. Anything else there is used as it is,
so a rerun continues where a run stopped (after a failed switch it just
switches); Nix and the template switch (helpers present) are skipped
when already done. The origin comparison and the pull are gone.
Programs started from the Nix store (the Steam session itself, the
desktop portal) keep /nix busy until logout, so nix-installer's
`systemctl stop nix.mount` failed and the wait for them could never end.
A runtime drop-in (LazyUnmount=yes on nix.mount, in /run, removed again
afterwards) makes that stop detach /nix; the programs keep their open
files until they exit. They are listed for information only, without a
prompt. The re-exec of a bash from the Nix store is no longer needed.
- uninstall: nix-installer's copy outside /nix is made and run as root
(a user-writable copy run by sudo could be swapped); README uninstall
paragraph shortened to one account of what happens when Nix stays.
- session.nix: the restart-check activation after steamFrameUserServices,
so the latter's comment is above it again.
- install.sh: a duplicate `local` in port_listening; comments.
- docs/cleanup.md: the installer internals of --clone (how an existing
clone is recognised, which git) and restart-check (what it compares,
test overrides); README keeps the usage.
- README install paragraph: shorter list of the dashboard patches.
Examples showed specific apps as if the repository installed or
configured them.
- Docs, README, template and option examples: the Signal Flatpak
(org.signal.Signal, sgnl:// and signalcaptcha://) and a made-up
org.example.App instead of the previous chat and remote-desktop apps;
no install lines (the app is installed by the user, as noted).
- Portal fix: the file-dialog symptom phrased generically.
- Launcher check: made-up Flatpak entries org.example.Chat (Electron,
--file-forwarding @@u %U @@, an action, an SSO scheme) and
org.example.Remote (Qt, -qwindowtitle %c @@u %u @@, localized keys)
replace the copied ones; Firefox, gedit and Jellyfin stay.
nix-installer uninstall failed at `systemctl stop nix.mount` ("Job
failed") while programs started from the Nix store still ran: a terminal
session's tools, or apps that mapped Home Manager's mime.cache.
- Before nix-installer runs, after Home Manager is gone, uninstall scans
/proc for the user's processes whose exe, cwd, root, an fd or a mapped
file is in /nix, and lists them by name and PID (the shells it was
started from included; itself, its subshells and its curl | bash
pipeline skipped). Close them and press Enter to re-check, or abort;
with --yes or without a terminal it stops: "close these or reboot, then
run uninstall again". Nothing is killed (replaces the old kill prompt).
- nix-installer runs from a copy outside /nix.
- cleanup check H: a fake /proc (STEAM_FRAME_NIX_PROC) with programs from
the store stops before Nix; without them Nix is removed.
Clones your own config repository (git@host:owner/repo, https://...,
github:owner/repo) into ~/nix-config or --dir and installs it like
--flake <dir>. An existing clone of the same repository (any URL form) is
reused and, after asking, pulled with --ff-only; another repository, a
non-clone or a different branch is refused. A failed clone hints at SSH
URLs and gh auth login. Uses SteamOS' git, else Nix's.
Checked against local bare repositories through a logging git.
A fresh install into a running session left the keyboard layout and the
SteamVR dashboard patches (VR pet, the VR keyboard's suggestion strip, ...)
silently off until a reboot: gamescope reads XKB_DEFAULT_* only at its
start, and SteamVR opens its DevTools port (VRWebHelper.DebuggerEnabled)
only at its start. Neither can be applied at runtime.
- install.sh restart-check (run on every switch by session.nix, and by
install at its end): compares the keyboard-layout drop-in with the
running gamescope session's environment and checks whether SteamVR runs
without port 8087; install ends with "Restart once" listing them.
- uninstall: a failing nix-installer uninstall (e.g. /nix busy) no longer
aborts the script before the ~/.config/home-manager link and Home
Manager state are removed; it says to reboot and run uninstall again.
- cleanup check: restart-check on fake cgroup/proc dirs.
The Nix-package launcher example in docs and option examples is now
Signal (pkgs.signal-desktop, desktop ID "signal", sgnl:// and
signalcaptcha:// handlers). The check uses a made-up org.example.App
from a fake package (fake store path), covering the same Exec, action,
MimeType, source and missing-entry cases.
Screenshots: placeholder Steam account IDs in the docs, option example
and check.
The module list gains vr-keyboard-controllers and vr-keyboard-touch; the
removed-options table gains the list form of launcherMenu.iconFallbacks,
windowCurvature.snap and barDragRoom; the intro counts the icon fallbacks
among the defaults; the swipe feature line names two-handed swipe and
functionKeys; the VR keyboard rows give the ranges the types enforce.
The Toon Cat (sources/toon-cat/), the Tuxedo Cat glTF (sources/tuxedo-cat/)
and the Quaternius Shiba Inu and Fox (models/{shiba,fox}/model.glb), each
byte-identical to the previously fetched file and with a LICENSE.md
(author, original URL, licence, changes). The build no longer downloads
them; three.js (preview only) still comes from npm. The baked frames,
model dirs and icons are unchanged.
docs/pet.md (usage, configuration, how it works), docs/pet-models.md
(the model spec), the README's feature line, options, changes outside
Nix and Credits (Toon Cat FREE and Tuxedo Cat, CC-BY 4.0; Quaternius
Shiba Inu and Fox, CC0), the cleanup artifact, the layout and runtime
names, and the template.
A SteamVR dashboard patch (vr-pet) drawing a baked 3D pet next to the
windows: the Toon Cat in five coats, a Shiba Inu, a Fox and a Dachshund,
plus models from steamFrame.pet.extraModels. It walks around, follows,
sits, lies and sleeps, can be picked up by its grip bar, petted and
switched in its menu; its spot, pose and model are saved state.
Also the vr-pet command, "Pet" in the "+" menu with the current model's
icon (steam-frame-nix-pet-icon), the flake outputs pet-models,
pet-icons and pet-preview, and the check pet. A built-in model with
"private": true fails evaluation; private models belong in extraModels.
<runtimeDir>/steam-frame-nix/vr-pet: icon.png when it links to a
*-vr-pet-icons store icon, its empty .lock and stray .icon.tmp.* links,
then the directory; kept by --orphans --keep pet. The empty runtime
directory now also goes with --orphans.
The controller bridge reads the poses with setTimeout instead of a fixed
11 ms interval: the next read after (distance - 10 cm) / 2.5 m/s, 11-250 ms,
the distance being the nearest tip's to the keyboard's rect plus a margin,
so a hand up to 2.5 m/s is read within 10 cm before it reaches the surface
(the tracker's crossing and 8 cm jump guard see 11 ms steps as before).
Full rate during a demand or with a pulled trigger. Without touch typing
(controllers.continuous, set by vr-keyboard-touch) no reads while the
keyboard is shown until a swipe demands them; a demand starting reads at
once. Bridge VERSION 6. Tests with a fake clock: bridge.test.mjs.
debugger_ensure_hook's "changed" status was never read; clean_icons'
case for Home Manager's links did nothing; cmd_cleanup computes --all
once. --quiet in the usage synopsis.
grep's read error (status 2) was swallowed with || true, so the profile's
prefs.js could be rewritten with nothing. Now it warns and keeps both
prefs.js and user.js for the next run.
c_write was fed through a pipe, so it ran in a subshell: its action
count and the printed header were lost, which printed "nothing to clean
up" after a rewrite, and a second header with --quiet. It takes the
content as an argument now.
ff_in_use piped find into grep -q; with pipefail, find's error on any
unreadable /proc/<pid>/fd (root's processes) made every profile look
unused, so cleanup could remove user.js and rewrite prefs.js under a
running Firefox. The Nix check's sandbox has no such processes.
find.keyboardPopup() (finders.js VERSION 3) replaces the same
g_PopupManager lookup in the swipe, extra keys and touch typing patches
(VERSIONs 29, 24, 4). hub.js keeps its own: it gets no finder library.
Every executionContextCreated (Runtime.enable alone reports each existing
context) started its own resync timer; one debounced timer now, as the
injectors do.
textmodel's lastReset (the patch logs the reason itself), __sfuiSwipe.model,
corrector's distance/fold and the decoder's N/W/cost/resample exports were
read by nothing (patch, tests, replay script).
Its 0.5 s poll (a SharedJSContext timer) kept running until the next
injection and could publish a hidden strip with its own sequence numbers
over the new popup's, so a pick on the panel was dropped as stale. The
poll now detaches it once the popup's document is gone.
VRKBD_VERBOSE and VRKBD_DISPLAY were undocumented; the extra keys section
gets a Debugging line like the others. That the routing is harmless on
other keymaps was said twice; now once, under Layouts.
A CDP call sent after the socket closed (e.g. Steam restarting between
Runtime.enable and the first inject) waited forever, so the helper hung
instead of reconnecting. Such calls now resolve empty at once.
down:/up: were checked with MODKEY[arg], which inherited names like
constructor or toString pass (xdotool then got a junk key name). The check
is now allowedMod() in allowlist.mjs, covered by its test.
The attach handler set the 15 s interval after its awaits even when the
socket had closed meanwhile (onclose already ran), leaking a timer per
such session. Also documents the optional stateDir config key.
- docs/window-curvature.md holds the full contract (now also: the next
press starts at 1x, return values, a drag keeps its value, neither side
restores the other's state); the patch headers of window-curvature and
frame-controls point to it and keep only their own side.
- frame-controls header: the localStorage history points to
docs/ui-patches.md#persistent-state.
Comments only, no VERSION bumps.
The Float action's import alias (l.yWq) and the frame controls' local
names (p, v) change with every SteamVR build and would warn after each
update; match the stable parts only.
The patch list, keyring summary, triggers and icon fallback history are
in docs/launchers.md, docs/launcher-menu.md and next to the code they
describe.